我正在使用Wikipedia article on A*。我的实现在通过cameFrom
映射时,在找到从0,0
到7,0
的路径后,一直在5,0
和6,0
之间进行ping响应,如下所示: cameFrom[5,0] == 6,0
和cameFrom[6,0] == 5,0
。
typedef std::deque<birunji::utils::Vector2i> AStarPath;
AStarPath ReconstructPath(const Map& map,
std::map<std::size_t,birunji::utils::Vector2i>& cameFrom,
const birunji::utils::Vector2i& c,
const birunji::utils::Vector2i& start)
{
AStarPath totalPath;
birunji::utils::Vector2i current = c;
totalPath.push_back(current);
while(cameFrom.find(map.GetIndex(current)) != cameFrom.end() && current != start)
{
current = cameFrom[map.GetIndex(current)];
totalPath.push_back(current);
}
return totalPath;
}
AStarPath AStar(
const birunji::utils::Vector2i& start,
const birunji::utils::Vector2i& goal,
const Map& map)
{
using namespace birunji::utils;
std::set<Vector2i, std::function<bool(const Vector2i&, const Vector2i&)>> closed([](const Vector2i& a, const Vector2i& b)
{
return true;
});
std::map<std::size_t, float> fScore;
float dx = std::abs(start.x - goal.x);
float dy = std::abs(start.y - goal.y);
float cost = 1.0f * (dx + dy) + (1.4f - 2.0f * 1.0f) * std::min(dx,dy);
fScore[map.GetIndex(start)] = cost;
std::set<Vector2i, std::function<bool(const Vector2i&,const Vector2i&)>> open([&](const Vector2i& a, const Vector2i& b)
{
return fScore[map.GetIndex(a)] < fScore[map.GetIndex(b)];
});
open.emplace(start);
std::map<std::size_t,Vector2i> cameFrom;
std::map<std::size_t,float> gScore;
gScore[map.GetIndex(start)] = 0;
while(!open.empty())
{
auto itr = open.begin();
Vector2i current = *itr;
open.erase(itr);
if(current == goal)
return ReconstructPath(map,cameFrom, current,start);
closed.emplace(current);
for(const TileData& n : map.GetNeighbours(current))
{
Vector2i neighbour(n.x,n.y);
if(closed.count(neighbour))
continue;
float moveCost;
if(!map.TraverseCost(current,neighbour,moveCost))
continue;
float tentativeGScore = gScore[map.GetIndex(current)] + moveCost;
std::size_t neighbourIndex = map.GetIndex(neighbour);
if(!open.count(neighbour))
open.emplace(neighbour);
else if(tentativeGScore >= gScore[neighbourIndex])
continue;
cameFrom[neighbourIndex] = current;
gScore[neighbourIndex] = tentativeGScore;
float dx = std::abs(neighbour.x - goal.x);
float dy = std::abs(neighbour.y - goal.y);
float h = 1.0f * (dx + dy) + (1.4f - 2.0f * 1.0f) * std::min(dx,dy);
fScore[neighbourIndex] = tentativeGScore + h;
}
}
return {};
}
我想念什么?
答案 0 :(得分:0)
我认为Wiki中缺少一个步骤,当您获得邻居时,您需要根据当前路径更新其父项(来自)和g值(如果它是比邻居现有路径更好的路径) )
/* Can the neighbour's g value be improved by coming from this current node ? */
if(neighbour.g > (currentNode.g + ( currentNode.distanceTo(neighbour)*this.wg ))) {
/* Yes this is a better path to the neighbour. Set neighbour g to the current node g + distance from current node */
neighbour.g = currentNode.g + ( currentNode.distanceTo(neighbour)*this.wg );
/* Parent node of neighbour is changed to the current node */
neighbour.parent = currentNode;
}
对不起,不是Java脚本,而是C。但是希望可以帮助您步入正轨。还要注意注释如何使阅读和调试变得更容易...
这可能是对AStar的最好解释(具体问题请从6:00开始)-https://www.youtube.com/watch?v=-L-WgKMFuhE
我在Javascript中的示例具有很不错的视觉效果。.http://mjp.co/js/astar/