使用以下A星可视化作为比较路径准确性的方法,我发现我的实现与此之间存在很大差异。
https://qiao.github.io/PathFinding.js/visual/
路径我正在比较:
我的测试路径:
有时算法似乎检查的节点太少(即测试#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);
}
}
}
我添加了最重要的代码。如果高级函数无法帮助找到问题的根源,请告诉我,我也会为它们添加实现。
帮助表示赞赏。
答案 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
}