搜尋演算法
1.地圖尋路問題(A,A*,IDA*)
2.博弈問題(Alpha-Beta剪枝,SSS*,MemSSS*)
職能演算法
1.遺傳演算法
2.類比退火
3.禁忌搜尋
4.人工神經網路
彙編最佳化:
能用整數,則盡量不用浮點數;
迴圈展開技術(比如100次降到50次):由於現代CPU具有分支預測技術,迴圈展開增加了代碼量,更多佔用CPU內部一級代碼快取的空間,迴圈展開遠遠不如原來有效。
局部變數在堆棧中,這樣可以重複使用記憶體,當一塊記憶體被反覆讀寫,其資料就會存在CPU的內部一級緩衝中,訪問速度非常快。而零散的靜態變數則沒有這個優勢。記憶體同CPU內部緩衝的資料交換,往往成為程式的速度瓶頸。
除2的整數冪可以被最佳化成移位操作,但是我們並不主張把n/8寫成n>>3,因為現代編譯器會幫你做這件事。這裡需要注意的是:如果你知道n肯定是個正數,而n又被聲明成int時,寫成(unsigned)n/8是有利於編譯器幫你最佳化的。因為對於一個有符號的數字除以8並不完全等價於右移3位。
實際上,即使除數不是2的整數冪,編譯器的最佳化依然會消除除法,變成一次乘法加一次移位操作。讓編譯器有最佳化餘地的唯一前提就是,讓除數是一個常數,除了直接寫除數,也可以用const int來定義。
對於浮點運算,我們有更多的方法減少除法的運算次數(以下方法在特定條件下,使用一些技巧也同樣適用於整數運算):
對於整數除法,如果需要對一個數字反覆做除法,則可以先算出其倒數,然後用乘法代替。如果 是常數除法,比如a/3.14倒不必寫成a*(1.0/3/14),因為編譯器通常會幫你完成這種最佳化。
在某些情況下,可以用乘法消除掉除法運算,比如if(a>b/c)可以寫成if(a*c>b).編譯器之所以 不會幫你做這樣的最佳化,是因為兩者並非完全等價(如果c是負數,後者的要寫成<;當然這個方法 用於整數的時候,要考慮a*c有溢出的可能)
我們還可以想辦法把多個除法合并起來。對於運算a/b+c/d,(a*d+c*b)/(b*d)會更快一些,這是 因為即使是算3次乘法也快過一次除法。
避免過大的迴圈
全域變數:在C中隨處可見,而在C++中是會被盡量迴避的,C++程式員更多的會把一類全域變數寫成一個類並做成單件,先取得單件的指標,再使用單件的方法來訪問這些資料。表面上看起來C++中的方法會多一次間接性,但是現代CPU,在對待資料時,把資料集中卻有助於提高資料快取的使用效率,並且之間訪問全域變數會產生一個32位地址資料,處理速度比用一個this指標加一個短位移量要低。
消失了的宏:宏在C語言中有極其重要的地位,而在C++中儘力迴避。紅在C語言的編程中主要有四大用途:定義函數,代碼產生,內聯代碼和對編譯流程做出選擇。C++,定義常數通常用const。
其實在更多的情況下,我們選擇一個內嵌函式返回一個常數值來取代直接定義一個全域的常數,這種靈活的方案被許多經驗豐富的C++程式員採納。因為C++對inline函數最佳化得很好,最終編譯器會把它最佳化成一個常數,而沒有函數調用的消耗。
inline函數在C++裡應用非常廣泛,配合template可以完成許多以前只有宏才能完成的事情。
判斷一個C++程式是否由一個有經驗的C++程式員寫出來,最簡單的方法之一就是看看代碼中const的出現頻率。
幾乎所有的C++程式員在描述字串常量的時候都會寫const char*而不是C語言程式員喜歡的char*。
C++程式員總是把函數的參數儘可能寫成const,表示這個函數不會修改它。同樣成員變數也經常會被修飾成const,這樣就只能在構造時構建它們。另外,為成員函數增加一個const修飾表達這個函數不會修改類的成員變數也使得成員變的優雅。
(成員函數的定義最後加上const,實際上是指出隱式傳入的this指標是一個const指標。)
儘可能使用const使軟體在設計階段的思路更清晰,讓編譯器更加理解程式員的想法,以便在程式員不小心犯錯誤時及時指出。
+=比+加=更符合效能要求,因為它不需要臨時構造出一個對象
為什麼需要指令碼?
(1)靈活性,需求會隨著項目的進展時刻變化,我們必須隨時改動遊戲中的許多東西。
(2)減少和底層的耦合度
(3)增加代碼複用性,如果我們把所有遊戲邏輯有關的東西都放進了指令碼中,那麼指令碼以下的模組實際上可以被很多遊戲項目複用。
(4)降低開發門檻
(5)方便更新
(6)阻礙使用者對遊戲做逆向工程
應該用指令碼做些什嗎?
(1)如果遊戲的介面比較豐富,請一定為這個模組設定一個指令碼驅動介面
(2)網路遊戲的用戶端網路包的處理應該使用指令碼
(3)遊戲的情節和遊戲規則應該用指令碼驅動
(4)遊戲的配置應該寫在指令碼中