简体   繁体   English

在 c++ 中实现 a* 寻路

[英]Implementing a* pathfinding in c++

Trying to implement A* pathfinding for a small game.尝试为一个小游戏实现 A* 寻路。 Running into some strange bugs.遇到一些奇怪的错误。

Code:代码:

class PathNode
{
private:
    const PathNode* parent;
    GameObject position;

    int g;
    int h;
    int f;

public:
    PathNode(GameObject _position, int _g, int _h, const PathNode* _parent = nullptr) {

        parent = _parent;
        position = _position;

        g = _g;  // distance between the start node and the current node
        h = _h;  // distance between the current node and the end node
        f = g + h;  // Total cost of the node (g + h)
    }

    PathNode(const PathNode& other) {

        position = other.position;
        g = other.g;  // distance between the start node and the current node
        h = other.h;  // distance between the current node and the end node
        f = other.f;  // Total cost of the node (g + h)

        parent = other.parent;
    }

    bool operator==(const PathNode& other) const {

        return (this->position == other.position);
    }

    bool operator!=(const PathNode& other) const {

        return !operator==(other);
    }

// GETTERS:
    int getg() const;
    int geth() const;
    int getf() const;
    const PathNode* getParent() const;
    const GameObject getPosition() const;

// SETTERS:
    void setg(int newG);
    void seth(int newH);
    void setf(int newF);
    void setParent(const PathNode* newParent);
    void setPosition(GameObject newPos);
};

And The PathFinding code:和寻路代码:

char Ghost::aStar(char board[BoardYSize][BoardXSize], GameObject end) {

    int startEndDistance = pow((getX() - end.getX()), 2) + pow((getY() - end.getY()), 2);

    PathNode startNode(getPosition(), 0, startEndDistance);  // in the ctor of PathNode, the default values of Parent == nullptr.

    PathNode endNode(end, startEndDistance, 0);  // in the ctor of PathNode, the default values of Parent == nullptr.

    // Initialize both Open and Closed Lists:
    vector<PathNode> openList;
    vector<PathNode> closedList;

    openList.reserve(500);
    closedList.reserve(500);

    // Add the StartNode:
    openList.push_back(startNode);

    // Loop until you find the end:
    while (openList.size() > 0) {

        // Get the current Node.
        PathNode currentNode(openList[0]);  // Default copy ctor.

        int index = 0;

        for (int i = 0; i < openList.size(); i++) {

            if (openList[i].getf() < currentNode.getf()) {

                index = i;
                currentNode = openList[i];
            }
        }

        // Pop Current off openList, and add to closedList:
        openList.erase(openList.begin() + index);
        closedList.push_back(currentNode);

        // If found the end, return:
        if (currentNode == endNode) {

            // return direction of the first move of the path:
            const PathNode* nextNode = &currentNode;
            const PathNode* firstMoveNode = nullptr;

            while (*nextNode != startNode) {

                firstMoveNode = nextNode;
                nextNode = nextNode->getParent();
            }

            GameObject newPos = firstMoveNode->getPosition();
            GameObject currentPos = startNode.getPosition();

            if (newPos.getX() - currentPos.getX() == 0 && newPos.getY() - currentPos.getY() == 1)

                return 'w';

            else if (newPos.getX() - currentPos.getX() == 0 && newPos.getY() - currentPos.getY() == -1)

                return 'x';

            else if (newPos.getX() - currentPos.getX() == 1 && newPos.getY() - currentPos.getY() == 0)

                return 'd';

            else if (newPos.getX() - currentPos.getX() == -1 && newPos.getY() - currentPos.getY() == 0)

                return 'a';

            else
                return 's';
        }

        // Generate Children:
        vector <PathNode> children;

        // temp is used to generate the children of the currentNode.
        GameObject temp[4];
        temp[0] = GameObject(0, 1);   // Position above currentNode
        temp[1] = GameObject(1, 0);   // Position right of currentNode
        temp[2] = GameObject(0, -1);  // Position left of currentNode
        temp[3] = GameObject(-1, 0);  // Position below currentNode

        for (int i = 0 ; i < 4; i++) {

            // Get Node Position:
            GameObject nodePosition(currentNode.getPosition() + temp[i]);

            // Make Sure within Range of board & Not a Wall (walkable terrain):
            if (!checkLegalMove(nodePosition, board))

                continue;
            
            PathNode newNode(nodePosition, 0, 0, &currentNode);
            children.push_back(newNode);
        }

        // Loop through Children:

        for (auto child : children) {

            bool addChild = true;

            // Child is on the closedList:
            for (auto closedChild : closedList) {

                if (child == closedChild) {

                    addChild = false;
                    continue;
                }
            }

            if (!addChild)  continue;

            // Create the G H and F values:
            child.setg(currentNode.getg() + 1);
            child.seth(pow((child.getPosition().getX() - endNode.getPosition().getX()), 2) + pow((child.getPosition().getY() - endNode.getPosition().getY()), 2));
            child.setf(child.getg() + child.geth());

            // Child is already in the openList:
            for (auto openNode : openList) {

                if (child == openNode && child.getg() > openNode.getg()) {

                    addChild = false;
                    continue;
                }
            }

            if (!addChild)  continue;

            openList.push_back(child);
        }
    }

    return 's';
}

My goal is to use A* to find a route and simply return the direction of the first position to travel to.我的目标是使用 A* 找到一条路线,然后简单地返回要前往的第一个 position 的方向。

The Problem I run into: The problem is that when the condition of currentNode == endNode is met (reached the goal).我遇到的问题:问题是当满足 currentNode == endNode 的条件时(达到目标)。 Every PathNode's parent is simply a pointing to itself (according to the debugger).每个 PathNode 的父节点都只是指向自身(根据调试器)。 I don't understand why it's happening, I assume The current pointer gets destroyed at some point in time but i can't figure out why it's happening.我不明白它为什么会发生,我假设当前指针在某个时间点被破坏,但我无法弄清楚它为什么会发生。

You're storing a pointer to a local variable, so every node will have that same local variable as the parent (and any access to it would be Undefined Behavior once it has been destroyed).您正在存储一个指向局部变量的指针,因此每个节点都将具有与父节点相同的局部变量(一旦它被销毁,对它的任何访问都将是未定义的行为)。 This happens in the PathNode newNode(nodePosition, 0, 0, &currentNode);这发生在PathNode newNode(nodePosition, 0, 0, &currentNode); declaration.宣言。

You might want to change currentNode to be a pointer, rather than an object, and have it point to the parent object in the closedList vector.您可能希望将currentNode更改为指针,而不是 object,并让它指向closedList向量中的父 object。 This would allow you to update what node it points at without having to make copies.这将允许您更新它指向的节点,而无需制作副本。 You've reserved enough space for 500 entries so you won't have a problem with dangling pointers until you add the 501st element to the vector.您已经为 500 个条目保留了足够的空间,因此在将第 501 个元素添加到向量之前,您不会遇到悬空指针的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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