寻找最短路径但未正确计算的星型算法

时间:2016-12-09 12:00:57

标签: c++ algorithm a-star

使用以下A星可视化作为比较路径准确性的方法,我发现我的实现与此之间存在很大差异。

https://qiao.github.io/PathFinding.js/visual/

路径我正在比较:

Path I'm comparing to

我的测试路径:

img

有时算法似乎检查的节点太少(即测试#6)。这是预期的,还是不正确?

算法中的重要变量:

TileMap* m_tileMap;
vector<Tile*> m_openList;
vector<Tile*> m_path;

// Direct mapping of 2D tile map. 
// Stores the list type for the same-indexed tile 
vector<vector<int>> m_listMap;

打开清单排序的比较器:

struct CompareNodes
{
    // sorts lowest F cost to end of vector
    bool operator() (Tile* lhs, Tile* rhs)
    {
        return lhs->getFCost() > rhs->getFCost();
    }
};

高级别实施:

vector<Tile*> PathGenerator::generatePath(Tile* startNode, Tile* endNode)
{
    setUpListMap();

    startNode->setGCost(0);
    startNode->setHCost(calculateHCost(startNode, endNode)); // Manhattan (no diagonal). { abs(y2 - y1) + abs(x2 - x1) }
    startNode->calculateFCost(); // calculates G+H internally

    m_openList.push_back(startNode);
    Vector2D startNodePos = startNode->getMapPos();
    m_listMap[startNodePos.x][startNodePos.y] = LIST_TYPES::OPEN;

    Tile* currentNode;


    while (m_openList.empty() == false)
    {
        currNode = m_openList[m_openList.size() - 1];
        m_openList.pop_back();

        Vector2D currNodePos = currNode->getMapPos();
        m_listMap[currNodePos.x][currNodePos.y] = LIST_TYPES::CLOSED;

        if (currNode != endNode)
        {
            vector<Tile*> neighbours = findNeighbours(currNode);
            removeUnnecessaryNodes(&neighbours); // remove walls and closed nodes
            computeCosts(&neighbours, currNode, endNode);
            addUniqueNodesToOpenList(&neighbours); // ignores duplicates and then sorts open list
        }
        else
        {
            m_path = getPath(currNode);
            resetLists(); // erases all vectors
        }
    }

    return m_path;
}

void PathGenerator::computeCosts(vector<Tile*>* nodes, Tile* current, Tile* end)
{
    int newGCost = current->getGCost() + 1;

    for (int i = 0; i < nodes->size(); i++)
    {
        Tile* node = nodes->at(i);
        unsigned int nodeGCost = node->getGCost(); // G cost defaults to max int limit

        if (newG < nodeGCost)
        {
            // set up node costs like above
            node->setParentNode(current);
        }
    }
}

我添加了最重要的代码。如果高级函数无法帮助找到问题的根源,请告诉我,我也会为它们添加实现。

帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

The sorting part seems correct, but since it's a vector this should be very easy for you to verify.

Instead, try using a for-loop as a test-case to make sure you're really get the lowest f-cost node:

Tile* currnode = m_openlist[0]; 
for (int i = 0; i < m_openList.size() i++) 
{ 
    if (m_openList[i]->getFCost() < currnode->getFCost()) 
        currnode = m_openList[i]; 
} 

See if that fixes it. If it does, there's an issue in your sort, but i'm not sure what the issue would be.

Also, in your computeCosts function, you do:

  for (int i = 0; i < nodes->size(); i++)
  {
      Tile* node = nodes->at(i);
      //.. other code
  }

Since you're using an std::vector, why not make use of its functionality, and use iterators or a range based loop:

// Iterators
for (auto it = nodes->begin(); it != nodes->end(); it++)
{
    Tile* node = *it;
    //.. other code
}

// Range based loop
for (auto node : *nodes)
{
    //.. other code
}