Z机智的形象... F成本没关系吗?
我找到了路径,但没有找到最短的路径。我认为我的PriorityQueue顺序不正确,或者只是重建路径不好。无法解决。我是用Wiki伪代码和一些youtube视频制作的。我试图调试它。有时,“优先级”队列的顺序是错误的。我试图通过删除来重新排序,并读如下。它总会找到一条路径,但有时却为它选择较高的f值节点。
我发现了一些问题:如果我运行寻路方法10次,它会给出理想的结果。 (也许取决于邻居数?)我通过鼠标右键单击来进行寻路,然后将鼠标右键设置为false,因此单击鼠标时它将运行1次。我删除了那个错误的开关,当鼠标右键按下时,如果保持右键,它会提供完美的效果。现在,我必须运行寻路10次才能得到完美的结果:
//A* path finding by right click
if (handler.isMouseright()==true) {
if (selected==true) {
handler.setMouseright(false);
//A star path finding:
for (int j=0;j<10;j++) {
aStar = new AStar((int)x/Game.tilesize,(int)y/Game.tilesize,(int)MouseInput.mx/Game.tilesize,(int)MouseInput.my/Game.tilesize);
path=aStar.findPath();
}
//aStar = null;
}
}
public class AStar {
public Node[][] searchArea;
public PriorityQueue<Node> openList;
public ArrayList<Node> closedList;
public ArrayList<Node> neighbourList;
public Node startNode;
public Node endNode;
public Node currentNode;
public Node parentNode;
public AStar(int startNodeX,int startNodeY, int endNodeX,int endNodeY) {
this.searchArea=Game.Nodes.clone();
this.startNode=searchArea[startNodeX][startNodeY];
this.endNode=searchArea[endNodeX][endNodeY];
this.openList = new PriorityQueue<Node>(new Comparator<Node>() {
@Override
public int compare(Node node0, Node node1) {
return Integer.compare(node0.getF(), node1.getF());
}
});
this.closedList = new ArrayList<Node>();
this.neighbourList = new ArrayList<Node>();
}
public ArrayList<Node> findPath() {
ArrayList<Node> path = new ArrayList<Node>();
int tentativeG;
startNode.setG(0);
startNode.calculateH(endNode);
startNode.calculateF();
openList.add(startNode);
while(!openList.isEmpty()) {
currentNode=openList.poll();
closedList.add(currentNode);
if (currentNode.getX()==endNode.getX() && currentNode.getY()==endNode.getY()) {
//path found!
path=getPath(currentNode);
System.out.println("Path found!");
return path;
} else {
//search neighbours
//neighbours:
//(x-1,y-1) (x0,y-1) (x+1,y-1)
//(x-1,y0) (x0,y0) (x+1,y0)
//(x-1,y+1) (x0,y+1) (x+1,y+1)
if (neighbourList.isEmpty()==false) neighbourList.clear();
//+map bounds check
//upper row---------------------------------------------------------------------------------------------------------------------------------------
if (currentNode.getX() > 0 && currentNode.getY() > 0) neighbourList.add(searchArea[currentNode.getX()-1][currentNode.getY()-1]);
if (currentNode.getY() > 0) neighbourList.add(searchArea[currentNode.getX()][currentNode.getY()-1]);
if (currentNode.getX() < Game.tiles && currentNode.getY() > 0) neighbourList.add(searchArea[currentNode.getX()+1][currentNode.getY()-1]);
//middle row--------------------------------------------------------------------------------------------------------------------------------------
if (currentNode.getX() > 0) neighbourList.add(searchArea[currentNode.getX()-1][currentNode.getY()]);
if (currentNode.getX() < Game.tiles) neighbourList.add(searchArea[currentNode.getX()+1][currentNode.getY()]);
//lower row---------------------------------------------------------------------------------------------------------------------------------------
if (currentNode.getX() > 0 && currentNode.getY() < Game.tiles) neighbourList.add(searchArea[currentNode.getX()-1][currentNode.getY()+1]);
if (currentNode.getY() < Game.tiles) neighbourList.add(searchArea[currentNode.getX()][currentNode.getY()+1]);
if (currentNode.getX() < Game.tiles && currentNode.getY() < Game.tiles) neighbourList.add(searchArea[currentNode.getX()+1][currentNode.getY()+1]);
for (Node neighbour : neighbourList) {
if (neighbour.isBlock==true || closedList.contains(neighbour)) continue;
currentNode.calculateG(startNode);
//tentative_gScore := gScore[current] + dist_between(current, neighbor)
tentativeG=currentNode.getG()+calculateNodeDist(currentNode,neighbour);
if (tentativeG >= neighbour.getG() || openList.contains(neighbour)==false) {
neighbour.setParent(currentNode);
neighbour.setG(tentativeG);
neighbour.calculateH(endNode);
neighbour.calculateF();
if (openList.contains(neighbour)==false) {
openList.add(neighbour);
openList.remove(neighbour); //reorder array
openList.add(neighbour); //reorder array
}
}
}
}
}
return path;
}
public ArrayList<Node> getPath(Node currentNode) {
ArrayList<Node> path = new ArrayList<Node>();
path.add(currentNode);
Node parentNode;
while ((parentNode = currentNode.getParent()) != null && parentNode!=startNode) {
path.add(0, parentNode);
currentNode = parentNode;
}
return path;
}
public int calculateNodeDist(Node node1,Node node2) {
//this.g=Math.abs(startNode.yy - this.yy) + Math.abs(startNode.xx - this.xx);
int dst;
int dstX = Math.abs(node1.getX() - node2.getX());
int dstY = Math.abs(node1.getY() - node2.getY());
if (dstX > dstY) {
dst = 14*dstY + 10* (dstX-dstY);
} else {
dst = 14*dstX + 10 * (dstY-dstX);
}
return dst;
}
}
public class Node {
public int xx,yy;
public int h; //heuristic distance from endNode
public int g; //distance from startNode
public int f; //h+g
public boolean isBlock; //path blocker?
public Node parent; //the parent node. if algorithm founds a path it can trace back
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public Node(int xx, int yy) {
super();
this.xx = xx;
this.yy = yy;
}
public int getX() {
return xx;
}
public void setX(int xx) {
this.xx = xx;
}
public int getY() {
return yy;
}
public void set(int yy) {
this.yy = yy;
}
public void calculateH(Node endNode) {
//this.h = Math.abs(endNode.yy - this.yy) + Math.abs(endNode.xx - this.xx);
int dstX = Math.abs(this.getX() - endNode.getX());
int dstY = Math.abs(this.getY() - endNode.getY());
if (dstX > dstY) {
this.h = 14*dstY + 10* (dstX-dstY);
} else {
this.h = 14*dstX + 10 * (dstY-dstX);
}
}
public void calculateG(Node startNode) {
//this.g=Math.abs(startNode.yy - this.yy) + Math.abs(startNode.xx - this.xx);
int dstX = Math.abs(this.getX() - startNode.getX());
int dstY = Math.abs(this.getY() - startNode.getY());
if (dstX > dstY) {
this.g = 14*dstY + 10* (dstX-dstY);
} else {
this.g = 14*dstX + 10 * (dstY-dstX);
}
}
public void calculateF() {
int finalCost = getG() + getH();
this.setF(finalCost);
}
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
public int getG() {
return g;
}
public void setG(int map) {
this.g = map;
}
public int getF() {
return f;
}
public void setF(int finalCost) {
this.f = finalCost;
}
public boolean isBlock() {
return isBlock;
}
public void setBlock(boolean isBlock) {
this.isBlock = isBlock;
}
}
好的,我自己找到了解决方案。在寻路结束时,if语句是错误的:
for (Node neighbour : neighbourList) {
if (neighbour.isBlock==true) continue;
currentNode.calculateG(startNode);
tentativeG=currentNode.getG()+calculateNodeDist(currentNode,neighbour);
if (!openList.contains(neighbour) && !closedList.contains(neighbour) || tentativeG < neighbour.getG()) {
neighbour.setParent(currentNode);
neighbour.setG(tentativeG);
neighbour.calculateH(endNode);
neighbour.calculateF();
if (closedList.contains(neighbour)) closedList.remove(neighbour);
if (!openList.contains(neighbour)) openList.add(neighbour);
}
}