網上有關a*演算法的文章已經非常豐富了,各種語言各種思路都有,本來我實在不想再寫一篇,,但因為最近工作動盪因此專門抽空又看了一下,然後就想寫個文章防止以後印象模糊,好歹看自己寫的東西可以很快回憶起來。如果是初次接觸a*演算法的朋友可以先看看這篇參考文章,我這邊只是做乙個總結,然後先貼上我之前的筆記吧:
二維陣列map資料:
0=可通過的格仔,s=起點,e=終點,b=障礙物
基礎定義:g=目標點到起點的步長總和 h=目標點到終點的步長總和(曼哈頓距離),f=兩總和之和
定義:openlist,closelist,current,adjacentcube,g(步長,這個例子假定為1)
1.將起點a加入到openlist中,遍歷openlist,每次取最小f值的item,將其賦值給current,隨後將這個item從openlist中刪除,加入到closelist(例子中在這裡遍歷closelist中是否存在目標點,有的話則立刻break,我個人覺得沒必要每次都遍歷,直接判斷取到的current是否目標路徑即可)。
2.獲取到該item四周的item(需要判斷map該位置是否為"0"或"e",否則過濾,因為障礙物和邊緣不能加入尋路openlist中),設定x和y並insert入adjacentcube中。
3.遍歷adjacentcube,檢查每個item是否已存在於openlist中,兩種情況:
(1.)已存在openlist中,則判斷如果current的g值+g步長和大於這個item的g值的話,則將這個item的parent置為current,同時將這個item的g值更新為current父物體的g值+g步長(主要是找乙個相對最短的路徑,因為最短路徑最終需要從終點通過parent回溯,而不是正向尋找一遍就結束了)。
(2.)未存在openlist中,則設定這個item的各種屬性值(g,h,f)以及parent,然後將其insert入openlist中。
4.重複以上步驟,直到找到目標點則break隨後開始回溯輸出。回溯的過程比較簡單,因為之前有記錄parent,所以當前current的parent已經記錄了一條最短的路徑。
然後如果你看過原文章的**的話可能會發現那個變數g會有問題,原始碼每次openlist遍歷一次g值就會+1,但是有可能會有一種情況就是順著乙個格仔c的周圍的其中一條路徑走了一段發現是錯誤的(即f值不再是openlist中最小的),這時需要繼續從openlist中重新找最小f值的item繼續找找新的路徑,假如此時找到了之前c格仔周圍的另乙個格仔的f值最小,此時就需要從這裡重新走新的路徑,新找到的這個格仔的g值當然也應該重新變回之前c格仔的g+g步長(這個例子中步長為1),而不是一直自加。下面我會上我修改後的**,在修改的地方都有加注釋,你可以去掉原始碼的注釋然後注釋掉我的**測試一下兩者的區別,我這裡上一下圖,在我之前說的這個例子中兩個**的執行結果:
原始碼:
可以看到搜尋的路徑差距很大,我的這個執行結果我能看懂,因為從起點到終點最大的f值只有80,而周圍檢索不到的點f值都達到了100所以不遍歷,但是原始碼的這個。。遍歷了這麼大的範圍說實話我是有點矇圈的,可能是因為原文章作者的那個路徑比較簡單看不太出問題,我大概想了一會沒想通,就先不糾結啦,反正肯定是和g值這個問題脫不了干係的。
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
namespace astarpathfindingtest
class program
;static void drawmaptoconsole()
}static void main(string args)
;var target = new location ;
var openlist = new list();
var closedlist = new list();
//修改處,g變為只表示步長
//int g = 0;
int g = 1;
// start by adding the original position to the open list
openlist.add(start);
while (openlist.count > 0)
else}}
}// assume path was found; let's show it
while (current != null)
console.readkey();
}static listgetwalkableadjacentsquares(int x, int y, string map)
,new location ,
new location ,
new location ,
};return proposedlocations.where(
l => map[l.y][l.x] == '0' || map[l.y][l.x] == 'e').tolist();
}static int computehscore(int x, int y, int targetx, int targety)}}
C 實現網路尋路
x 國的乙個網路使用若干條線路連線若干個節點。節點間的通訊是雙向的。某重要資料報,為了安全起見,必須恰好被 兩次到達目的地。該包可能在任意乙個節點產生,我們需要知道該網路中一共有多少種不同的 路徑。源位址和目標位址可以相同,但中間節點必須不同。如圖1所示的網路。1 2 3 1 是允許的 1 2 1 ...
js實現A 尋路演算法
onload function cc.log this.searchroad map,0,0,4,4 傳入變數屬性,起始點座標和目標的座標。整個 執行後,列印出的是起始點到目標點最近路徑的座標 其中的map.arr是二維陣列 searchroad function map,start x,start...
迷宮尋路(A星尋路演算法)
題目 假設我們有乙個7 5大小的迷宮,如下圖所示,綠色格仔表示起點,紅色的格仔表示終點,中間的3個深灰色格仔表示障礙物。請找到一條從起點到終點最短的路徑。解題思路 需要引入兩個集合和乙個公式,如下 具體步驟 把起點放入openlist 檢查openlist中是否有值,如果沒有則無法到達終點,結束尋路...