A star演算法優化二

2021-08-17 05:07:12 字數 1882 閱讀 9913

本文目的是對a*尋路演算法所生成的路徑進行一些人性化的調整,使其看起來不至於太機械化。關於a*演算法的原理與實現,讀者可以閱讀其他資料,這裡不再詳細闡述。

a*尋路演算法本質上是乙個有方向性的廣度優先搜尋演算法,它使用乙個估價函式,來估測可能的最短路徑,在每一次搜尋迭代完成後,選取其鄰接點中最優的乙個(即,距離終點最近的乙個點),作為下一次迭代的起點。如此反覆,直到找到終點。下面先列出估價函式的常規寫法:

設i點到起點的價值為s,到終點的估價為e,i點的總估價g等於s+e。s的值是確定的:

[cpp]view plain

copy

s = parent.s + 1(i點是其父節點的水平或垂直方向上的鄰接點)  

或  s = parent.s + sqrt(2))(i點是其父節點斜方向上的鄰接點)  

e點的值需要估算。精確一點的寫法:

[cpp]view plain

copy

水平距離:dx = abs(ix - ex)  

垂直距離:dy = abs(iy - ey)  

需要斜著走過的距離:v1 = min(dx, dy) * sqrt(2)  

需要直線走過的距離:v2 = max(dx, dy) - min(dx, dy)  

e =  v1 + v2  

粗略的寫法:

[cpp]view plain

copy

e = abs(ix - ex) + abs(iy - ey)  

a*尋路得到的結果是最優的,但不是唯一的,這源於兩點之間最近的路線可能不只一條。那麼問題就產生了,兩條最佳路線距離都相等的情況下,哪一條會更好?

(紅色是障礙,白色可通行,黑色是搜尋路徑)

如上圖所示,是a* 8方向搜尋得到的兩條距離相等的路線,但是左圖的路線在中間位置發生了「拐彎」,要比右圖的路線多乙個「拐彎」。如果路線上拐彎太多,人物行走的過程中,會出現頻繁轉向,從而出現「抖動」現象。所以,我們判定右圖路線優於左圖路線。針對這一問題,我們可以通過修改估價函式,來選擇「拐彎」更少的路線。

拐彎的問題,可以簡化成先盡可能的向乙個方向走,然後再考慮轉向。進一步簡化成,點越接近起點或是終點,越優先考慮。我們給e加上乙個干擾值factor,

[cpp]view plain

copy

factor = min(abs(ix - sx), abs(ix - ex)) + min(abs(iy - sy), abs(iy - ey))  

factor *= 0.01  

factor的值不能過大,否則會造成搜尋結果不是最短距離,因此適當的給factor乘上乙個縮放係數。

a*尋路的效果是抄近道,走捷徑。但對於遊戲體驗來說,這並不完全是件好事,放著寬闊的馬路不走,非得走懸崖峭壁,一不小心就跌落萬丈深淵,或者卡在岩石邊上。那麼,我們該如何避免這些現象呢?

同樣,我們可以通過修改估計函式做到。

我們給每一塊可走區域都加上乙個干擾值,越靠近障礙的可走區域,其干擾值越大。干擾值計算方法:

[cpp]view plain

copy

factor = 0  

for(x = -n; x <= n; ++x)  

}  }  我們甚至可以根據地表的材質來增加干擾值,比如山路和沼澤地帶明顯比馬路的干擾值大。

總之,我們可以調節估價函式來達到不同的效果。但是,也不能隨意修改,不良的估價函式,會增加搜尋成本。

軟體實習專案二 A Star演算法

實現的原理 建立next stemp函式,用來判斷0值下一步可以移動的方向 建立函式faction1,判斷移動後的方格是否為目標方格 建立函式faction2,判斷移動後的方格是否出現在open鍊錶和close鍊錶中 建立insert函式,將下一步未出現在open鍊錶和close鍊錶中的情況儲存在o...

演算法 Astar尋路演算法改進

早前寫了一篇 rcp gef智慧型尋路演算法 a star 出現了一點問題。在astar演算法中,預設尋路起點和終點都是n x n的方格,但如果用在路由上,就會出現問題。如果,需要連線的終點並不在方格的四角上,就產生了斜線。於是我們可以對終點附近的點重新做一點兒處理,原始碼如下所示 int size...

基於c 的A star演算法

資料 一 基礎原理 1 從起點開始,向周圍八個方向擴充套件。測試新擴充套件的點的路徑代價,路徑代價由已走的路徑和距離終點的期望加和而成。這個路徑代價是選擇路徑的標準。2 有兩個表open close。close 生成並且考察過的點,存在兩種點。一種是當前選擇的路徑,是最終想要的結果。另一種是考察但沒...