I'm trying to find the shortest path between two locations in a 2D array with only horizontal and vertical moves allowed (Manhattan distance).
I've tried to convert the pseudocode from Wikipedia's article on the A star algorithm (http://en.wikipedia.org/wiki/A_star) into Java, but it doesn't work. Note: the game works properly using a recursive path-finding algorithm that doesn't guarantee a shortest path, so the bug must be here.
Can anyone please tell me what I'm doing wrong?
/ A* algorithm wikipedia
public ArrayList<OrderedCoordinatePair> aStar(int irow, int icol, int frow,
int fcol) {
// The set of nodes already evaluated.
closedSet = new ArrayList<OrderedCoordinatePair>();
// The set of tentative nodes to be evaluated.
openSet = new ArrayList<OrderedCoordinatePair>();
openSet.add(allCells[irow][icol]);
// Distance from start along optimal path.
gScore = new int[NUMROWS][NUMCOLS];
gScore[irow][icol] = 0;
// heuristic estimate of distance from start to goal
hScore = new int[NUMROWS][NUMCOLS];
hScore[irow][icol] = Math.abs(frow - irow) + Math.abs(fcol - icol);
// Estimated total distance from start to goal through y.
fScore = new int[NUMROWS][NUMCOLS];
fScore[irow][icol] = hScore[irow][icol];
while (!openSet.isEmpty()) {
// x := the node in openset having the lowest f_score[] value
currentNode = openSet.get(0);
for (int i = 0; i < openSet.size(); i++) {
if (fScore[openSet.get(i).getRowNum()][openSet.get(i)
.getColNum()] < fScore[currentNode.getRowNum()][currentNode
.getColNum()]) {
currentNode = openSet.get(i);
}
}
if (currentNode.getRowNum() == frow
&& currentNode.getColNum() == fcol) {
shortestPath.clear();
resetParentNodes();
return reconstructPath(irow, icol, frow, fcol);
}
openSet.remove(currentNode);
closedSet.add(currentNode);
for (int i = 0; i < 8; i++) {
switch (i) {
case 0:
neighborRow = currentNode.getRowNum() - 1;
neighborCol = currentNode.getColNum();
break;
case 1:
neighborRow = currentNode.getRowNum();
neighborCol = currentNode.getColNum() - 1;
break;
case 2:
neighborRow = currentNode.getRowNum();
neighborCol = currentNode.getColNum() + 1;
break;
case 3:
neighborRow = currentNode.getRowNum() + 1;
neighborCol = currentNode.getColNum();
break;
}
if (isValidCell(neighborRow, neighborCol) && allCells[neighborRow][neighborCol].getColor() == 0) {
currentNodeNeighbor = allCells[neighborRow][neighborCol];
if (closedSet.contains(currentNodeNeighbor)) {
// 1 is distance between currentNode & currentNodeNeighbor
tentativegScore = gScore[currentNode.getRowNum()][currentNode
.getColNum()] + 1;
tentativeIsBetter = false;
if (!openSet.contains(currentNodeNeighbor)) {
openSet.add(currentNodeNeighbor);
hScore[neighborRow][neighborCol] = Math.abs(frow
- neighborRow)
+ Math.abs(fcol - neighborCol);
tentativeIsBetter = true;
} else if (tentativegScore < gScore[neighborRow][neighborCol]) {
tentativeIsBetter = true;
}
if (tentativeIsBetter == true) {
allCells[neighborRow][neighborCol].setParentNode(
currentNode.getRowNum(), currentNode
.getColNum());
gScore[neighborRow][neighborCol] = tentativegScore;
fScore[neighborRow][neighborCol] = gScore[neighborRow][neighborCol]
+ hScore[neighborRow][neighborCol];
}
}
}
}
}
return new ArrayList<OrderedCoordinatePair>();
}
ArrayList<OrderedCoordinatePair> reconstructPath(int initialRow,
int initialCol, int finalRow, int finalCol) {
int currentRow = finalRow;
int currentCol = finalCol;
int tempRow = currentRow;
int tempCol = currentCol;
while (currentRow != initialRow && currentCol != initialCol) {
shortestPath.add(allCells[currentRow][currentCol]);
tempRow = currentRow;
tempCol = currentCol;
currentRow = allCells[tempRow][tempCol].getRowNum();
currentCol = allCells[tempRow][tempCol].getColNum();
}
return shortestPath;
}