一、遊戲程式的靈魂——演算法
程式=資料結構+演算法
程式語言(如c++)是一種工具,而演算法是程式的靈魂。
資料結構和演算法在遊戲程式中應用得很廣,可以說無處不在。而且一般遊戲對程式的效率要求很高,因此能否成為出色的遊戲程式設計師很大程度取決於能否編寫出高效的演算法。以《魔獸世界》為例,在遊戲中,獵人的寵物跟敵人一「碰」上,戰鬥便一觸即發。在程式裡是利用碰撞演算法來判斷是否有碰撞發生的。當然,像《魔獸世界》這類遊戲不需要精確的碰撞檢測,只要很簡單的碰撞演算法就能應付了,但像一些飛行模擬遊戲就需要精確的碰撞檢測了;現在換乙個場景,你在如畫的遊戲世界裡休閒地散步,很不幸,乙隻妖怪盯上了你,而且它足夠聰明,它會選擇一條最短的路徑向你殺過去。為什麼這只妖怪那麼聰明?這就是a*(讀a星)演算法的魔力,a*演算法是一種尋找最短的路徑的尋路演算法。這類例子在遊戲中比比皆是,大家在玩遊戲時可以多加留意。
目前為止,被設計出來而又應用廣泛的演算法有很多,如貪婪演算法、遺傳演算法和一些常用的排序演算法等等。下面,向大家介紹遊戲中用得最多的演算法——排序演算法。
我們知道,在遊戲場景裡,在近處的遊戲角色會遮擋住遠處的角色。要做到這一點,一種方法是可以把所有的角色按它們的座標值進行排序,然後以遠到近把玩家「放」入到遊戲場景裡。常用的排序演算法有四種:選擇排序、氣泡排序、插入排序和快速排序。以下我們僅以最簡單的氣泡排序法為例來加深大家對演算法的理解。
對一組有n個元素的陣列,我們把它的每乙個元素想象成乙個泡泡。從最底部的元素開始,將各相鄰的元素進行比較,若下面的元素大於上面的元素時,則把它們的值進行交換,即較大的元素將「往上冒泡」。如此類推,我們將要進行n-1次的「冒泡」。
template < class t >
void bubbli_sort( t a, int n )
}i = last_pos;}}
二、遊戲資料的大管家——資料結構
資料結構是什麼呢?這是乙個很抽象的概念,沒有統一的名詞解釋。你可以把它理解為資料在
計算機中的組織形式。經典的資料結構,在網路遊戲中都能得到體現。下面我們為大家舉例並介紹。
1.道具包管理——線性表
在任何網路遊戲中,你的道具包裡也會放著許多珍貴的道具。在程式中需要把這些資料組織起來,方便管理。使用線性表可以簡單方便地做到。線性表是一組元素以線性的結構組織起來,如(
e1,e2,…en)。線性表一般分為陣列與鍊錶兩類。
陣列裡的元素以連續的
記憶體空間存放,因此可以用記憶體位址檢索到對應的資料元素,訪問元素很方便。但如果要進行插入/刪除資料元素,就要做一些記憶體移動了,效率比較低。而鍊錶的資料元素存放在任意的物理記憶體位置,相鄰的元素以指標作為「鏈扣」串連起來。如單向鍊錶,元素
e1有乙個指標指向它的後繼節點
e2,這個指標就是它們之間的「鏈扣」。當進行插入/刪除資料元素時,只要改變相應的「鏈扣」就可以,不需要做記憶體移動,效率相對於陣列要高。
2.任務管理——佇列與堆疊
我在開始玩《夢幻西遊》時,在城裡走了幾圈就接了滿身的任務。這讓我很煩惱,不知從哪個任務開始做起,這時我想到了佇列。佇列是一種「先進先出(first-in-first out, fifo)」的資料結構。就好像是在銀行裡排隊,排在前面的先服務。每次接到任務就把該任務壓進任務佇列裡,要做任務時就從任務佇列裡取出乙個任務,這樣哪個任務先接到就先做哪個任務。
也許你不喜歡這樣方式,你想做乙個賞金獵人,哪個任務報酬多的就先做哪個任務。這樣普通的佇列就滿足不了你的需求了,你需要的是優先順序佇列。優先順序佇列在插入元素時,優先高的元素插入佇列前面。把任務的報酬設成是優先順序資料,那麼你每次在任務佇列裡取出任務時,就能保證這個任務是你現接的任務裡報酬最高的。
堆和棧在概念上不大一樣,這裡所說的堆疊是指棧(stack)。棧是一種「先進後出」的資料結構。就好像是疊盤子,疊在最上面的盤子最先拿來使用。佇列和堆疊可能是使用頻率最高的資料結構了。在匹配表示式應用中,堆疊發揮了巨大的作用。還有經典的漢諾塔
問題,如果沒有堆疊的幫助,你可不知道要搬碟子搬到什麼時候了。這裡我想舉乙個word的例子,這個例子比較形象。誰都會有失誤,在word裡發生了誤操作一點也不需要驚慌,因為word有「撤消」的功能,可以撤消你之前的操作。把使用者的操作壓入棧裡,要撤消操作時就從棧彈出最近發生的操作。這樣可以很方便地實現這個功能。
3.遊戲選單設計——樹
樹跟以上介紹的資料結構不一樣,樹是一種非線性的資料結構。樹的實現與應用都要比線性資料結構複雜,c++標準庫也沒有實現樹這種資料結構。但其實樹的應用很廣泛,很常用到,但是由於它的複雜性,很多程式設計師都迴避使用。如果能有效地使用樹,你的程式效率將會得到很大的提高。如圖1是一棵簡單的樹的邏輯結構。
樹跟線性資料結構不同,它的每乙個節點可以有0個或多個後繼。在圖1這棵樹中,節點a是整棵樹的根,它沒有前驅節點。b、c、d是a的孩子,b、c、d這幾個節點是兄弟。
樹在應用時分很多種型別,我們在這裡只介紹二叉樹。二叉樹對後繼節點進行了一項約束——每個二叉樹的節點最多只能有二個後繼節點。紅黑樹是一種特殊的二叉樹,c++標準庫的set和map就是用紅黑樹實現的,因此它們的排序查詢效率很高。
由於樹是一種非線性的資料結構,因此它對元素的遍歷並不像線性資料結構那麼簡單。二叉樹一般常用的有三種遍歷演算法:前繼遍歷、中繼遍歷和後繼遍歷。前繼遍歷先訪問父節點,然後是左節點,右節點;中繼遍歷先訪問左節點,再到父節點,最後是右節點;後繼遍歷先訪問左節點,再到右節點,最後是父節點。
4.地圖資料管理——圖
圖是一種複雜的資料結構,相對於樹要複雜一些。跟樹一樣,圖是一種非線性的資料結構,c++標準庫同樣沒有實現圖。圖就像乙個網一樣,各個節點用邊線連線起來,每條邊線有乙個權值,可以理解成兩個節點間的距離。圖2是乙個圖的資料結構。研究圖對遊戲開發很有意義,遊戲地圖是圖的應用的乙個很好的例子。遊戲中的地圖一般會被分成一塊塊的格仔,每一塊都會有乙個座標值。那麼可以使用二維陣列把地圖的資料記錄起來,這是最簡單的方法。但大家都知道,魚與熊掌是不能兼得的,這種方法只能用在很小型的地圖,而較專業的做法是使用圖記錄地圖資料,圖的每乙個節點對應的是地圖的乙個座標。
圖的標準搜尋演算法有兩種:廣度優先搜尋與深度優先搜尋。廣度優先搜尋從開始節點的周圍節點一層一層地往外搜尋;深度優先搜尋以開始節點為始點對一條路徑搜尋到盡頭後再搜尋另一條路徑,直到所有的路徑都搜尋完為止。
圖論是一門很大的課題,有興趣的讀者可以找相關的專業書籍進行深入研究。
三、正確的學習途徑
學習資料結構與演算法是很枯燥乏味的,但不要想找什麼捷徑,只有理解後反覆上機練習、練習再練習!使用過stl(c++標準模板庫)的讀者可能會問:既然已經有人幫我們實現了各種資料結構與演算法,為什麼還要自己去學習呢?我們要學習的是蘊涵在資料結構與演算法中的思想。我們要理解的是「為什麼要這樣做」,而不只是停留在「怎樣做」,只有理解了這些思想,才能寫出更加合理、高效的程式。
學習資料結構從最簡單的出發,你需要花乙個星期的時間在陣列線性表,它的難點主要是在插入資料和刪除資料;鍊錶比陣列要難一點,但單向鍊錶的話也是只要乙個星期的時間學習,然後再花乙個星期學習雙向鍊錶向強化練習;佇列和堆疊是很常用的資料結構,你要花兩個星期的時間好好理解一下。然後就是樹了,從二叉樹開始學起,大概要兩個星期的時間;最後是圖,也是最難的,但有了之前的知識作基礎,相信你也只要兩個星期的時間去學習。資料結構學習得差不多了,加以應用吧,最後花乙個月的時間好好研究一下各種演算法。
《資料結構、演算法與應用——c++語言描述》
本書全面系統地介紹了線性表、佇列、堆疊、樹和圖,以
及貪婪演算法、分而治之演算法、分枝定界演算法等多種演算法設計方法。本書以應用為主,提供了多個應用例項與練習題。
《演算法導論》
本書以深入淺出的方法全
面地介紹了各種演算法。
涵蓋的內容有:演算法在計算中的作用,概率分析和隨機演算法的介紹。
遊戲開發中常用的資料結構
內容會持續更新,有錯誤的地方歡迎指正,謝謝 1.陣列 需處理的元素個數確定並且需使用下標時可以考慮,不過建議用泛型list 優點 陣列在記憶體中是連續儲存的,索引和修改的速度都非常快 缺點 插入和刪除很慢,長度開闢過長易造成記憶體浪費,長度開闢過短易造成記憶體越界 2.list list是泛型的,即...
C Xml中對映為類資料結構(報文)
system.runtime.serialization.datamemberattribute public information archive set system.xml.serialization.xmlattributeattribute system.runtime.serializ...
linux C 開發中重要的資料結構 結構體
在linux的驅動開發中,最常用的,也最重要的資料結構是結構體,它也最容易使人混淆。要掌握結構體,首先要弄明白運算子的優先順序 在所有運算子中,下面4個運算子的優先順序是最高的 結構體運算子 和 用與函式呼叫的 以及用於下標的 因此它們同運算元之間的結合也最緊密。例如對 struct p 表示式 p...