astar是一種深度優先啟發式尋路演算法,廣泛運用在遊戲領域。提起astar不得不提一下迪傑特斯拉演算法,它是一種廣度優先啟發式尋路演算法,俗稱閹割版的astar。因為大部分情況下astar的效率都比迪傑特斯拉高,我們只需要稍作了解就可以。
astar的原理,有一篇部落格寫的很詳細,萌新推薦一下
public class node
public int y
public int g;
public int h;
public int f;
public bool walkable;//該節點是否可移動
public node parent;
public node(int x, int y)
/// /// 清空節點上的消耗計算資料
///
public void clear()
}
這裡是4方向戰棋作為例子,如果8方向的話,4個頂點消耗應該高一些。
4方向戰棋4個方向消耗都是1。
/// /// 獲取周圍節點
///
///
///
public void getneighbour(listneighbournode, node startpoint)
if (startpoint.x + 1 < length)
if (startpoint.y - 1 >= 0)
if (startpoint.y + 1 < width)
}
/// /// 預估兩個點間的消耗 曼哈頓演算法
///
///
///
///
public int geth(node startpoint, node endpoint)
因為資料少,所以用氣泡排序會更快一些
/// /// 按f值氣泡排序
///
///
public void sortlistbyf(listlist)
for (int i = 0; i < list.count - 1; i++)}}
}
/// /// 尋路
///
///
///
///
public listfindpath(vector3int startpoint, vector3int endpoint)
openlist.add(startnode);
while (openlist.count > 0)
neighbournodes.clear();//清空
getneighbour(neighbournodes, startnode); //獲取周邊4個節點
foreach (node n in neighbournodes)
//如果該點不可移動
if (!n.walkable)
//消耗計算
int g = startnode.g + 1;
int h = geth(n, endnode);
int f = g + h;
//檢測是否已經探索過
if (openlist.contains(n))
}else
}openlist.remove(startnode);
closelist.add(startnode);//將該點加入關閉列表
}debug.log("no path");
return null;
}
尋路方法結束時,如果存在路徑的話,路徑儲存在節點node的煉表裡,我們還需要乙個方法取出路徑。
另外,取完路徑一定記得清空節點快取的fgh值,不然下次呼叫資料發生錯亂可能會宕機233
/// /// 得到路徑
///
///
///
public listgetpath(node path)
if (path.parent != null)
}pathlist.reverse();//逆向排序 這裡用棧去儲存路徑好了,棧結構剛好逆向輸出,用list反而麻煩了,這個優化就留給讀者好了
nodesclear(pathlist);//清空計算過程中快取的資料
return pathlist;
}/// /// 清理節點上的資料
///
///
public void nodesclear(listpaths)
}
戰棋遊戲中,角色的移動範圍搜尋就是astar的乙個變種。
有大佬和我討論說,如果角色移動力是3,就建立乙個7*7的範圍,然後去除掉曼哈頓值大於3的節點,就是移動範圍。這樣時間複雜度o(n)就能搞定。
實際上這麼考慮不全面,角色有可能被圍在乙個四面是牆的空間,即便牆外的曼哈頓值小於等於3也沒有辦法走過去。
所以,移動範圍還是考慮用astar去搜尋,攻擊範圍是穿透型的,直接用曼哈頓值計算就可以。
下面是**示例
/// /// 尋找移動範圍
///
///
///
///
public listfindmove(vector3int startpoint, int movepower)
srpgtile tile = terrain.gettile(new vector3int(n.x, n.y, 0));
//如果該點不可移動
if (!tile.walkable || n.unit != null || n.obj != null)
int g = startnode.g + 1;
//檢測是否已經探索過
if (openlist.contains(n))
continue;
}n.g = g;
n.parent = startnode;
if (n.g <= movepower)
}if (n.g < movepower)
}openlist.remove(startnode);//探索完畢 從開放列表中移除本次探索點
closelist.add(startnode);//將該點加入關閉列表
} while (openlist.count > 0);
nodesclear(moverange);
return moverange;
}
astar尋路 起點與終點距離太遠的時候,astar的計算量會非常大,可以考慮用四叉樹把地圖分割一下,結合astar尋路
四叉樹的介紹鏈結
完美收工
萌新的資料結構與演算法2 鍊錶基礎
嘗試寫了一下鍊錶的增刪改查,感覺難度不是很大,但一次寫出沒有bug的 還需要努力。萌新水平有限,優化可以改進或者寫錯了歡迎指出。建立鍊錶 node nodelistcreate int array 下個節點 node nextnode null 從後向前建立 for int i array.leng...
資料結構與演算法 3
非遞迴 o n logn 示例 mergesort 求陣列最小和問題 求陣列中 每個數左側所有比它小的數的和 的和 求降序對問題 陣列中每個數與其右側比它小的數組成的二元組 上題反過來即可 partition過程 給定乙個陣列arr,和乙個整數num,請把小於num的數放在陣列的左邊,大於num的數...
資料結構與演算法 排序演算法(3)
1 原理 將要排序的資料分到幾個有序的桶裡,每個桶裡的資料再進行排序。桶內的資料排序完畢之後,再把桶裡的資料依次取出,組成的序列就是有序的了。2 原地排序?屬於原地排序演算法。主要看桶內排序是否時原地排序演算法,若選擇插入排序,則桶排序就是屬於原地排序,若選擇了快速排序,則不屬於原地排序。3 穩定性...