文章目录

  • 1. 算法解析
  • 2. 总结

仙剑奇侠传这类MMRPG游戏中,有人物角色 自动寻路功能。当人物处于游戏地图中某位置时,点击另一个相对较远的位置,人物就会自动地绕过障碍物走过去。这个功能是怎么实现的呢?

1. 算法解析

这是一个非常典型的搜索问题。起点是当下位置,终点是鼠标点击位置。找一条路径。路径要绕过地图中所有障碍,并且走的路不能太绕。最短路径显然是最聪明的走法,是最优解。

但是如果图非常大,那Dijkstra最短路径算法的执行耗时会很多。在真实的软件开发中,面对的是超级大的地图和海量的寻路请求,算法的执行效率太低,是无法接受的。

一般情况下,我们都不需要非得求最优解(最短路径)。在权衡路线规划质量和执行效率的情况下,只需要寻求一个次优解就足够了

  • A* 算法是对Dijkstra算法的优化和改造。

Dijkstra 算法有点类似BFS算法,它每次找到跟起点最近的顶点,往外扩展。这种往外扩展有些盲目。举一个例子。下图对应一个真实地图,每个点在地图中的位置,用一个坐标(x,y)来表示,x横坐标,y纵坐标。

在Dijkstra算法中,用一个优先队列,记录已经遍历的顶点以及这个顶点与起点的路径长度。顶点与起点路径长度越小,优先从优先级队列中取出来扩展,从图中举例可以看出,尽管找的是从s到t的路线,但是最先被搜索到的顶点依次是1,2,3。这个搜索方向明显“跑偏"了。

之所以“跑偏”,是因为没有考虑这个顶点到终点的距离,尽管1,2,3三个顶点离起始顶点最近,但离终点却越来越远。

如果综合更多因素,把这个顶点到终点可能还要走多远,考虑进去,综合判断哪个顶点先出队列,是不是就可以避免“跑偏”呢?

当遍历到某个顶点时,从起点走到这个顶点的路径长度是确定的,我们记作g(i)。通过这个顶点跟终点之间的直线距离,也就是欧几里得距离,来近似估计这个顶点跟终点的路径长度。我们把这个距离记作h(i),专业叫法是启发函数(heuristic function)。因为欧几里得距离公式,会涉及比较耗时的开根号计算,所以一般计算曼哈顿距离(Manhattan distance)。曼哈顿距离是两点之间横纵坐标的距离之和。只涉及加减法、符号位反转,所以更加高效。

int hManhattan(Vertex v1, Vertex v2)
{ // Vertex 表示顶点return Math.abs(v1.x - v2.x) + Math.abs(v1.y - v2.y);
}

通过两者之和 f(i)= g(i)+ h(i),来判断哪个顶点最先出队。能有效避免“跑偏"。这里f(i)的专业叫法是估价函数(evaluation function)。

A* 算法就是对Djkstra算法的简单改造。在A*算法的代码实现中,顶点Vertex类的定义,多了x,y坐标,f(i)值。

A* 算法跟Djkstra 算法主要有3点区别:

  • 优先级队列构建的方式不同。A*算法是根据 f 值 f(i)=g(i)+h(i)来构建优先级队列,而Dijkstra 算法是根据dist值 g(i)来构建优先级队列;
  • A*算法在更新顶点dist值的时候,同步更新 f 值;
  • 循环结束的条件不一样。Dijkstra 算法是在终点出队列的时候才结束,A*算法是一旦遍历到终点就结束。

尽管A* 算法可以快速找到从起点到终点的路线,但是它并不能像Dijkstra算法那样,找到最短路线

Dijkstra 算法在回溯基础上,利用动态规划思想,对回溯进行剪枝,只保留起点到某个顶点的最短路径,继续往外扩展搜索。动态规划相较于回溯搜索,只是换了一个实现思路,但它实际上也考察到了所有从起点到终点的路线,所以能得到最优解。

A* 算法之所以不能像Dijkstra 算法那样,找到最短路径,主要原因是两者的while 循环结束条件不一样。

  • Dijkstra 算法是在终点出队列的时候才结束
  • A*算法是一旦遍历到终点就结束。

对于Dijkstra 算法来说,当终点出队列的时候,终点的 dist 值是优先级队列中所有顶点的最小值,即便再运行下去,终点的dist值也不会再被更新了。
对于A* 算法来说,一旦遍历到终点,我们就结束 while循环,这个时候,终点的dist值未必是最小值。

A* 算法利用贪心算法的思路,每次都找 f 值最小的顶点出队列,一旦搜到终点就不继续考察其他顶点和路线。所以,它没有考察所有路线,也就不能找出最短路径。

如何借助A* 算法解决游戏寻路?

游戏地图并不像现实生活中那样,存在规划非常清晰的道路,更多的是宽阔的荒野、草坪等。换一种抽象的思路,把地图分割成一个一个的小方块。在某个方块上的人物,只能往上下左右四个方向移动。把每个方块看作一个顶点。方块相邻,它们之间连两条有向边,权值都是1。套用A* 算法。

2. 总结

