轉載於:https://www.sohu.com/a/191037466_478315
比如像這樣子:
第一步:把起點放入OpenList
第二步:找出OpenList中F值最小的方格,即唯一的方格Node(1,2)作爲當前方格,並把當前格移出OpenList,放入CloseList。代表這個格子已到達並檢查過了。
第三步:找出當前格上下左右所有可到達的格子,看它們是否在OpenList當中。如果不在,加入OpenList,計算出相應的G、H、F值,並把當前格子作爲它們的“父親節點”。
圖中,每個格子的左下方數字是G,右下方是H,左上方是F。
Round2 ~ 第一步:找出OpenList中F值最小的方格,即方格Node(2,2)作爲當前方格,並把當前格移出OpenList,放入CloseList。代表這個格子已到達並檢查過了。
Round2 ~ 第二步:找出當前格上下左右所有可到達的格子,看它們是否在OpenList當中。如果不在,加入OpenList,計算出相應的G、H、F值,並把當前格子作爲它們的“父親節點”。
爲什麼這一次OpenList只增加了兩個新格子呢?因爲Node(3,2)是牆壁,自然不用考慮,而Node(1,2)在CloseList當中,說明已經檢查過了,也不用考慮。
Round3 ~ 第一步:找出OpenList中F值最小的方格。由於這時候多個方格的F值相等,任意選擇一個即可,比如Node(2,3)作爲當前方格,並把當前格移出OpenList,放入CloseList。代表這個格子已到達並檢查過了。
Round3 ~ 第二步:找出當前格上下左右所有可到達的格子,看它們是否在OpenList當中。如果不在,加入OpenList,計算出相應的G、H、F值,並把當前格子作爲它們的“父親節點”。
剩下的就是以前面的方式繼續迭代,直到OpenList中出現終點方格爲止。這裏就僅用圖片簡單描述了,方格中數字表示F值:
public Node aStarSearch(Node start, Node end) {
// 把起點加入 open list
openList.add(start);
//主循環,每一輪檢查一個當前方格節點
while (openList.size() > 0) {
// 在OpenList中查找 F值最小的節點作爲當前方格節點
Node current = findMinNode();
// 當前方格節點從open list中移除
openList.remove(current);
// 當前方格節點進入 close list
closeList.add(current);
// 找到所有鄰近節點
List<Node> neighbors = findNeighbors(current);
for (Node node : neighbors) {
if (!openList.contains(node)) {
//鄰近節點不在OpenList中,標記父親、G、H、F,並放入OpenList
markAndInvolve(current, end, node);
}
}
//如果終點在OpenList中,直接返回終點格子
if (find(openList, end) != null) {
return find(openList, end);
}
}
//OpenList用盡,仍然找不到終點,說明終點不可到達,返回空
return null;
}
幾點說明:
1.這裏對於A*尋路的描述做了很大的簡化。實際場景中可能會遇到斜向移動、特殊地形等等因素,有些時候需要對OpenList中的方格進行重新標記。
2.截圖中的小遊戲可不是小灰開發的,而是一款經典的老遊戲,有哪位小夥伴玩過嗎?