A*路径搜寻算法

A*搜寻算法,俗称A星算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。常用于游戏中的NPC(Non-Player-ControlledCharacter)的移动计算,或线上游戏的BOT(ROBOT)的移动计算上。该算法像Dijkstra算法一样,可以找到一条最短路径;也像BFS一样,进行启发式的搜索。

A*算法是一种启发式搜索算法,启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无谓的搜索路径,提高了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。

A*算法的公式为:f(n)=g(n)+h(n),g(n)表示从起点到任意顶点n的实际距离,h(n)表示任意顶点n到目标顶点的估算距离。 这个公式遵循以下特性:

  • 如果h(n)为0,只需求出g(n),即求出起点到任意顶点n的最短路径,则转化为单源最短路径问题,即Dijkstra算法
  • 如果h(n)<=“n到目标的实际距离”,则一定可以求出最优解。而且h(n)越小,需要计算的节点越多,算法效率越低。

对于函数h(n),估算距离常用的方法有:

  • 曼哈顿距离:定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里德空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为:|x1 - x2| + |y1 - y2|。
  • 欧氏距离:是一个通常采用的距离定义,它是在m维空间中两个点之间的真实距离。在二维和三维空间中的欧氏距离的就是两点之间的距离。例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的欧氏距离为: sqrt((x1-x2)^2+(y1-y2)^2 )。
  • 切比雪夫距离:是两个向量之间各分量差值的最大值。例如在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的切比雪夫距离为:max(|x1 - x2| , |y1 - y2|)。

A*算法实现伪代码:

function A*(start,goal)
    closedset := the empty set
    openset := {start} 
    came_from := the empty map
 
    g_score[start] := 0
    h_score[start] := heuristic_cost_estimate(start, goal)
    f_score[start] := g_score[start] + h_score[start]
 
    while openset is not empty
        x := the node in openset having the lowest f_score[] value
        if x = goal
            return reconstruct_path(came_from, came_from[goal])
 
        remove x from openset
        add x to closedset
        foreach y in neighbor_nodes(x)
            if y in closedset
                 continue
            tentative_g_score := g_score[x] + dist_between(x,y)
 
            if y not in openset
                 add y to openset
                 tentative_is_better := true
            else if tentative_g_score < g_score[y]
                 tentative_is_better := true
            else
                 tentative_is_better := false
 
            if tentative_is_better = true
                 came_from[y] := x
                 g_score[y] :=tentative_g_score
                 h_score[y] :=heuristic_cost_estimate(y, goal)
                 f_score[y] := g_score[y] +h_score[y]
 
    return failure
 
 function reconstruct_path(came_from,current_node)
    if came_from[current_node] is set
        p := reconstruct_path(came_from, came_from[current_node])
        return (p + current_node)
    else
        return current_node

下面给出一个A*(曼哈顿距离)的例子:

代表起点,代表终点,代表障碍,代表属于OPENSET,代表属于CLOSEDSET, ——  黄色线段代表最终得出的路径。
方格内左上角代表f(n)即启发函数值,左下角代表g(n),即起点到该点的距离,右下角代表h(n),即该点到终点距离的估值,使用曼哈顿距离,方格上下左右相邻距离为10,对角线相邻为14,曼哈顿距离以10为单位。
(gif动画文件)

A*路径搜寻算法_第1张图片

A*与Dijkstra,DFS,BFS:

  • A*算法,每次从OPENSET中选择 f(n) 最小的节点将其加入CLOESEDSET中,同时扩展相邻节点,可把OPENSET看成一个优先队列,key值为 f(n),优先级最高的先出。
  • Dijkstra算法,每次从OPENSET中选择 g(n) 最小的节点将其加入CLOSEDSET中,同时扩展相邻节点,可把OPENSET看成一个优先队列,key值为 g(n),优先级最高的先出。
  • DFS算法,每次从OPENSET中选择最晚被加入的节点将其加入CLOSEDSET中,同时扩展相邻节点,可把OPENSET看成一个栈,后进先出。
  • BFS算法,每次从OPENGSET中选择最早被加入的节点将其加入CLOSEDSET中,同时扩展相邻节点,可把OPENSET看成一个队列,先进先出。

下面通过几个例子对比一下5种算法,A*(曼哈顿距离),A*(欧氏距离),A*(切比雪夫距离),Dijkstra,Bi-Directional Breadth-First-Search ,以显示A*算法的优越性。
例一:
1.1 A*(曼哈顿距离)
A*路径搜寻算法_第2张图片

1.2 A*(欧氏距离)
A*路径搜寻算法_第3张图片

1.3 A*(切比雪夫距离)
A*路径搜寻算法_第4张图片

1.4 Dijkstra 
A*路径搜寻算法_第5张图片

1.5 Bi-Directional Breadth-First-Search
A*路径搜寻算法_第6张图片


例二:
2.1 A*(曼哈顿距离)
A*路径搜寻算法_第7张图片

2.2 A*(欧氏距离)
A*路径搜寻算法_第8张图片

2.3 A*(切比雪夫距离)
A*路径搜寻算法_第9张图片

2.4 Dijkstra
A*路径搜寻算法_第10张图片

2.5 Bi-Directional Breadth-First-Search
A*路径搜寻算法_第11张图片

例三:
3.1 A*(曼哈顿距离)
A*路径搜寻算法_第12张图片

3.2 A*(欧氏距离)
A*路径搜寻算法_第13张图片

3.3 A*(切比雪夫距离)
A*路径搜寻算法_第14张图片

3.4 Dijkstra
A*路径搜寻算法_第15张图片

3.5 Bi-Directional Breadth-First-Search
A*路径搜寻算法_第16张图片

例四:

4.1 A*(曼哈顿距离)
A*路径搜寻算法_第17张图片

4.2 A*(欧氏距离)
A*路径搜寻算法_第18张图片

4.3 A*(切比雪夫距离)
A*路径搜寻算法_第19张图片

4.4 Dijkstra
A*路径搜寻算法_第20张图片

4.5 Bi-Directional Breadth-First-Search
A*路径搜寻算法_第21张图片

附:
我从网上找到的比较好的一个算法演示程序,下载地址
http://download.csdn.net/detail/walkinginthewind/3822153

你可能感兴趣的:(游戏,算法,搜索,路径,a)