A* 算法属于一种启发式搜索算法(Heuristically Search Algorithm)。启发式搜索算法还有很多其他算法,比如 IDA* 算法、蚁群算法、遗传算法、模拟退火算法等。

  • 启发式搜索算法利用估价函数,避免“跑偏”,贪心地朝着最有可能到达终点的方向前进。
  • 算法找出的路线,并不是最短路线。
  • 实际软件开发中的路线规划问题,并不需要非得找最短路线。鉴于启发式搜索算法能很好地平衡路线质量和执行效率,它应用更加广泛。

A*搜索算法--游戏寻路相关推荐

  1. c语言a 寻路算法,JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例

    本文实例讲述了JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法.分享给大家供大家参考,具体如下: 完整实例代码如下: A*寻路算法 #stage { border: 1px solid lig ...

  2. 游戏寻路中 A* 算法的改进

    在众多寻路算法中,A* 的确是比较不错的.但在游戏寻路领域,A* 耗时过大,显然需要改进. 改进 我的想法是预先将地图按照一定的规则划分为多个区域,这些区域彼此连通,并且计算好彼此连通的区域之间的来往 ...

  3. a算法和a*算法的区别_游戏寻路中 A* 算法的改进

    在众多寻路算法中,A* 的确是比较不错的.但在游戏寻路领域,A* 耗时过大,显然需要改进. 改进 我的想法是预先将地图按照一定的规则划分为多个区域,这些区域彼此连通,并且计算好彼此连通的区域之间的来往 ...

  4. Unity 之 手把手教你实现自己Unity2D游戏寻路逻辑 【文末源码】

    Unity 之 手把手教你实现自己Unity2D游戏寻路逻辑 [文末源码] 前言 一,效果展示 二,场景搭建 三,代码逻辑 四,完善场景 五,使用小结 前言 还在看别人的寻路逻辑?保姆级教程,一步步教 ...

  5. 游戏思考24:游戏寻路算法思考和Unity场景相关代码开发原则及导入地图数据(10/09)

    文章目录 一.游戏寻路算法 1)总体划分为 2)取几种算法详细介绍 (1)JPS介绍及其优化 二.场景相关开发原则 1)Unity开发商业项目场景开发基本原则 2)商业项目的大体流程和组织思路 一.游 ...

  6. 【Unity】游戏寻路系统—NavMesh入门(个人翻译)

    以下内容笔者个人翻译自:http://www.theknightsofunity.com/ 游戏中的许多角色经常需要绕过关卡种中的障碍物.正是因为这是一个游戏中非常常见的情形,Unity提供了内置的寻 ...

  7. 游戏寻路算法的简单实现

    提到寻路算法,大家都会想到A*算法. 在度娘找了不少代码,看了不少教程之后,尤其是这个文章中提到的总结:http://www.cppblog.com/christanxw/archive/2006/0 ...

  8. 【CSON原创】A*算法+HTML5实现游戏寻路

    功能描述: 结合A*算法和HTML5完成的一个寻路demo. 鼠标点击地图任意位置,飞鸟会寻找最短路程到达该位置. 效果预览: 代码分析: 具体的A*算法寻路逻辑请看这里推荐的一篇很好的文章,我就不再 ...

  9. 易语言写64位魔兽世界游戏 寻路call 教程

    自从Game-EC 8.5.3 辅助模块 发布 开发 64位游戏内存,封包的功能后, 受到了很多写 64位游戏封包,内存辅助的爱好者喜爱 今天在新版本 Game-EC 里面 开发了一个 能调用64位游 ...

最新文章

  1. 开源:Angularjs示例--Sonar中项目使用语言分布图
  2. Lucene教程具体解释
  3. 一个垃圾分类项目带你玩转飞桨(1)
  4. Linxu的常用命令
  5. c语言二叉树学生成绩,二叉树C语言
  6. win10系统按esc会弹出计算机,win10系统版本2004控制面板多出ESC是什么原因?
  7. 纪事本 乱码_纪事地图和Yahoo Cloud服务基准
  8. 智能制造的灾备问题如何解决?
  9. 01背包、完全背包、多重背包问题的C++实现及路径记录
  10. 那些面对面试官的“绝杀技”
  11. [CEOI2008]order
  12. IT人士易犯4大职业病 鼠标手居第一位
  13. Xshell上传文件方法
  14. 固态硬盘和机械硬盘的区别(7大区别,简单易懂)
  15. EDI集成对业务的重要性
  16. 2023拼多多商品详情,拼多多sku采集
  17. 备份恢复Lesson 09. Diagnosing Failures
  18. java 反射 set方法_java 反射调用set方法
  19. ioswebview混编_iOS 原生和H5混合开发总结
  20. 为什么计算机领域没有诺贝尔奖,为什么没有数学家获得诺贝尔奖

热门文章

  1. 面试题:找出公司员工最喜欢的k种水果
  2. lightoj1259 线性筛的另一种写法 v变成bool标记数组
  3. 【VBA编程】06.控制语句
  4. JNative用法注意事项
  5. 用MS SQL Server事件探查器来跟踪数据库的操作
  6. 自旋锁/互斥锁/读写锁/递归锁的区别与联系
  7. C++ functor 仿函数
  8. Android Input 子系统初探
  9. Win10系统添加 Win10 LTSC2019闹钟
  10. STM32CubeMx官网下载HAL库文档资料