A*搜索算法

作为程序员的我们可能经常会听到 A*搜索算法这个的词,听起来非常高大上,腻害,但是具体是什么呢?

引用 Wiki 上的说法就是:
A* 搜索算法(A* search algorithm)是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。常用于游戏中的NPC的移动计算,或网络游戏的BOT的移动计算上。

该算法综合了最良优先搜索Dijkstra算法的优点:在进行启发式搜索提高算法效率的同时,可以保证找到一条最优路径(基于评估函数)。

在此算法中,如果以 g ( n ) g(n) g(n) 表示从起点到当前顶点 n n n 的实际距离, h ( n ) h(n) h(n)表示当前顶点 n n n 到目标顶点的估算距离(根据所采用的评估函数的不同而变化),那么A*算法的估算函数为:

f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)

f ( n ) f(n) f(n):代表了该节点的综合预估值,值越小,到达目标的成本就越小,所以访问的时候尽量优先考虑最小的。

这里的 h ( n ) h(n) h(n)值可以采用 欧几里得距离曼哈顿距离切比雪夫距离等公式计算而来。

具体分析如下:

如图:
在这里插入图片描述
这里以 绿色(2,1) 为起点, 红色(2,5) 为终点, 蓝色 格子为障碍物,这里的邻居节点只考虑上下左右4个四个方向。

路径搜索过程如下:
1. 首先需要创建两个集合,一个存储待访问的节点(nodeLists),一个存储已经访问过的节点(visitedNodeLists)
2. 添加 起点(2,1)nodeLists 列表,并且计算该点的预估值

这里就需要用到上面讲到的预估函数了,
f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)
我们可以很清楚的看到,起点到当前节点的距离为0,即: g ( n ) = 0 g(n)=0 g(n)=0
而当前顶点(2,1)到目标顶点(2,5)的距离为4,即: h ( n ) = 4 h(n)=4 h(n)=4

这里的h值可以采用 曼哈顿距离公式 计算得来:
h = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ h = |x_1-x_2|+|y_1-y_2| h=x1x2+y1y2

这里需要注意的是: h h h 值是在不考虑障碍的情况下计算的

3. 查找nodeLists预估值最小的节点,作为当前访问的节点,并且从nodeLists 删除 该节点。
4. 获取 当前节点 的 邻居节点,计算出他们的预估值 并且添加到nodeLists列表中。

如图:
在这里插入图片描述
这里只考虑上下左右4个方位,并且分别计算了他们的各个预估值,
右下角: h ( n ) h(n) h(n)
左下角: g ( n ) g(n) g(n)
左上角: f ( n ) f(n) f(n)

除了计算预估值,我们还需要把当前节点作为每个邻居节点的父节点,以便为了后面确定最终的路线。

这里需要注意的是:我们在添加到 待访问列表之前需要处理一下边界问题,并且判断一下是否是障碍物,如果是就不需要添加到列表中。

5. 把当前节点添加到visitedNodeLists中,代表已经访问过了。
6. 重复以上步骤 3 - 5 ,直到找到目标节点位置为止。
7. 循环输出 最终节点的父节点,就是我们需要的路径了。

以上就是该算法的大致流程。

伪代码如下:
function startSearch(){
	//把起点添加到nodeLists
	nodeLists.push(startNode);
	//循环
	while (nodeLists.length > 0) {
		//查找预估值最小的节点
	    let currentNode = findMinNode();
	    //获取并且添加邻居节点到待访问列表
	    findAndAddNeighborNode(currentNode);
	    //把当前节点添加到已访问列表
	    visitedNodeLists.push(currentNode);
	    //判断是否是目标节点
	    if (this.isTarget(currentNode)) {
	        return currentNode
	    }
	}
	return null
}

基于Cocos Creator JS的A*算法的Demo下载链接

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值