1. 程式人生 > >2D遊戲之五子棋(3)人工智慧AI,自動落棋

2D遊戲之五子棋(3)人工智慧AI,自動落棋

class AI { // 15*15共有572種五子連珠的可能性 const int MaxFiveChainCount = 572; //玩家的可能性 bool[,,] _ptable = new bool[Board.CrossCount, Board.CrossCount, MaxFiveChainCount]; //電腦的可能性 bool[, ,] _ctable = new bool[Board.CrossCount, Board.CrossCount, MaxFiveChainCount]; //記錄2位玩家所有可能的連珠數,-1則為永遠無法5連珠
int[,] _win = new int[2, MaxFiveChainCount]; //記錄每格的分值 int[,] _cgrades = new int[Board.CrossCount, Board.CrossCount]; int[,] _pgrades = new int[Board.CrossCount, Board.CrossCount]; //記錄棋盤 int[,] _board = new int[Board.CrossCount, Board.CrossCount]; int _cgrade, _pgrade; int
_icount, _m, _n; int _mat, _nat, _mde, _nde; public AI( ) { for ( int i = 0;i<Board.CrossCount;i++) { for ( int j = 0;j<Board.CrossCount;j++) { _pgrades[i, j] = 0; _cgrades[i, j] = 0; _board[i, j] = 0
; } } //遍歷所有的五連子可能情況的權值 //橫 for ( int i = 0;i<Board.CrossCount;i++) { for ( int j = 0;j<Board.CrossCount - 4 ;j++) { for( int k = 0;k < BoardModel.WinChessCount;k++) { _ptable[j + k, i, _icount] = true; _ctable[j + k, i, _icount] = true; } _icount++; } } //橫 for (int i = 0; i < Board.CrossCount; i++) { for (int j = 0; j < Board.CrossCount - 4; j++) { for (int k = 0; k < BoardModel.WinChessCount; k++) { _ptable[i, j + k, _icount] = true; _ctable[i, j + k, _icount] = true; } _icount++; } } // 右斜 for (int i = 0; i < Board.CrossCount - 4; i++) { for (int j = 0; j < Board.CrossCount - 4; j++) { for (int k = 0; k < BoardModel.WinChessCount; k++) { _ptable[j+k, i + k, _icount] = true; _ctable[j + k, i + k, _icount] = true; } _icount++; } } // 左斜 for (int i = 0; i < Board.CrossCount - 4; i++) { for (int j = Board.CrossCount - 1; j >= 4; j--) { for (int k = 0; k < BoardModel.WinChessCount; k++) { _ptable[j - k, i + k, _icount] = true; _ctable[j - k, i + k, _icount] = true; } _icount++; } } for (int i = 0; i < 2; i++) { for (int j = 0; j < MaxFiveChainCount; j++) { _win[i, j] = 0; } } _icount = 0; } void CalcScore( ) { _cgrade = 0; _pgrade = 0; _board[_m, _n] = 1;//電腦下子位置 for (int i = 0; i < MaxFiveChainCount; i++) { if (_ctable[_m, _n, i] && _win[0, i] != -1) { _win[0, i]++;//給白子的所有五連子可能的載入當前連子數 } if (_ptable[_m, _n, i]) { _ptable[_m, _n, i] = false; _win[1, i] = -1; } } } void CalcCore( ) { //遍歷棋盤上的所有座標 for (int i = 0; i < Board.CrossCount; i++) { for (int j = 0; j < Board.CrossCount; j++) { //該座標的黑子獎勵積分清零 _pgrades[i, j] = 0; //在還沒下棋子的地方遍歷 if (_board[i, j] == 0) { //遍歷該棋盤可落子點上的黑子所有權值的連子情況,並給該落子點加上相應獎勵分 for (int k = 0; k < MaxFiveChainCount; k++) { if (_ptable[i, j, k]) { switch (_win[1, k]) { case 1://一連子 _pgrades[i, j] += 5; break; case 2://兩連子 _pgrades[i, j] += 50; break; case 3://三連子 _pgrades[i, j] += 180; break; case 4://四連子 _pgrades[i, j] += 400; break; } } } _cgrades[i, j] = 0;//該座標的白子的獎勵積分清零 if (_board[i, j] == 0)//在還沒下棋子的地方遍歷 { //遍歷該棋盤可落子點上的白子所有權值的連子情況,並給該落子點加上相應獎勵分 for (int k = 0; k < MaxFiveChainCount; k++) { if (_ctable[i, j, k]) { switch (_win[0, k]) { case 1://一連子 _cgrades[i, j] += 5; break; case 2: //兩連子 _cgrades[i, j] += 52; break; case 3://三連子 _cgrades[i, j] += 130; break; case 4: //四連子 _cgrades[i, j] += 10000; break; } } } } } } } } // AI計算輸出, 需要玩家走過的點 public void ComputerDo(int playerX, int playerY, out int finalX, out int finalY ) { setPlayerPiece(playerX, playerY); CalcCore(); for (int i = 0; i < Board.CrossCount; i++) { for (int j = 0; j < Board.CrossCount; j++) { //找出棋盤上可落子點的黑子白子的各自最大權值,找出各自的最佳落子點 if (_board[i, j] == 0) { if (_cgrades[i, j] >= _cgrade) { _cgrade = _cgrades[i, j]; _mat = i; _nat = j; } if (_pgrades[i, j] >= _pgrade) { _pgrade = _pgrades[i, j]; _mde = i; _nde = j; } } } } //如果白子的最佳落子點的權值比黑子的最佳落子點權值大,則電腦的最佳落子點為白子的最佳落子點,否則相反 if (_cgrade >= _pgrade) { _m = _mat; _n = _nat; } else { _m = _mde; _n = _nde; } CalcScore(); finalX = _m; finalY = _n; } void setPlayerPiece( int playerX, int playerY ) { int m = playerX; int n = playerY; if ( _board[m, n ] == 0 ) { _board[m, n] = 2; for( int i = 0;i<MaxFiveChainCount;i++) { if ( _ptable[m, n, i ] && _win[1, i] != -1 ) { _win[1, i]++; } if (_ctable[m,n,i]) { _ctable[m, n, i] = false; _win[0, i] = -1; } } } } }