象棋和五子棋AI的開發(一)
阿新 • • 發佈:2018-11-26
剛出來工作的時候,用C++做過一個五子棋的AI,那時候已基本達到了自己戰勝不了電腦的水平。當然,自己的水平相當有限,不能以此作為標準。最近心血來潮,想做一款象棋的,看了一些資料之後,發現五子棋也可以再寫一遍。於是就使用C#做了象棋和五子棋的AI,都達到了自己無法戰勝的水平。
一開始,我以為五子棋更簡單一些,畢竟象棋的走法更復雜,但做下來發現,其實五子棋是更復雜、計算量更大的一個棋類。
程式的內容很大一部分參考了《PC遊戲程式設計(人機博弈)》這本書,在閱讀本博文之前,請先了解書裡的內容。我不打算重複書裡講過的內容,只會講一些自己的特色。
一、基本資料型別的定義
程式沒有以效率至上為原則,充分地考慮了易讀性,所以程式碼看起來還是比較容易理解的。
一些基本的資料型別:
/// <summary> /// 棋子顏色 /// </summary> public enum ChessColor { 無, 黑, 紅, 白, 藍 } /// <summary> /// 棋子型別 /// </summary> public enum ChessType { 空, 卒, 象, 士, 炮, 馬, 車, 將, 有 } /// <summary> /// 棋子結構 /// </summary> public class Chess { public Chess() { color = ChessColor.無; type = ChessType.空; } public Chess(ChessColor c, ChessType t) { color = c; type = t; } public void Set(ChessColor c, ChessType t) { color = c; type = t; } public ChessColor color; public ChessType type; } /// <summary> /// 移動類棋走步結構 /// </summary> public class Step : IComparable { public Step(int fr, int fc, int tr, int tc) { FromRow = fr; FromCol = fc; ToRow = tr; ToCol = tc; } public int FromRow; public int FromCol; public int ToRow; public int ToCol; /// <summary> /// 走步價值 /// </summary> public int value; public int CompareTo(object obj) { return (obj as Step).value - value; } } /// <summary> /// 單放類棋走步結構 /// </summary> public class Put : IComparable { public Put(int tr, int tc, ChessColor c) { ToRow = tr; ToCol = tc; Color = c; } public int ToRow; public int ToCol; public ChessColor Color; /// <summary> /// 走步價值 /// </summary> public int value; public int CompareTo(object obj) { return (obj as Put).value - value; } }
整個棋盤用一個二維陣列表示,board[Row,Col],它的每一格都是一個Chess型別,而Chess包括了顏色和棋子型別兩個屬性。在象棋裡面,顏色是紅和黑,型別有將、象、馬、車等;在五子棋裡面,顏色是白和黑,型別只有空和有。
象棋和五子棋的走步結構也並不一樣,象棋是由一個位置移動到另一個位置,而五子棋是直接放棋子在某一個空位上。我們還能注意到,結構裡有一個走步價值的屬性。它是排序用的,在歷史啟發演算法裡使用。