我已经写了一个A *算法来找到从敌人到玩家的最短路径(敌人只能在4个基本方向上移动),但是,只有起始单元格和周围的4个单元格被添加到打开列表,然后算法停止。如果有人可以查看我的代码来找到我可能错过的东西,那将是值得赞赏的。谢谢! 作为参考,放在打开列表中的单元格在图片中显示为红色: http://imgur.com/a/sMbzL
主要搜索类:
import acm.util.*;
import java.awt.*;
import java.util.*;
/**
* searches to find the shortest path between two points
*
* @author Garrett Rademacher
* @version 1.0
*/
public class AStarMain
{
// instance variables
private ArrayList<AStarCell> open = new ArrayList<AStarCell>(); //list of open cells
private ArrayList<AStarCell> closed = new ArrayList<AStarCell>();//list of closed cells
public ArrayList<Character> path = new ArrayList<Character>(); //will hold the path once found
public static AStarCell[][] grid = new AStarCell[25][25]; //grid of cells
private int startRow, startCol; //staring point for the search
private int endRow, endCol; //destination
private boolean pathFound = false;
private AStarCell current; //current cell
private HackNSlashMain game;
public AStarMain(int startRow, int startCol, int endRow, int endCol, HackNSlashMain game){
//save passed data
this.startRow = startRow;
this.startCol = startCol;
this.endRow = endRow;
this.endCol = endCol;
this.game = game;
//populate grid
populateGrid();
//start main pathfinding method
open.add(0, grid[startRow][startCol]); //add the starting cell to the open list
current = grid[startRow][startCol]; //set the current cell to the starting cell
//use a while loop to search for a path
while(!pathFound && open.size()>0){
//loop through the open array list, find the cell with the lowest cost
for(int i = 0; i < open.size(); i++){
if(open.get(i).getFCost() < current.getFCost() && open.get(i).getFCost() != 0){
current = open.get(i);
}
game.cell[open.get(i).getRow()][open.get(i).getCol()].colorRed();
}
//remove the found cell from the open list
open.remove(current);
//add the cell to the closed list
closed.add(current);
//check if a path has been found
if(current.getRow() == endRow && current.getCol() == endCol){
pathFound = true;
constructPath();
}
//consider each vertical and horizontal neighbor of the current cell
//check if in bounds of array of cells
if(checkInBounds(current.getRow()-1, current.getCol())){
consider(grid[current.getRow()-1][current.getCol()]);
}
if(checkInBounds(current.getRow()+1, current.getCol())){
consider(grid[current.getRow()+1][current.getCol()]);
}
if(checkInBounds(current.getRow(), current.getCol()-1)){
consider(grid[current.getRow()][current.getCol()-1]);
}
if(checkInBounds(current.getRow(), current.getCol()+1)){
consider(grid[current.getRow()][current.getCol()+1]);
}
}
}
private void consider(AStarCell passedCell){
//if the neighbor cell is not passable or is already on the closed list, skip it
if(!passedCell.getIsPassable() || closed.contains(passedCell)){
return;
}
//calculate the h cost of the cell
int heuristic = (Math.abs(endRow-passedCell.getRow()) + Math.abs(endCol-passedCell.getCol()));
passedCell.setHCost(heuristic);
//calculate the g cost (add one to the g cost of the current cell)
int holdingGCost = current.getGCost() + 1;
//if the cell has not been touched before, or if accesing the cell via current is a shorter route
if(passedCell.getGCost() > holdingGCost || !(passedCell.getGCost() == 0)){
//set the gCost
passedCell.setGCost(holdingGCost);
//set the f cost to gCost + hCost
passedCell.calcFCost();
//set the parent cell of passedCell to current cell
passedCell.setParent(current);
}
//if the passedCell does not exist in the open list
if(!(open.contains(passedCell))){
//add passedCell to open
open.add(passedCell);
}
}
private boolean checkInBounds(int row, int col){
if(row > -1 && row < 25 && col > -1 && col < 25){return true;} //cell is in bounds
else{return false;}//cell is out of bounds
}
private void constructPath(){
//once a path has been found, trace it backwards adding each step to the path ArrayList
//start at the end cell,
AStarCell currentCell = grid[endRow][endCol];
AStarCell parentCell;
while(!(currentCell.getRow() == startRow) && !(currentCell.getCol() == startCol)){
parentCell = currentCell.getParent(); //get the parent cell
if((parentCell.getRow()) < (currentCell.getRow())){
//add move up
Character character = new Character('U');
path.add(0,character);
}else if((parentCell.getRow()) > (currentCell.getRow())){
//add move down
Character character = new Character('D');
path.add(0,character);
}else if((parentCell.getCol()) > (currentCell.getCol())){
//add move left
Character character = new Character('L');
path.add(0,character);
}else if((parentCell.getCol()) < (currentCell.getCol())){
//add move right
Character character = new Character('R');
path.add(0,character);
}
currentCell = parentCell;//update the current cell so the path traces backwards
}
}
public Character getMove(){
return path.get(0);
}
private void populateGrid(){
for(int i = 0; i < 25; i++){
for(int j = 0; j < 25; j++){
AStarCell cell = new AStarCell(i,j);
grid[i][j] = cell;
cell.setPassable(game.cell[i][j].getIsPassable());
}
}
}
}
细胞类:
public class AStarCell
{
// instance variables
private int hCost = 0;
private int gCost = 0;
private int fCost = 0; //G+H
private int row, col; //location in grid of cells
private AStarCell parent; //parent cell
private boolean isPassable = true;
AStarCell(int row, int col){
this.row = row;
this.col = col;
}
public void setGCost(int gCost){
this.gCost = gCost;
}
public void setHCost(int hCost){
this.hCost = hCost;
}
public void calcFCost(){
fCost = gCost + hCost;
}
public void setParent(AStarCell parentCell){
this.parent = parentCell;
}
public void setPassable(boolean isPassable){
this.isPassable = isPassable;
}
public int getGCost(){
return this.gCost;
}
public int getFCost(){
return fCost;
}
public boolean getIsPassable(){
return isPassable;
}
public int getCol(){
return col;
}
public int getRow(){
return row;
}
public AStarCell getParent(){
return this.parent;
}
}
我也在使用ACM库,如果这有助于消除任何混淆。