A *寻路算法

时间:2019-02-09 16:35:13

标签: c++ search path-finding a-star graph-traversal

我是一名学生,遇到了我似乎无法解决的问题。我有一个Terrain映射,它是一个包含整数和名称的枚举数组。

enum ETerrainCost
{
    Clear = 1,
    Water = 2,
    Wood  = 3,
    Wall  = 0
};

// Maps of any size are implemented as 2D vectors
using TerrainMap = vector<vector<ETerrainCost>>;

在加载地图并添加“开始”和“目标”坐标后,我正在使用A *运行寻路,但是由于某种原因,它是错误的,即使进行了检查也不会忽略Walls。

inline bool WallCheck(TerrainMap& terrain, unique_ptr<SNode>& node)
{
    if (static_cast<int>(terrain[node->x][node->y]) == 0)
    {
        return true;
    }

    return false;
}

我看了多个视频,试图模仿伪代码,但我仍然无法弄清出哪里出了问题。这是搜索的代码:

此函数获取从调用代码传递的开始和目标指针的所有权。 最终没有返回所有权,因此消耗了开始和目标节点。 通过引用参数返回路径。

bool CSearchAStar::FindPath(deque<unique_ptr<SNode>>& openList, deque<unique_ptr<SNode>>& closedList,
                                        TerrainMap& terrain, unique_ptr<SNode>& start, unique_ptr<SNode>& goal,
                                                                            NodeList& path, int& counter)
{
    unique_ptr <SNode> startNode(new SNode);
    unique_ptr <SNode> currentNode(new SNode);
//For .erase() function
deque <unique_ptr <SNode> >::iterator myIt;

//North, East, South, West are the options to move
int rulesNumber = 4;

//Set start and calculate score(heuristic only)
startNode->x = start->x;
startNode->y = start->y;
startNode->parent = 0;
startNode->cost = 0;
startNode->heuristic = utility::NodeHeuristic(startNode, goal);
startNode->score = startNode->heuristic;

//Moved to the openList
openList.push_back(move(startNode));

//If it's the goal, return
if (start->x == goal->x && start->y == goal->y)
{
    return true;
}

while (currentNode->x != goal->x || currentNode->y != goal->y)
{
    //If there is no element to expand, return
    if (openList.empty())
    {
        return false;
    }

    //Take an element from the openList and make 
    //it current to expand it's neighbors
    currentNode = move(openList.front());
    openList.pop_front();

    //tempNode is identical to currentNode, 
    //and will be pushed into the closed list instead of it
    //To be pushed to the closedList
    unique_ptr <SNode> tempNode(new SNode);
    tempNode->x = currentNode->x;
    tempNode->y = currentNode->y;
    tempNode->parent = currentNode->parent;
    tempNode->cost = currentNode->cost;
    tempNode->heuristic = currentNode->heuristic;
    tempNode->score = currentNode->score;

    for (int i = 0; i < rulesNumber; ++i)
    {
        unique_ptr <SNode> neighborNode(new SNode);
        switch (i)
        {
        case 0:
            neighborNode->x = currentNode->x;
            neighborNode->y = currentNode->y + 1;
            neighborNode->cost = utility::NodeCost(terrain, currentNode, neighborNode);
            neighborNode->parent = currentNode.get();
            neighborNode->heuristic = utility::NodeHeuristic(neighborNode, goal);
            neighborNode->score = neighborNode->cost + neighborNode->heuristic;

            //If it's a wall - skip it
            if (utility::WallCheck(terrain, neighborNode))
            {
                break;
            }

            //If it's on one of the lists and it's score is heigher with this route - skip it
            if ((utility::FindOnOpenList(neighborNode, openList, myIt) || utility::FindOnClosedList(neighborNode, closedList, myIt)) 
                && neighborNode->score >= currentNode->score)
            {
                break;
            }

            //If it's on one of the lists and has a lower score with this route - 
            //refer to it from now on and take it from the list
            if (utility::FindOnOpenList(neighborNode, openList, myIt))
            {
                auto temp = myIt;
                neighborNode = move((*myIt));
                openList.erase(temp);

                //Refresh the parent and get the cost changed for the old element
                neighborNode->parent = currentNode.get();
                neighborNode->cost = utility::NodeCost(terrain, currentNode, neighborNode);
                neighborNode->heuristic = utility::NodeHeuristic(neighborNode, goal);
                neighborNode->score = neighborNode->cost + neighborNode->heuristic;
            }
            else if (utility::FindOnClosedList(neighborNode, closedList, myIt))
            {
                break;
            }

            //Push back onto the openList
            openList.push_back(move(neighborNode));

            //Reorder OpenList by score(since either the cost of the node has been updated
            //or it has been pushed onto the OpenList).
            std::sort(openList.begin(), openList.end(), [](unique_ptr<SNode>& lhs,
                unique_ptr<SNode>& rhs) { return lhs->score < rhs->score; });
            counter++;

            break;

与案例1、2和3相同,并且在for循环之后:

//Push current to the closedList
    closedList.push_back(move(tempNode));
}


return true;

很抱歉,代码和消息太长了,我们非常欢迎您提供任何帮助和注释,甚至在代码样式方面。

0 个答案:

没有答案