A*寻路算法与它的速度
如果你是一個游戲開發(fā)者,或者開發(fā)過一些關于人工智能的游戲,你一定知道A*算法,如果沒有接觸過此類的東東,那么看了這一篇文章,你會對A*算法從不知道變得了解,從了解變得理解。
我不是一個純粹的游戲開發(fā)者,我只是因為喜歡而研究,因為興趣而開發(fā),從一些很小的游戲開始,直到接觸到了尋路等人工智能,才開始查找一些關于尋路方面的文章,從而知道了A*算法,因為對于初期了解的我這個算法比較復雜,開始只是copy而已,現(xiàn)在我們一起來精密的研究一下A*算法,以及提高它的速度的方法。
一,A*算法原理
我看過Panic翻譯的國外高手Patrick Lester的一篇關于A*算法初探的文章,現(xiàn)在我就根據(jù)回憶,來慢慢認識A*算法的原理。
我們先來看一張圖
圖中從起點到終點,需要繞過一些遮擋,也許我們看的比較簡單,但是實際上,交給電腦來實現(xiàn)卻要經(jīng)過一番周折,電腦如何知道哪里有遮擋物,又是如何找到從起點到終點的最短路徑的呢?
了解這些,我們首先要知道一個公式:
F = G + H?
其中,F 是從起點經(jīng)過該點到終點的總路程,G 為起點到該點的“已走路程”,H 為該點到終點的“預計路程”。
A*算法,要從起點開始,按照它的算法,逐步查找,直到找到終點。
初期,地圖上的節(jié)點都是未開啟也未關閉的初始狀態(tài),我們每檢測一個節(jié)點,就要開啟一些節(jié)點,檢測完之后,要把檢測完的節(jié)點,就要把它關閉。
我們需要一個開啟列表和關閉列表,用來儲存已經(jīng)被開啟的節(jié)點和被關閉的節(jié)點。
這些就讓我們在實際過程中來深入了解吧。
看下面的圖
首先,我們來從起點出發(fā),開啟它周圍的所有點,因為遮擋是無法通過的,我們不去管它,這樣,被我們開啟的節(jié)點,就是圖中的三個節(jié)點,它們的父節(jié)點就是起點,所以圖中的箭頭指向起點,計算相應的FGH值,如圖所視,檢測完畢,將起點放入關閉列表。
這個時候,我們從被開啟的所有節(jié)點中查找F值最小的節(jié)點,做為下一次檢測的節(jié)點,然后開啟它周圍的點。
這時候起點左方和下方的F值都是70,我們根據(jù)自己的喜好選擇任意一個,這里先選擇下方的節(jié)點進行檢測。
如下圖
首先把未被開啟的剩下的節(jié)點的父節(jié)點指向檢測點。
已經(jīng)開啟的點,我們不去開啟第二遍,但是我們計算一下從檢測點到達它們的新的G值是否更小,如果更小則代表目前的路徑是最優(yōu)的路徑,那么把這個節(jié)點的父節(jié)點改為目前的檢測點,并重新計算這個點的FGH的值,全部檢測完畢之后,關閉檢測點,然后開始尋找下一個節(jié)點,如此循環(huán),直到找到終點。
然后從終點開始,按照每個節(jié)點的父節(jié)點,倒著畫出路徑,如下圖
?
?
這個就是A*算法的原理,說難倒是不難,但是對于初步接觸的人來說有點費勁而已。
?
二,A*算法的速度
前面,我們了解了A*算法的原理,發(fā)現(xiàn),在每次查找最小節(jié)點的時候,我們需要在開啟列表中查找F值最小的節(jié)點,研究A*的速度,這里就是關鍵,如何更快的找出這個最小節(jié)點呢?
1,普通查找算法
我們先來看看,最簡單的做法,就是每次都把開啟列表中所有節(jié)點檢測一遍,從而找到最小節(jié)點
[c-sharp]?view plaincopy
這里我用了一張很簡單的地圖來驗證此方法
運行結果如圖
我們看到,耗時38毫秒,其實這個數(shù)字是不準確的,我們權且當作參考
2,排序查找算法
顧名思義,這個算法就是,始終維持開啟列表的排序,從小到大,或者從大到小,這樣當我們查找最小值時,只需要把第一個節(jié)點取出來就行了
維持列表的排序,方法是在太多了,我的方法也許很笨,勉強參考一下吧,我們每次排序的同時,順便計算列表中的平均值,這樣插入新節(jié)點的時候,根據(jù)這個平均值來判斷從前面開始判斷還是從后面開始判斷
[c-sharp]?view plaincopy
運行結果如圖
我們看到,耗時25毫秒,這個數(shù)字雖然不準確的,但是與普通查找算法相比較,速度確實是提高了
3,二叉樹查找算法
(參考了火夜風舞的C++新霖花園中的文章)
這個算法可以說是A*算法的黃金搭檔,也是被稱為苛求速度的binary heap”的方法
就是根據(jù)二叉樹原理,來維持開啟列表的“排序”,這里說的排序只是遵循二叉樹的原理的排序而已,即父節(jié)點永遠比子節(jié)點小,就像下面這樣
?? 1
|??? |
5??? 9
|?? |? |
7? 12 10
二叉樹每個節(jié)點的父節(jié)點下標 = n / 2;(小數(shù)去掉)
二叉樹每個節(jié)點的左子節(jié)點下標 = n * 2;右子節(jié)點下標 = n * 2 +1
注意,這里的下標和它的值是兩個概念
[c-sharp]?view plaincopy
運行結果如圖
我們看到,耗時15毫秒,速度是這三個方法里最快的,但是因為這個數(shù)字是不夠準確的,實際上,用二叉樹查找法,會讓A*算法的速度提高幾倍到10幾倍,在一些足夠復雜的地圖里,這個速度是成指數(shù)成長的。
4,總結
得出結論,用了A*算法,就要配套的用它的黃金搭檔,二叉樹,它可以讓你的游戲由完美走向更完美。
總結
以上是生活随笔為你收集整理的A*寻路算法与它的速度的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 理解A*寻路算法具体过程
- 下一篇: A* 寻路算法