等距地图的准确A *搜索启发式算法?

时间:2009-08-12 14:53:23

标签: algorithm search heuristics a-star isometric

我编写了A *搜索算法的实现。问题是我目前使用的启发式方法仅适用于方格网格。由于我的地图是等距的,启发式不会考虑实际地图的布局,因此也就是单元格之间的距离。

更新经过大量的记录和分析(读作花费大量时间试图找出平庸),我得出的结论是我当前的启发式工作原理很好,只有一个例外:最终结果与真实直线和对角线移动相反。

inline int Pathfinder::calculateDistanceEstimate(const CellCoord& coord) const
{
    int diagonal = std::min(abs(coord.x-goal->position.x), abs(coord.y-goal->position.y));
    int straight = (abs(coord.x-goal->position.x) + abs(coord.y-goal->position.y));
    return 14 * diagonal + 10 * (straight - 2 * diagonal);
}

这意味着直接移动(实际上比等距地图上的对角线移动花费sqrt(2)倍)计算为对角线移动。问题是:如何修改当前的启发式方法,以便为等轴测布局生成正确的结果?只需将diagonal替换为straight,反之亦然

Map layout

2 个答案:

答案 0 :(得分:4)

尝试的一件事是从等距坐标转换为所有计算的方形网格坐标集。

假设0,0保持地图的根。 0,1保持不变,1,2变为0.2; 1,3变为0,3; 2,3变为1,4; 3,3变为2,5; 0,2变为-1,1;这会使你回到正方形网格中,这样坐标和启发法就可以再次运作了。

Y坐标变为Y + sourceX偏移(3,3在x = 2;因此变为2,5);以数学方式找到sourceX证明自己更难。

[意识流;忽略] Y = 0处的等距坐标对于源X是准确的。因此,要计算源X,您需要'向左/向上移动Y次',这应该净化Y / 2的变化;向下舍入,在X坐标....大致建议方形坐标为:

sourceX = X - Y/2
sourceY = Y + sourceX

其中sourceX和sourceY是正常方形网格中的坐标;和Y / 2是整数运算/向下舍入。

所以,从理论上讲,这就变成了:

double DistanceToEnd(Point at, Point end)
{
    Point squareStart = squarify(at);
    Point squareEnd = squarify(end);
    int dx=squareStart.X-squareEnd.X;
    int dy=squareStart.Y-squareEnd.Y;
    return Math.Sqrt(dx*dx+dy*dy);
}
Point squarify(Point p1)
{
     return new Point(p1.X-p1.Y/2, p1.Y+(p1.X-p1.Y/2));
}
根据新问题点

更新

假设你试图获得距离(3,2; 3,3)< (距离(2,3; 3,3)=距离(3,1; 3,3));以下应该有效:(从C#翻译;不保证不存在的拼写错误)

inline int Pathfinder::calculateDistanceEstimate(const CellCoord& coord) const
{
    int cx=coord.x - coord.y/2;
    int cy=coord.y + cx;
    int gx=goal->position.x - goal->position.y/2;
    int gy=goal->position.y + gx;
    int diagonal = std::min(abs(cx-gx), abs(cy-gy));
    int straight = (abs(cx-gx) + abs(cy-gy));
    return 14 * diagonal + 10 * (straight - 2 * diagonal);
}

编辑:修复了可怕的错字....再次。

答案 1 :(得分:-1)

Amit这里计算“六边形的曼哈顿距离”。它的C ++代码,我无法保证它,但Amit是我之前听过的游戏开发名称。

六边形的曼哈顿距离应该适合于适当的启发式。

编辑:颠倒了超链接的语法,哎呀。