Алгоритм поиска пути - PullRequest
       29

Алгоритм поиска пути

0 голосов
/ 09 февраля 2019

Я студент и столкнулся с проблемой, которую не могу решить.У меня есть карта Terrain, которая представляет собой массив enum, содержащий целые числа и имя.

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* но по какой-то причине это неправильно и не игнорирует стены, несмотря на проверку.

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

    return false;
}

Я смотрел несколько видео, пытался имитировать код psuedo, но до сих пор не могу понять, где онпойдет не так.Вот код поиска:

Эта функция становится владельцем указателей старта и цели, которые передаются из вызывающего кода.Право собственности не возвращается в конце, поэтому начальный и целевой узлы используются.Путь возвращается через опорный параметр.

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;

Извините за ужасно длинный код и сообщение,любая помощь и комментарии даже в отношении стиля кода приветствуются.

...