已解决:非常抱歉,我错误地重构了路径。我以为closedSet只有从起点到终点的所有航点,但它还有其他航点。我误解了这个概念。现在它可以正常工作了!
我仍然在使用A*算法时遇到一些问题。
我的角色正在寻找他的路径,但有时候,根据我在地图上点击的位置不同,算法会找到最短路径或路径,但选择了许多不应该选择的节点。
我尝试遵循维基百科和A* Pathfinding for Beginner's的实现,但它们给我相同的结果。我不知道是启发式函数还是算法本身有问题,但肯定有问题。
这是两个不同节点的单击问题示例:http://i.imgur.com/gtgxi.jpg
这是Pathfind类:
import java.util.ArrayList;
import java.util.Collections;
import java.util.TreeSet;
public class Pathfind {
public Pathfind(){
}
public ArrayList<Node> findPath(Node start, Node end, ArrayList<Node> nodes){
ArrayList<Node> openSet = new ArrayList<Node>();
ArrayList<Node> closedSet = new ArrayList<Node>();
Node current;
openSet.add(start);
while(openSet.size() > 0){
current = openSet.get(0);
current.setH_cost(ManhattanDistance(current, end));
if(start == end) return null;
else if(closedSet.contains(end)){
System.out.println("Path found!");
return closedSet;
}
openSet.remove(current);
closedSet.add(current);
for(Node n : current.getNeigbours()){
if(!closedSet.contains(n)){
if(!openSet.contains(n) || (n.getG_cost() < (current.getG_cost()+10))){
n.setParent(current);
n.setG_cost(current.getG_cost()+10);
n.setH_cost(ManhattanDistance(n, end));
if(!openSet.contains(n))
openSet.add(n);
Collections.sort(openSet);
}
}
}
}
return null;
}
private int ManhattanDistance(Node start, Node end){
int cost = start.getPenalty();
int fromX = start.x, fromY = start.y;
int toX = end.x, toY = end.y;
return cost * (Math.abs(fromX - toX) + Math.abs(fromY - toY));
}
}
closedSet
选择为ArrayList
不够高效。每个contains()
操作都是O(n)
(其中n
是关闭节点的数量)。您应该使用一个Set
来获得更好的性能 -HashSet
是一个明智的选择,如果您想保持插入顺序 - 您应该使用LinkedHashSet
。(请注意,您将需要重写Node
的equals()
和hashCode()
方法) - amit