我的A *实现未正确跟踪“ camefrom”地图

时间:2019-01-21 08:57:17

标签: c++ a-star

我正在使用Wikipedia article on A*。我的实现在通过cameFrom映射时,在找到从0,07,0的路径后,一直在5,06,0之间进行ping响应,如下所示: cameFrom[5,0] == 6,0cameFrom[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 {};
}

我想念什么?

1 个答案:

答案 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/