简体   繁体   中英

C++ A* Pathfinding causes infinite loop

I'm really new to this kind of thing and used this tutorial to write my code.

Basically, calling my function causes my code to crash, the obvious problem would be that I'm causing an infinite loop, but I can't see it.

Take a look:

std::vector<Vector2> TileMap::pathFind(Vector2 pathStart, Vector2 pathEnd){
    struct Node{
        Vector2 pos;
        int f;
        inline Node operator=(Node a){
            pos = a.pos;
            f = a.f;
        }
    };
    std::vector<Node> openList;
    std::vector<Vector2> closedList;
    closedList.push_back(pathStart);

    Vector2 currentNode = pathStart;
    do{
        if(currentNode.x - 1 >= 0){ //NORTH
            Node node;
            node.pos = Vector2(currentNode.x-1, currentNode.y);
            node.f = 1 + (std::abs(pathEnd.x - node.pos.x)+std::abs(pathEnd.y - node.pos.y));
            openList.push_back(node);
        }
        if(currentNode.x + 1 <= MAP_WIDTH){ //SOUTH
            Node node;
            node.pos = Vector2(currentNode.x+1, currentNode.y);
            node.f = 1 + (std::abs(pathEnd.x - node.pos.x)+std::abs(pathEnd.y - node.pos.y));
            openList.push_back(node);
        }
        if(currentNode.y - 1 >= 0){ //WEST
            Node node;
            node.pos = Vector2(currentNode.x, currentNode.y-1);
            node.f = 1 + (std::abs(pathEnd.x - node.pos.x)+std::abs(pathEnd.y - node.pos.y));
            openList.push_back(node);
        }
        if(currentNode.y + 1 <= MAP_HEIGHT){ //EAST
            Node node;
            node.pos = Vector2(currentNode.x, currentNode.y+1);
            node.f = 1 + (std::abs(pathEnd.x - node.pos.x)+std::abs(pathEnd.y - node.pos.y));
            openList.push_back(node);
        }//step 2 now

        if(!(openList.empty())){
            Node minimum = openList[0];
            int num = 0;
            for(auto i : openList){
                num++;
                if(minimum.f > i.f){
                    minimum = i;
                }
            }
            currentNode = minimum.pos;
            closedList.push_back(minimum.pos);
            openList.erase(
            std::remove_if(openList.begin(), openList.end(), [&](Node & node) {
                return node.pos == minimum.pos;
            }), openList.end());
        }

        if(currentNode == pathEnd){
            openList.clear();
        }
    }while(!(openList.empty()));
    return closedList;
}

I use a simple Vector2 struct I wrote in a header file here:

#ifndef VECTOR2_H_INCLUDED
#define VECTOR2_H_INCLUDED

struct Vector2{
    int x;
    int y;
    Vector2(int x, int y){
        this->x = x;
        this->y = y;
    }
    Vector2(){
        this->x = 0;
        this->y = 0;
    }

    inline Vector2 operator=(Vector2 a){
        x=a.x;
        y=a.y;
    }

    bool operator==(Vector2 a){
        return (x==a.x && y==a.y);
    }
};

#endif // VECTOR2_H_INCLUDED

Adding some comments on code quality would be nice too.

The problem is that you didn't calculate node.f correctly. Referring to the tutorial provided,

F = G + H

where G is the cost from A to the current square and H is the estimated cost from the current square to B. However, looking back to the code referring this part:

node.f = 1 + (std::abs(pathEnd.x - node.pos.x)+std::abs(pathEnd.y - node.pos.y));

It seems that the G is always 1, while the rest of the code is for working out H. In this case , G should be the steps it takes from A to currentNode plus 1, since it has take one step to move.

So, the most important part is that, only saving F is not enough. G has to be saved in order to work out F in other squares.

Edit: The reason why we do not use (std::abs(currentNode.x -pathStart.x)+std::abs(currentNode.y - pathStart.y) + 1 is because we might not reach the current square without a detour. eg

+---+
|   |
| | |
|S|E|
+-+-+

Supposed that now we are at point E starting form point S. Using (std::abs(currentNode.x -pathStart.x)+std::abs(currentNode.y - pathStart.y) + 1 , the distance is only 1. However, it takes 5 steps to go to E.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM