萌新的資料結構與演算法3 A 演算法

2021-09-20 12:54:49 字數 3438 閱讀 9890

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 穩定性...