A-Star Pathfinding选择不好的航路点

时间:2012-09-14 03:59:02

标签: java algorithm path-finding a-star heuristics


已解决:对不起。我正在重建不正确的道路。我认为closedSet只有从开始到结束的所有航点,但它也有其他一些航路点。我想念这个概念。现在它正在发挥作用!


我仍然遇到A *的麻烦。

我的角色正在寻找他的路径,但有时候,根据我在地图上点击的位置,算法会找到最短的路径或路径,但是有许多节点不应该被选中。

我尝试按照 Wikipedia的 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));
}

}

2 个答案:

答案 0 :(得分:1)

我认为错误与条件有关:

if(n.getCost() < current.getCost()){

如果成本(g(node)+h(node))从当前开始减少,则不应阻止前进。看一下这个反例:(S是源,T是目标)

_________
|S |x1|x2|
----------
|x3|x4|x5|
---------
|x6|x7|T |
----------

现在,假设你在S,你还没有移动g(S) =0,并且在曼哈顿距离启发式下h(S) = 4,所以你得到f(S)=4

现在,看看x1,x3:假设您向每个人迈出了一步,他们将拥有g(x1)=g(x3)=1,并且两者都会在同一启发式下拥有h(x1)=h(x3)=3。这将导致f(x1)=f(x3)=4 - 并且您的if条件将导致无法“打开”,因此一旦您完成对S的迭代 - 您将不会向open推送任何内容 - 并且您的搜索将会终止。


作为旁注:
我认为选择closedSetArrayList效率不高。每个contains()操作都是O(n)(其中n是已关闭节点的数量)。您应该使用Set来获得更好的效果 - HashSet是明智的选择,如果您想维持插入顺序,则应使用LinkedHashSet。 (请注意,您必须覆盖equals()的{​​{1}}和hashCode()方法

答案 1 :(得分:0)

您的单位是仅向上/向下/向左/向右走,还是也可以对角线走路?

A *启发式的一个要求是它admissible - 它绝不能超过 - 估计实际的路径长度。如果你的单位可以对角行走,那么manhatten-distance会高估路径长度,因此A *不能保证工作。