人工智慧是乙個非常具有潛力的分支,顧名思義,它可以通過計算機指令模擬人的行為,在遊戲中的人工智慧就非常地多樣了。對於fps、tab、rpg、stg、adv等遊戲,有著不同的人工智慧,但都基於幾種理論:有限狀態機、遺傳演算法、神經網路等。下面我就採用遊戲中最基礎也是最常用的人工智慧演算法來進行演示。
我的開發環境是:
windows: windowsxp(sp3) + mingw4.4/mingw4.7 + qt4.8.3/qt5.0.1 + qtcreator2.6/qtcreator2.7
linux: ubuntu12.10 + gcc4.7 + qt4.8.1/qt4.8.4/qt5.0.1 + qtcreator2.6/qtcreator2.7
這裡這裡
注意:由於qt5.0.1中乙個未知的bug,編譯執行後角色無法移動,所以請使用qt4.6+來進行編譯。
程式截圖如下所示:
通過子視窗的控制選項,我們可以設定我們的初音ミク、鏡音リン和鏡音レン的控制方法,可以選擇人工控制也可以選擇ai控制。如果選擇人工控制,那麼可以通過按下「上下左右」鍵控制角色的移動,如果選擇ai控制,那麼角色會沿著場景作順時針移動。
整個專案的**量較多,我將選擇有關人工智慧的內容進行講解,也希望大家沿著我的思路思考下去。
首先如何讓角色沿著視窗作順時針旋轉?乙個簡單的想法就是:當角色將要達到視窗頂端那麼角色將往右移動;角色將要到達視窗右端那麼角色將往下移動,以此類推。按照這樣的思路,我寫了這樣的ai**:
這也是我ai的第乙個版本,但是正如qtmikusnake7_ver_1應用程式截圖中所示,它並不能達到應有的效果,角色一直在右上角打轉。看來第乙個版本有問題。問題在哪兒呢?這是由於我們將向上的判定優先於向下的判定,導致了角色在右上角處轉至下後又轉回了右上角。了解了這個問題之後第乙個想法就是為向上判定新增約束條件,使其能夠在右上角處正確地轉至向下判定而不會折返。下面是ai的第二個版本:
if ( m_pcharacter->pos( ).y( ) > 20.0 &&
m_pcharacter->m_direction != character::_down_ )
else if ( m_pcharacter->pos( ).x( ) < 608.0 &&
m_pcharacter->m_direction != character::_left_ )
else if ( m_pcharacter->pos( ).y( ) < 340.0 &&
m_pcharacter->m_direction != character::_up_ )
else if ( m_pcharacter->pos( ).x( ) > 0.0 &&
m_pcharacter->m_direction != character::_right_ )
為了保險,按照這種思路,將每乙個方向判定都新增了約束條件,即判定當前的方向是何方向。按理說角色要往上走,那麼當前的方向就肯定不是往下走,角色要往左走,當前的方向就肯定不是往右走。好了,執行一下,結果發現如qtmikusnake7_ver_2所示的效果一樣,角色在右下角處至左移了一格就往上走了。看來又是一次失誤。
分析原因,發現向上判定的約束雖然解決了當前方向向下時仍進行向上判定的問題,可是未解決當前方向向左時仍然出現向上判定優先於向左判定的情況。看來還是需要再對向上判定進行進一步約束,按照「上右下左」的移動順序,我們了解向上判定需要兩個約束,向右判定需要乙個約束,而向下判定不需要額外的約束,向左判定就更不需要了。下面ai的第三個版本:
if ( m_pcharacter->pos( ).y( ) > 20.0 &&
m_pcharacter->m_direction != character::_down_ &&
m_pcharacter->m_direction != character::_left_ )
else if ( m_pcharacter->pos( ).x( ) < 608.0 &&
m_pcharacter->m_direction != character::_left_ )
else if ( m_pcharacter->pos( ).y( ) < 340.0 )
else if ( m_pcharacter->pos( ).x( ) > 0.0 )
else if ( m_pcharacter->pos( ).x( ) == 0.0 )// 為防止角色在左下角卡死設立的判斷
注意到最下面乙個判斷,因為角色走在左下角的時候會因為都滿足不了這些判定條件而陷入「卡死」狀態,所以我們要進行「解鎖」操作——將當前的方向設為向上,這樣又可以滿足向上的判定了。下面是程式qtmikusnake7_ver_3的截圖。
似乎這個問題圓滿地解決了。但是我覺得這個**還是寫得太被動了,因為這些**都是出了問題而乙個乙個地打補丁打上去的,非常被動。我們得換乙個角度考慮。試想,如果一條語句能夠「排隊」,當讓它執行的時候它排在最前面,執行完畢後它輪到最末尾,給下一條語句機會,要是這樣的話,我們可以讓上、右、下、左四條語句依次排隊,一條語句一條語句地輪著執行。
這完全有可能實現!回想起來了嗎?這不就是資料結構中經典的佇列結構!可是,怎樣才能讓語句智慧型地移動到後面執行呢?這裡需要使用乙個類對這條語句進行封裝。因為語句的格式相當有條理:if 判定條件 then 執行語句。我是這樣封裝的:
class clause: public qobject
virtual bool judgesentence( void ) = 0;
virtual void statement( void ) = 0;
protected:
character* m_pcharacter;
};
隨後我設定乙個佇列,在qt中有個現成的qqueue。
qqueuem_clauses;
接著進行語句類的定義,讓其繼承clause類:
class dirupclause: public clause
bool judgesentence( void )
void statement( void )
};class dirdownclause: public clause
bool judgesentence( void )
void statement( void )
};class dirleftclause: public clause
bool judgesentence( void )
void statement( void )
};class dirrightclause: public clause
bool judgesentence( void )
void statement( void )
};
最後我們在更新物件狀態**中進行乙個簡單地呼叫就可以了。
foreach ( clause* pclause, m_clauses )
else
}
上面的**中,當條件滿足的時候進行語句的執行,當條件不滿足的時候將該語句從佇列的頭部移至佇列的尾部。這樣寫雖然**會比較多,但是思路清晰,對更複雜的狀態維護起著重要的作用。執行起來效率也比較高,因為少了一些不必要的判定。下面是程式qtmikusnake7_ver_4的截圖。
上面的演算法僅僅是乙個很簡單的演示,對於角色的運動還有諸如追擊、自主規避、尋路等ai演算法,對於複雜的遊戲,狀態的維護非常複雜且容易出錯,而這個錯誤又不像程式宕機那樣容易覺察,這時需要乙個特定的職位——指令碼設計師來解決此類問題。指令碼設計師面對著各類的資料,通過自身熟練的指令碼語言來對程式的各類引數進行微調,一款成功的遊戲總有指令碼設計師付出的辛勤汗水。所以說指令碼設計師都是藝術家。
後記:程式qtmikusnake7對
上乙個版本的幀框大小進行了修正,重新整理不會出現殘影的現象,有關ai測試**也將在下乙個版本中被去除。
人工智慧演算法在遊戲中演示
注意 由於qt5.0.1中乙個未知的bug,編譯執行後角色無法移動,所以請使用qt4.6 來進行編譯。程式截圖如下所示 通過子視窗的控制選項,我們可以設定我們的初音 鏡音 和鏡音 的控制方法,可以選擇人工控制也可以選擇ai控制。如果選擇人工控制,那麼可以通過按下 上下左右 鍵控制角色的移動,如果選擇...
人工智慧演算法分類
人工智慧演算法大體上來說可以分類兩類 基於統計的機器學習演算法 machine learning 和深度學習演算法 deep learning 總的來說,在sklearn中機器學習演算法大概的分類如下 1 回歸演算法 2 分類演算法 3 聚類演算法 4 降維演算法 5 概率圖模型演算法 6 文字挖掘...
矩陣戰爭遊戲人工智慧演算法分析
矩陣戰爭中的人工智慧演算法詳細解析 矩陣戰爭是邵帝大佬開發的又一款燒腦策略遊戲。其中的人工智慧演算法之強超出大部分人的能力範圍。想知道你為什麼一直ai打敗嗎?請看這篇文章。主要演算法 隨機森林,svm 對戰演算法 樸素貝葉斯 聊天區外交演算法 邵帝的這款遊戲中人工智慧會首先分析棋盤狀態,隨機選取五個...