前言
在课堂上听老师讲了一个人工智能的基础小算法,感觉神奇而有趣,便自行研究一下。研究了几个小时,总算实现了。想写一篇博文来记录一下今天的学习经历,那么,就请有兴趣的各位跟我一起从零实现一个简单的A星寻路算法啦。
概述
- 首先,需要有个基本概念:A*搜寻算法俗称“A星算法”。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。(启发式搜索)
几个要素
- 是否相通的标记(标记有许多种方式,例如:0为通畅、1为障碍;或者把两两结点的线路保存下来,再去查该线路是否存在)
- 一个父亲结点指针(处理结点时候,需要知道该结点的父节点)
- OPEN 表(待检查的点,认为当前点为父亲结点,父亲结点也要保存,)
- CLOSE 表(不再检查的点)
- 一条公式:F = H + G
F 为到终点的总耗费
H 为网格上当前方格移动到终点的预估耗费(预估算法有很多种,例如:“曼哈顿法”:H = |行数| + |列数|、另外也可利用直线距离…);
G 为父亲结点移动到当前结点的预估移动耗费; 现在,再来举个栗子,下面的步骤解析也会与之相结合:
简单解释:
- 图中有 A、B、C、D、E、F、G、H 8个结点( A 为起点、E 为终点) - 括号为当前结点到终点的预估值(由于预估算法的选择有许多,使用时需要根据实际情况选择,而我们现在优先学习A星算法的思路,因此这里直接给出预估值 - 即 H 值) - 结点间的连线为相同直线,上面的数字代表线路的移动耗费值(即 G 值) - 任务:利用A星算法计算出路线
算法步骤
- 设起点 A ,将 A 加入 OPEN 表
- 寻找相邻可达点,计算出其 F 值,并加入 OPEN 表;若相邻点已经在 Open 表中,则判断其是否需要更新 F 值;若相邻点已经在 Close 表中,则跳过该点
- 将原父亲结点(A 结点)从 OPEN 表中删除,把它加入到 CLOSE 表中
- 从 OPEN 表中选择一个 F值最小的,然后将它作为父亲结点,继续处理其相邻结点
- 只要 Open 表不为空,则循环执行上述2、3、4步骤,发现相邻点是终点,则跳出循环。
- 当 Open 表为空,还没有找到终点,则说明起点不可达到终点
Just show me the code !
讲了那么多,理论知识总该要实践才行,建议大家先参考伪代码,理解好算法思路,自行尝试实现一番,再去看我那些半桶水的实现代码,一定会有更多收获的。
一段核心思路伪代码:
我的 Java 实现代码:
|
|
|
|
总结
相信大家动手实现后,就会对A*算法有个基本的认识啦,以上代码通过了几个简单的样例,但不排除会隐藏着奇怪的 Bug 噢,或者是一段有待改进的代码,欢迎大家指点指点。