簡體   English   中英

在 c++ 中實現 a* 尋路

[英]Implementing a* pathfinding in c++

嘗試為一個小游戲實現 A* 尋路。 遇到一些奇怪的錯誤。

代碼:

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);
};

和尋路代碼:

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';
}

我的目標是使用 A* 找到一條路線,然后簡單地返回要前往的第一個 position 的方向。

我遇到的問題:問題是當滿足 currentNode == endNode 的條件時(達到目標)。 每個 PathNode 的父節點都只是指向自身(根據調試器)。 我不明白它為什么會發生,我假設當前指針在某個時間點被破壞,但我無法弄清楚它為什么會發生。

您正在存儲一個指向局部變量的指針,因此每個節點都將具有與父節點相同的局部變量(一旦它被銷毀,對它的任何訪問都將是未定義的行為)。 這發生在PathNode newNode(nodePosition, 0, 0, &currentNode); 宣言。

您可能希望將currentNode更改為指針,而不是 object,並讓它指向closedList向量中的父 object。 這將允許您更新它指向的節點,而無需制作副本。 您已經為 500 個條目保留了足夠的空間,因此在將第 501 個元素添加到向量之前,您不會遇到懸空指針的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM