A星详解Word文件下载.docx
- 文档编号:21045994
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:8
- 大小:24.54KB
A星详解Word文件下载.docx
《A星详解Word文件下载.docx》由会员分享,可在线阅读,更多相关《A星详解Word文件下载.docx(8页珍藏版)》请在冰豆网上搜索。
8_|1`_Tn}o
W3^_zIj
f(n)=g(n)+h(n)
w-UKMW9"
6ex_RS]BI
其中f(n)是节点n的估价函数,g(n)实在状态空间中从初始节点到n节点的实际代价,h(n)是从n到目标节点最佳路径的估计代价。
在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。
如果说详细点,g(n)代表了搜索的广度的优先趋势。
但是当h(n)>
>
g(n)时,可以省略g(n),而提高效率。
这些就深了,不懂也不影响啦!
我们继续看看何谓A*算法。
%4j&
H!
y-w;
Uh>
.v|P6
二、初识A*算法:
__N_A+_&
jV
CV___s8s
启发式搜索其实有很多的算法,比如:
局部择优搜索法、最好优先搜索法等等。
当然A*也是。
这些算法都使用了启发函数,但在具体的选取最佳搜索节点时的策略不同。
象局部择优搜索法,就是在搜索的过程中选取“最佳节点”后舍弃其他的兄弟节点,父亲节点,而一直得搜索下去。
这种搜索的结果很明显,由于舍弃了其他的节点,可能也把最好的节点都舍弃了,因为求解的最佳节点只是在该阶段的最佳并不一定是全局的最佳。
最好优先就聪明多了,他在搜索时,便没有舍弃节点(除非该节点是死节点),在每一步的估价中都把当前的节点和以前的节点的估价值比较得到一个“最佳的节点”。
这样可以有效的防止“最佳节点”的丢失。
那么A*算法又是一种什么样的算法呢?
其实A*算法也是一种最好优先的算法。
只不过要加上一些约束条件罢了。
由于在一些问题求解时,我们希望能够求解出状态空间搜索的最短路径,也就是用最快的方法求解问题,A*就是干这种事情的!
我们先下个定义,如果一个估价函数可以找出最短的路径,我们称之为可采纳性。
A*算法是一个可采纳的最好优先算法。
A*算法的估价函数克表示为:
pJd0k"
_{_
|Dg;
__(i?
_
f’(n)=g’(n)+h’(n)
(YIhTSL"
]
xY|yI>
这里,f’(n)是估价函数,g’(n)是起点到终点的最短路径值,h’(n)是n到目标的最短路经的启发值。
由于这个f’(n)其实是无法预先知道的,所以我们用前面的估价函数f(n)做近似。
g(n)代替g’(n),但g(n)>
=g’(n)才可(大多数情况下都是满足的,可以不用考虑),h(n)代替h’(n),但h(n)<
=h’(n)才可(这一点特别的重要)。
可以证明应用这样的估价函数是可以找到最短路径的,也就是可采纳的。
我们说应用这种估价函数的最好优先算法就是A*算法。
哈!
你懂了吗?
肯定没懂!
接着看!
[#___0Yt/G
E&
Bn8L~_O
举一个例子,其实广度优先算法就是A*算法的特例。
其中g(n)是节点所在的层数,h(n)=0,这种h(n)肯定小于h’(n),所以由前述可知广度优先算法是一种可采纳的。
实际也是。
当然它是一种最臭的A*算法。
_WE_"
)xhV6
_W}>
=JoN^J
再说一个问题,就是有关h(n)启发函数的信息性。
h(n)的信息性通俗点说其实就是在估计一个节点的值时的约束条件,如果信息越多或约束条件越多则排除的节点就越多,估价函数越好或说这个算法越好。
这就是为什么广度优先算法的那么臭的原因了,谁叫它的h(n)=0,一点启发信息都没有。
但在游戏开发中由于实时性的问题,h(n)的信息越多,它的计算量就越大,耗费的时间就越多。
就应该适当的减小h(n)的信息,即减小约束条件。
但算法的准确性就差了,这里就有一个平衡的问题。
可难了,这就看你的了!
_^\:
_yf.k
Uh.Sc:
trA
好了我的话也说得差不多了,我想你肯定是一头的雾水了,其实这是写给懂A*算法的同志看的。
哈哈!
你还是找一本人工智能的书仔细看看吧!
我这几百字是不足以将A*算法讲清楚的。
只是起到抛砖引玉的作用希望大家热情参与吗!
@44_P_4_?
;
h4__Ia>
^@_
预知A*算法的应用,请看《深入A*算法》。
Z__v4_<
b
|q__!
._a
第二部分:
深入A*算法———浅析A*算法在搜索最短路径中的应用#XI"
@_pD__
a_zo0{`S?
一、前言
:
mpiAs<
%U"
GAQ'
Ti1!
在这里我将对A*算法的实际应用进行一定的探讨,并且举一个有关A*算法在最短路径搜索的例子。
值得注意的是这里并不对A*的基本的概念作介绍,如果你还对A*算法不清楚的话,请看姊妹篇《初识A*算法》。
1TjZ#yP%1
yG&
2U_q_X
这里所举的例子是参考AMIT主页中的一个源程序,你可以在AMIT的站点上下载也可以在我的站点上下载。
你使用这个源程序时,应该遵守一定的公约。
_5_lTD]d_
B,_
`btJ_h
二、A*算法的程序编写原理
KFDS_q_"
j
(R'
+_j_WH
我在《初识A*算法》中说过,A*算法是最好优先算法的一种。
只是有一些约束条件而已。
我们先来看看最好优先算法是如何编写的吧。
rGlRAn#?
_
_zoP_%u,XL
如图有如下的状态空间:
(起始位置是A,目标位置是P,字母后的数字表示节点的估价值)
F___tv8@l
@(:
___v__l
搜索过程中设置两个表:
OPEN和CLOSED。
OPEN表保存了所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
算法中有一步是根据估价函数重排OPEN表。
这样循环中的每一步只考虑OPEN表中状态最好的节点。
具体搜索过程如下:
t`G)
b&
3_O
9vI]L_fP
1)初始状态:
S#8>
Zw_Q
OPEN=[A5];
CLOSED=[];
_P6=~q3k
2)估算A5,取得搜有子节点,并放入OPEN表中;
5P_ZN^\^__
OPEN=[B4,C4,D6];
CLOSED=[A5]0JYWrP_R
3)估算B4,取得搜有子节点,并放入OPEN表中;
_"
X__n%at4
OPEN=[C4,E5,F5,D6];
CLOSED=[B4,A5]I,O#X)O|i_
4)估算C4;
取得搜有子节点,并放入OPEN表中;
2~c~{jl_\
OPEN=[H3,G4,E5,F5,D6];
CLOSED=[C4,B4,A5]___>
UHa
5)估算H3,取得搜有子节点,并放入OPEN表中;
I*\_^_,ow_
OPEN=[O2,P3,G4,E5,F5,D6];
CLOSED=H3C4,B4,A5]|(_%u}V?
6)估算O2,取得搜有子节点,并放入OPEN表中;
SK_XD^O_H
OPEN=[P3,G4,E5,F5,D6];
CLOSED=[O2,H3,C4,B4,A5]ijUzC>
O_+q
7)估算P3,已得到解;
Llz[_'
"
_m
看了具体的过程,再看看伪程序吧。
算法的伪程序如下:
_ii4B?
__E_
rZwB>
__c
Best_First_Search()_p!
W[X%`
)
{:
q+N&
j'
3_
Open=[起始节点];
Closed=[];
RK_Tb'
3H
while(Open表非空)+,flE=5]s
{G?
hK9@|_v
从Open中取得一个节点X,并从OPEN表中删除。
"
="
O_>
__
if(X是目标节点)/_"
#4T^7&
{;
b%_{ilx:
求得路径PATH;
返回路径PATH;
uJow7-FD_
}H__;
KDZO9W
for(每一个X的子节点Y)Hi,t@_!
_!
{%|"
Qi]c_d
if(Y不在OPEN表和CLOSE表中)_w_2"
_]Pl
{>
bm|%_O_u"
求Y的估价值;
并将Y插入OPEN表中;
//还没有排序_}NmNanW^
}&
a)vdlZSE=
else'
_Z8aPH_D
if(Y在OPEN表中)J)
x3\[}Ye
{3C^1f_rF_
if(Y的估价值小于OPEN表的估价值)mP}#Cc_ji?
更新OPEN表中的估价值;
_lpC_@I^:
}
_B@K__[3
else//Y在CLOSE表中y_p]@_^TN
{"
^r__Nr_
if(Y的估价值小于CLOSE表的估价值)_LI_W*4r!
{C_lU_Sr_Sp
更新CLOSE表中的估价值;
=n_R__uY'
从CLOSE表中移出节点,并放入OPEN表中;
_._5Z_EO
}b:
MG@H_xc_
}3N4.$#>
#9@
将X节点插入CLOSE表中;
9_6Z_dM=
按照估价值将OPEN表中的节点排序;
!
_]b@RU__U
}//endfork
BsXfVs_9
}//endwhile!
:
us!
s___
}//endfunc])_T/_sO#'
b|?
h2_1rG
啊!
伪程序出来了,写一个源程序应该不是问题了,依葫芦画瓢就可以。
A*算法的程序与此是一样的,只要注意估价函数中的g(n)的h(n)约束条件就可以了。
不清楚的可以看看《初识A*算法》。
好了,我们可以进入另一个重要的话题,用A*算法实现最短路径的搜索。
在此之前你最好认真的理解前面的算法。
不清楚可以找我。
我的Email在文章尾。
HeIS;
g_fUY
_|_B[__eJq
三、用A*算法实现最短路径的搜索
_JP_=Z_U_u
bkv/I{C>
_?
在游戏设计中,经常要涉及到最短路径的搜索,现在一个比较好的方法就是用A*算法进行设计。
他的好处我们就不用管了,反正就是好!
^_*
bZ5n_,KQA5
^.HWk_S`e
%z)EO9vt_r
注意下面所说的都是以ClassAstar这个程序为蓝本,你可以在这里下载这个程序。
这个程序是一个完整的工程。
里面带了一个EXE文件。
可以先看看。
p_\D_>
z("
)f*Iomp]@
先复习一下,A*算法的核心是估价函数f(n),它包括g(n)和h(n)两部分。
g(n)是已经走过的代价,h(n)是n到目标的估计代价。
在这个例子中g(n)表示在状态空间从起始节点到n节点的深度,h(n)表示n节点所在地图的位置到目标位置的直线距离。
啊!
一个是状态空间,一个是实际的地图,不要搞错了。
再详细点说,有一个物体A,在地图上的坐标是(xa,ya),A所要到达的目标b的坐标是(xb,yb)。
则开始搜索时,设置一个起始节点1,生成八个子节点2-9因为有八个方向。
如图:
_0__dt"
ZSm
A*0_*s__Z0
仔细看看节点1、9、17的g(n)和h(n)是怎么计算的。
现在应该知道了下面程序中的f(n)是如何计算的吧。
开始讲解源程序了。
其实这个程序是一个很典型的教科书似的程序,也就是说只要你看懂了上面的伪程序,这个程序是十分容易理解的。
不过他和上面的伪程序有一些的不同,我在后面会提出来。
B,y3]g6u
w_n84?
$BGd
先看搜索主函数:
_rjBc_;
a
+x_]e-P%
voidAstarPathfinder:
FindPath(intsx,intsy,intdx,intdy)^!
u_O(B&
{RV92qnB_
NODE*Node,*BestNode;
P"
Rk_?
_lL
intTileNumDest;
_R____Kk"
//得到目标位置,作判断用+_Ag#B_*_
TileNumDest=TileNum(sx,sy);
{6tx,;
r(F
//生成Open和Closed表_T_&
*_eOr
OPEN=(NODE*)calloc(1,sizeof(NODE));
g&
>
mP?
CLOSED=(NODE*)calloc(1,sizeof(NODE));
W_D%|Ub2X
//生成起始节点,并放入Open表中my=_~"
bw_4
Node=(NODE*)calloc(1,sizeof(NODE));
_LOt#1_Qv
Node->
g=0;
9Burj_G1k?
//这是计算h值oHRbAE^_
h=(dx-sx)*(dx-sx)+(dy-sy)*(dy-sy);
//shouldreallyusesqrt().+}Auk|>
_Dc
//这是计算f值,即估价值5Wl,J_<
F_
f=Node->
g+Node->
h;
C}bPv+_t
NodeNum=TileNum(dx,dy);
i&
5!
9m`_Cw
x=dx;
_.Btv}__b
y=dy;
ur`}_v_|ZY
OPEN->
NextNode=Node;
//makeOpenListpointtofirstnode5u_"
nxT_
for(;
)_W*|O_Oa'
{//从Open表中取得一个估价值最好的节点0n7_Hk_Do_
BestNode=ReturnBestNode();
j_Cam,$o_E
//如果该节点是目标节点就退出_}.w#__X_
if(BestNode->
NodeNum==TileNumDest)//ifwe’vefoundtheend,breakandfinishWJBW:
2=;
break;
_!
~____Ax_
//否则生成子节点%_y!
____
GenerateSuccessors(BestNode,sx,sy);
{8l_d:
ZP_
}z[__R"
+_
PATH=BestNode;
%k_aTQ"
PB
}=k_yJaT^5[
再看看生成子节点函数GenerateSuccessors:
m3h2/}_%9`
GenerateSuccessors(NODE*BestNode,intdx,intdy)_Y*h`_),_
{p
I__M*c6
intx,y;
1_gf/#+$\
//哦!
依次生成八个方向的子节点,简单!
o_X_
%PsS
//Upper-Leftox_xE'
cx{g
if(FreeTile(x=BestNode->
x-TILESIZE,y=BestNode->
y-TILESIZE))6i*p+S?
U"
GenerateSucc(BestNode,x,y,dx,dy);
N9fUlXhR_
//UpperY_2ah__zB
x,y=BestNode->
y-TILESIZE))!
_"
_I_Nmz
b[_Q_C
M/_
//Upper-Right6c;
`
__C
x+TILESIZE,y=BestNode->
y-TILESIZE))z[<
_p_i_:
c@_"
___i_?
//Right10QNV=yK7s
y))_B7x"
ef_
pKGUM__
//Lower-Right_~-o^eI_4_
y+TILESIZE))qjda_hV_Y_
S^sW._(_I
//Lower__]pucv!
y+TILESIZE))Qn_u&
GB__M
[fJFH^&
?
hr
//Lower-Leftd$G%F$BTs
y+TILESIZE))/:
__c_,v-
FrQ-_v]_c
//Left@bVh?
T0~F,
y))JOoLH_ZQ1v
_T_VE_F+t
}(>
@syF%PB_
_[_cT,_3_
看看最重要的函数GenerateSucc:
uq1(yyWp(_
GenerateSucc(NODE*BestNode,intx,inty,intdx,intdy)m_{=~|_I_
{g_T_\y&
_
intg,TileNumS,c=0;
w<
^2h}__5
NODE*Old,*Successor;
o_\V_4qekk
//计算子节点的g值6W#F__Ss~
g=BestNode->
g+1;
//g(Successor)=g(BestNode)+costofgettingfromBestNodetoSuccessorp]IhQnj2__
TileNumS=TileNum(x,y);
//identificationpurposes1*`Jc_Un,>
//子节点再Open表中吗?
LRlk9:
QD>
if((Old=CheckOPEN(TileNumS))!
=NULL)//ifequaltoNULLthennotinOPENlist,elseitreturnstheNodeinOld___._
{|k9j)H_g(
//若在hI#M{cz__
for(c=0;
c<
8;
c++)if(BestNode->
Child[c]==NULL)//AddOldtothelistofBestNode’sChildren(orSuccessors).__T_KutO0
4F__c1_'
BestNode->
Child[c]=Old;
uN^qfJ'
@>
//比较Open表中的估价值和当前的估价值(只要比较g值就可以了)r__V_W'
_KN
if(gg)//ifournewgvalueisParent=BestNode;
s17gi_,"
X
Old->
g=g;
xB_]_v_
f=g+Old->
~G^do
j3|+
}__'
cc4Y~0s
}_BA_lkN+_D
else//在Closed表中吗?
f9bz:
_;
W__
if((Old=CheckCLOSED(TileNumS))!
=NULL)//ifequaltoNULLthennotinOPENlist,elseitreturnstheNodeinOld_Qn_Af_A%
{g_Q_t_@xNO
//若在8WQ%rN_={8
c<
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 详解