【问题标题】:Implementing A* pathfinding in a 2D array在二维数组中实现 A* 寻路
【发布时间】:2013-11-13 18:51:11
【问题描述】:

我正在制作一个 2D 瓦片地图,我现在正在尝试实现 A* 寻路。我正在关注the Wikipedia pseudocode for A*

除了算法做出的决策中出现一些奇怪的行为外,一切进展顺利。

到目前为止我的代码:

void Pathfinding(Point from, Point destination) {

    goalNode = new Node(destination, 0, 0);
    startNode = new Node(from, 0, ManhattanDistance(from, destination));

    open = new List<Node>();            //list of nodes
    closed = new List<Node>();
    open.Add(startNode);                //Add starting point

    while(open.Count > 0) {

        node = getBestNode();                   //Get node with lowest F value
        if(node.position == goalNode.position) {
            Debug.Log("Goal reached");
            getPath(node);
            break;
        }
        removeNode(node, open);
        closed.Add(node);

        List<Node> neighbors = getNeighbors(node);
        foreach(Node n in neighbors) {
            float g_score = node.G + 1;
            float h_score = ManhattanDistance(n.position, goalNode.position);
            float f_score = g_score + h_score;

            if(isValueInList(n, closed) && f_score >= n.F) 
                continue;

            if(!isValueInList(n, open) || f_score < n.F) {
                n.parent = node;
                n.G = g_score;
                n.G = h_score;
                if(!isValueInList(n, open)) {
                    map_data[n.position.x, n.position.y] = 4;
                    open.Add(n);
                }
            }
        }
    }
}

运行这段代码的结果:

蓝色是打开列表中的节点,绿色是选择到目标节点的路径。

解决方案:

void Pathfinding(Point from, Point destination) {

    goalNode = new Node(destination, 0, 0);
    startNode = new Node(from, 0, ManhattanDistance(from, destination));

    open = new List<Node>();            //list of nodes
    closed = new List<Node>();
    open.Add(startNode);                //Add starting point

    while(open.Count > 0) {

        node = getBestNode();                   //Get node with lowest F value
        if(node.position == goalNode.position) {
            Debug.Log("Goal reached");
            getPath(node);
            break;
        }
        removeNode(node, open);
        closed.Add(node);

        List<Node> neighbors = getNeighbors(node);
        foreach(Node n in neighbors) {
            float g_score = node.G + 1;
            float h_score = ManhattanDistance(n.position, goalNode.position);
            float f_score = g_score + h_score;

            if(isValueInList(n, closed) && f_score >= n.F) 
                continue;

            if(!isValueInList(n, open) || f_score < n.F) {
                n.parent = node;
                n.G = g_score;
                n.H = h_score;
                if(!isValueInList(n, open)) {
                    map_data[n.position.x, n.position.y] = 4;
                    open.Add(n);
                }
            }
        }
    }
}

【问题讨论】:

  • 什么奇怪的行为/选择?可视化看起来不错。
  • 我指的是它直线上升然后向左移动的事实。如果它向右扩展然后向上,不是更好吗?我一直认为 A* 总是会给出实现目标的最短路径。
  • 最好的 C# A* 实现可以在这里找到:blogs.msdn.com/b/ericlippert/archive/tags/astar
  • 您分配了两次 n.G 并且从不存储 f_score。当 f_score 较低时,您可能想用 f_score 覆盖 n.F。
  • 看起来 Eric Lippert c# MSDN 博客早已死去。这是一台 Wayback 机器 archive of it

标签: c# algorithm search artificial-intelligence a-star


【解决方案1】:

首先,您打开的节点应该按降序排序,而在您的代码中 - 没有排序。您计算距离 (g) 和启发式 (h) 但从未实际使用它。您应该考虑使用 有序容器 而不是列表(因为在每次迭代中排序列表效率不高)

其次,你不要将节点中的启发式值存储为

n.G = h_score;

应该是

n.H = h_score;

【讨论】:

    猜你喜欢
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    相关资源
    最近更新 更多