我基于维基百科页面link to page上的伪代码为A *实现了这个算法,但它找不到任何路径。当我使用它时,我永远不会到达当前节点等于目标的点。我认为它可能与我的启发式或我初始化f和g分数的方式有关,但我似乎无法弄明白。
我正在使用的地图大小是1920 x 1080,并使用30的单元格大小。
private ArrayList<Vector2> aStar(Vector2 start, Vector2 goal) {
HashSet<Vector2> closedSet = new HashSet<Vector2>();
ArrayList<Vector2> openSet = new ArrayList<Vector2>();
openSet.add(start);
HashMap<Vector2,Vector2> cameFrom = new HashMap<Vector2, Vector2>();
HashMap<Vector2,Float> gScore = new HashMap<Vector2, Float>();
HashMap<Vector2,Float> fScore = new HashMap<Vector2, Float>();
ArrayList<Vector2> neighbors = new ArrayList<Vector2>();
neighbors.add(new Vector2(0,30));
neighbors.add(new Vector2(0,-30));
neighbors.add(new Vector2(30,0));
neighbors.add(new Vector2(-30,0));
for(int i = 0; i < 1920; i +=30){
for(int j = 0; j < 1080; j +=30){
gScore.put(new Vector2(i,j),Float.MAX_VALUE);
fScore.put(new Vector2(i,j),Float.MAX_VALUE);
}
}
gScore.put(start,0f);
fScore.put(start,heuristic(start,goal));
while(!openSet.isEmpty()){
int low = 0;
for(int i = 0; i < openSet.size(); i++){
if(fScore.get(openSet.get(i))<fScore.get(openSet.get(low))){
low = i;
}
}
Vector2 current = openSet.get(low);
if(current.equals(goal)){
System.out.println("YES!");
return null;
}
openSet.remove(current);
closedSet.add(current);
for(Vector2 neighbor:neighbors){
Vector2 tst = new Vector2(neighbor.x + current.x,neighbor.y + current.y);
if(tst.x > -30 && tst.x <1920 && tst.y > -30 && tst.y < 1080){
neighbor.add(current);
if(closedSet.contains(neighbor)){
continue;
}
if(!openSet.contains(neighbor)){
openSet.add(neighbor);
}
float tentative_gScore = gScore.get(current) + heuristic(current,neighbor);
if(tentative_gScore >= gScore.get(neighbor)){
continue;
}
cameFrom.put(neighbor,current);
gScore.put(neighbor,tentative_gScore);
fScore.put(neighbor,gScore.get(neighbor)+heuristic(neighbor,goal));
}
}
}
return null;
}
private float heuristic(Vector2 begin, Vector2 end) {
return (Math.abs(begin.x - end.x) + Math.abs(begin.y - end.y)) ;
}
答案 0 :(得分:0)
行neighbor.add(current);
更改了邻居。不仅如此,而且您存储了该邻居,这意味着将保留此对象引用,并且可能在将来的代码中进一步失真。
另一个问题是你的启发式问题。您正在使用曼哈顿距离,这意味着存在大量具有相同距离的路径(只要您永远不会离开目标节点,每条路径的距离都相同)。尝试允许对角线邻居,并使用欧几里德距离而不是曼哈顿距离。
答案 1 :(得分:0)
在所有代码中都很难找到错误。我会尝试,但我认为解决这个问题的更好方法会对你有帮助。
考虑创建一个名为Node
的类,对于每个Node n,它具有以下项目:
然后是递归解的伪代码:
search_a_star(frontier)
if(frontier.isEmpty())
return false
//Select node with lower f(n) + g(n)
node = selectNode(frontier)
if node is goal then
return node //You have in the node the cost and the path
else
//Generate the neighbours of your current node. You should calculate the heuristing of each neighbour.
neighbours = generateNeighbours(node)
//Add neighbours to reducedFrontier
reducedFrontier = frontier - node
newFrontier = add(reducedFrontier, neighbours)
search_a_star(newFrontier)
您应该保留一组可访问的节点。此外,当您生成邻居时,您应该考虑这种情况进行循环控制: