在棋類遊戲中最難的便是人機對戰電腦的AI演算法了,演算法設計的好壞將嚴重的影響遊戲的趣味程度,關於五子棋的相關演算法,討論的人也比較多。在我們此次的電腦的AI演算法中採用的方式即是,當電腦開始下棋的時候,它會計算對手下在各個位置獲勝的可能性,然後通過可能性的大小來對比自己應該把棋子下在哪個位置。可能性的大小我們用權值來表示,那麼如何計算權值呢?權值的計算方法比較容易,即從上、下、左斜向、右斜向四個方向尋找連子,如果連子有1個,即可賦值權值100,依次增高,如果連子有4個,那麼就應該有最高的權值,即10000。值得注意的是,權值不僅僅包括一個方向,例如“雙三”(兩個三個的,玩過五子棋的都懂的)或“沖四”(即立即可以贏的),在一個棋子的不同方向都有多個子的時候,應該加上所有方向的權值。
由於近來比較的忙,沒有時間認認真真的研究演算法,等有時間了再好好研究,下面參考了網上的一個有關五子棋的AI演算法,大家可以看看,等過段時間會好好的研究一下並重新整理一下:
public class SuanFa {//定義一個數組來賦值當前的棋局private int[][] curChess = new int[12][12];//複製當前的棋局private void copyChessboard(int[][] chess){for(int i=0;i<12;i++){for(int j =0;j<12;j++){curChess[i][j] = chess[i][j];}}}//記錄當前的落子的位置private int ci,cj;private void copyChessLocation(int i,int j){ci=i;cj=j;}//記錄下棋方的IDprivate int nameID;public void loadInfo(int[][] chess,int i,int j){copyChessboard(chess);copyChessLocation(i,j);nameID = 2;}//定義權值常量//黑白白空private final int Q2O = 50;//空白白空private final int Q2 = 100;//黑白白白空private final int Q3O = 500;//空白白白空private final int Q3 = 1000;//黑白白白白空private final int Q4O = 5000;//空白白白白空private final int Q4 = 10000;//白白白白白private final int Q5 = 100000;//權值定義好之後,就可以用來計算棋盤上各個點的權值了,經分析,棋盤上某個點的權值有四部分構成,//分別是此點在水平方向的權值、此點在垂直方向上的權值、此點在45度方向上的權值、此點在135度方向上的權值,//所以必須先求出這四個方向上的權值,然後再將他們進行相加便得到這個點的權值了private int getQuan(int i,int j)//i,j記錄當前假定的落子點{//求當前位置的權值int q = 0;q += getQuan0(i,j);//q += getQuan90(i,j);//q += getQuan45(i,j);//q += getQuan135(i,j);return q;}private int getQuan0(int i,int j){//水平權值int samechessNumS = 0;//相同棋子的個數int samechessNumF = 0;//用來堵棋的,反方的相同棋子的個數int blankNumS = 0;int blankNumF = 0;int q = 0,qS = 0,qF = 0;int[][] ij0 = new int[2][2];//計算權值用的ij0[0][0] = ij0[0][1] = i;ij0[1][0] = ij0[1][1] = j;samechessNumS = getsamechessNum0(ij0,1);//得到白子數目if(ij0[1][0]>=0)if(curChess[ij0[0][1]][ij0[1][0]] == 0)blankNumS++;if(ij0[1][1]<12)//12為線條數if(curChess[ij0[0][1]][ij0[1][1]] == 0)blankNumS++;qS = getQuanpart(samechessNumS,blankNumS);//得到速勝權值ij0[0][0] = ij0[0][1] = i;ij0[1][0] = ij0[1][1] = j;samechessNumF = getsamechessNum0(ij0,2);//得到黑子數目if(ij0[1][0] >= 0)if(curChess[ij0[0][0]][ij0[1][0]] == 0)blankNumF++;if(ij0[1][1] >= 0)if(curChess[ij0[0][1]][ij0[1][1]] == 0)blankNumF++;qF = getQuanpart(samechessNumF,blankNumF);//得到堵敵權值q = qS + qF;return q;}private int getsamechessNum0(int[][] qij,int chessID){//得到水平方向的同子數目int num = 1;//儲存相同棋子數目,當前點滿足條件qij[1][0]--;while(qij[1][0]>=0 && num < 5){//向左探索我們只探索臨近的4個點,注意不要出邊界哦if(curChess[qij[0][0]][qij[1][0]] != chessID)break;num++;qij[1][0]--;}qij[1][1]++;while(qij[1][1]<12 && num<5){//向右探測if(curChess[qij[0][1]][qij[1][1]] != chessID)break;num++;qij[1][1]++;}return num;}private int getQuanpart(int sameChessNum,int blankNum){//求取某一方向上的一般權值if(sameChessNum == 2 && blankNum == 1)return Q2O;if(sameChessNum == 2 && blankNum == 2)return Q2;else if(sameChessNum == 3 && blankNum == 1)return Q3O;else if(sameChessNum == 3 && blankNum == 2)return Q3;else if(sameChessNum == 4 && blankNum == 1)return Q4O;else if(sameChessNum == 4 && blankNum == 2)return Q4;else if(sameChessNum == 5)return Q5;else return 0;}}