c++ - A*算法好像在兜圈子,我做错了什么?

标签 c++ a-star

<分区>

我为我正在制作的游戏编写了一个星形算法(我第一次使用它),但它无法找到超过一个方格的任何目标。我使用调试器查看发生了什么,它看起来确实有点像在兜圈子。这是我的算法(sx,sy 是起始图 block 坐标,tx,ty 是目标坐标。此外,此函数是类的一部分,以防您对 undefined variable 感到疑惑):

void Pathfinder(int sx, int sy, unsigned int tx, unsigned int ty, int map[7][11],std::map<array2,Door*> doors,int dv){
                if (!map[ty][tx] == 0){ return;}
                Node map_nodes [7][11];

                std::vector<Node*> open;
                int current_index, x, y, tile;
                path.clear();

                map_nodes[sy][sx].load(sx,sy,tx,ty,0, true, false,0,0);

                Node* current = &map_nodes[sy][sx];
                open.push_back(current);

                while (open.size() > 0) {
                    for (int b = 0; b < open.size(); ++b) {
                        if (b == 0 || open[b]->f < current->f) {
                            current = open[b];
                            current_index = b;
                        }
                    }
                    // checks if current is the target
                    if (current->x == tx && current->y == ty) {
                        int path_length = current->g + 1;
                        path.resize(path_length, {0, 0});

                        for (int p = 0; p < path_length; p++) {
                            path[p][0] = current->x;
                            path[p][1] = current->y;
                            current = &map_nodes[current->y][current->x];
                        }
                        return;
                    }

                    current->closed = true;
                    current->open = false;
                    open.erase(open.begin() + current_index);

                    for (int k = 0; k < 3; k++) {
                        for (int u = 0; u < 3; u++) {
                            if (k != 1 && u != 1) {
                                x = current->x + u - 1;
                                y = current->y + k - 1;
                                if (x >= 0 && y >= 0) {
                                    //checks if it is traversable
                                    if (map_nodes[y][x].closed || (map[y][x] == 0 || (map[y][x] >= dv && doors[{x, y}]->access_level <= acess_level))) {
                                        if (!map_nodes[y][x].open) {
                                            map_nodes[y][x].load(x, y, tx, ty, current->g + 1, true, false, current->x,current->y);
                                            open.push_back(&map_nodes[y][x]);
                                        } else if (current->g < map_nodes[y][x].g) {
                                            map_nodes[y][x].update_f(current->g, current->x,current->y);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

这是节点类:

class Node{
    public:
        int x = 0, y = 0, f = 0, g = 0, h = 0, px = 0, py = 0;
        bool open = false, closed = false;
        void load(int xa, int ya, int tx, int ty, unsigned int ga, bool opena, bool closeda, int pxa,int pya){
            x = xa;
            y = ya;

            g = ga;
            h = ((tx - x) * (tx - x)) + ((ty - y) * (ty - y));

            f = g + h;

            open = opena;
            closed = closeda;

            px = pxa;
            py = pya;
        }
        void update_f(unsigned int ga, int pxa, int pya){
            g = ga;
            f = g + h;
            px = pxa;
            py = pya;
        }
    };

编辑: 没关系修复它,有一个 if 命令缺少一个!这把事情搞砸了。

最佳答案

从一些 A* 伪代码开始,such as this在维基百科上。 (维基百科是著名算法伪代码的一个不错的来源,因为有足够多的随机人路过并修复最糟糕的拼写错误)

将其转录为评论。现在,留下注释,逐行写。

简单地丢弃一堆不工作的代码并询问“我做错了什么”需要有人首先弄清楚你的代码的每一行试图做什么(不假设它正在做某事合理),然后将其映射到他们习惯的 A* 实现,确定您正在做的事情实际上导致了您所看到的问题。

在每行旁边的注释中说明应该做什么,查找错误的问题就变得容易了 O(n);您可以发现一行未能按照评论所说的执行操作,或者您可以在评论中发现错误。

TL;DR“你做错了”是指使用低级 C 风格编程编写算法,并且没有返回到正式正确版本的算法,并期望它能够工作。

一般来说,当编写重要到足以拥有名称的算法时,您会希望能够引用伪代码描述来说明您应该做什么。简单地编写“做你认为应该做的事”的代码会使追踪问题变得非常非常困难。

这可能与您找到的实现此类算法的示例代码不一致;有时这是因为编写示例代码的人已经实现了该算法数十次,其他时候是因为他们删除了注释(之后或在编写代码时),或者因为他们有信心(并且足够幸运)这样做第一次就对了。

关于c++ - A*算法好像在兜圈子,我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54206347/

相关文章:

c++ - 如何转发声明 _com_ptr_t 指针?

c++ - 将 shared_lock 升级为独特的锁使用、时序和设计

c++ - C++中的动画

c++ - 确定推力的最大长度::device_vector

algorithm - 允许A-star算法绕过x个障碍物

java - A* 寻路问题处理(Java)

path-finding - 基于图 block 的 A* 寻路,但带有炸弹

c++ - 类中的全局和外部

algorithm - A* 如何搜索图表?

java - 关于leetcode 1091 二进制矩阵中的最短路径的问题