咱們的程序須要讓電腦可以在輪到它走子的時候執行一個它認爲對它最有利的着法,那前提就是它要有諸多(也多是惟一)可供選擇的着法,提供全部可選着法的「清單」就是咱們的着法生成器所要完成的。以後用搜索函數來搜索「清單」,並用局面評估函數來逐一打分,最後就能夠選擇「最佳」着法並實施了。數組
在着法生成器中,我採用的基本思想就是遍歷整個棋盤(一個接一個地看棋盤上的每一個位置點),當發現有當前下棋方的棋子時就根據它是何種棋子而相應地找出其全部合法着法,而後存入着法隊列。安全
這裏談到的「合法着法」包括如下幾點:
一、各棋子按其行子規則行子。諸如馬跳「日」字、象走「田」字、士在九宮內斜行等等(這裏須要特別注意的是卒的行子規則隨其所在位置不一樣而會發生變化——過河後能夠左右平移)。
二、行子不能越出棋盤界限。固然全部子都不能走到棋盤的外面,同時某些特定的子還有本身的行棋界限,如將、士不能出九宮,象不能過河。
三、行子的半路上不能有子阻攔(除了炮隔子打子以外)以及行子的目的點不能有本方棋子(固然不能本身吃本身了)。
四、將帥不能碰面(本程序中只認爲將帥碰面是非法的,而其它「送死」的着法並不非法,只是產生敗局罷了)ide
產生了着法後要將其存入着法隊列以供搜索之用,因爲搜索會搜索多層(即考慮雙方你來我往好幾步,這樣纔有利於對局面進行評估而儘量避免「目光短淺」 ),因此在存着法隊列的時候還要同時存儲該着法所屬的搜索層數。所以我將着法隊列定義爲二維數組MoveList[12][80],第一個下標爲層數,第二個下標爲每一層的所有着法數。函數
關於搜索層數,考慮到當前大多數機器的配置以及層數對電腦水平的影響我給數組下標設定爲12,實際使用的是1到11(搜索層數的增長會顯著提升電腦的下棋水平。但有關實驗數據代表,當搜索層數大於八、9以後電腦下棋水平將主要依賴於局面評估部分。個人迅馳1.5,736M內存的筆記本只能搜索5層,再多將致使搜索時間達到沒法容忍的地步,而咱們指導老師的雙CPU的機器搜索到11層也很輕鬆)。post
而對每一層的着法數,也就是當前下棋方針對某一局面的全部合法着法,在象棋實戰中通常最多也就五六十種。定義第二個數組下標爲80,基本上能夠保證安全。設計
下面是CChessMove.h的代碼。其中CCHESSMOVE類型和POINT類型分別是在前面一篇CChessDef.h中定義的走法的結構體以及棋盤上的點的結構體。
在GenerateMove函數中存在着較大範圍的代碼冗餘,像隊列
//==========生成紅車的着法 case RED_J: …… break; //==========生成黑車的着法 case BLACK_J: …… break;
之類的代碼段徹底能夠併到一塊兒寫成內存
//==========生成車的着法 case RED_J: // fall through case BLACK_J: …… break;
的形式,之因此分開寫是由我最初的設計思想致使的(我本來計劃不遍歷棋盤而是遍歷全部棋子,後來發現這樣作得不償失因此又中途改爲遍歷棋盤了)。而當最初的方案被否決並修改後,我以爲既然已經分開寫了,這樣也不會影響最後程序的執行效率,結合註釋分開寫反而讀起來更加清楚,因此也就沒改。由此致使的代碼冗餘,若是哪位朋友看了以爲不爽,還望海涵 : )it
// CChessMove.h #include "CChessDef.h" /////////////////// Data Define /////////////////////////////////////////////// CCHESSMOVE MoveList[12][80] ; // 存儲產生的着法隊列 int nMoveCount ; // 存儲當前搜索深度已產生的着法數 /////////////////// Function Prototype //////////////////////////////////////// // 判斷ptPosition處是否有同一方的子,如有返回true,不然返回false inline bool HaveFriend( POINT ptPosition, int fSide ); // 判斷 x, y 處是否有同一方的子,如有返回true,不然返回false inline bool HaveFriend( BYTE x, BYTE y, int fSide ); // 判斷ptPosition處是否有子,如有返回true,不然返回false inline bool HaveMan( POINT ptPosition ); // 判斷 x, y 處是否有子,如有返回true,不然返回false inline bool HaveMan( BYTE x, BYTE y ); // 檢查將帥是否碰面,若碰面返回對方王的 y 值座標,不碰面則返回-1。 // 其中x, y分別爲當前走棋方的王所在位置座標,fSide爲當前走棋方 int IsKingFaceToFace( int x, int y, int fSide ); // 產生fSide方全部着法,返回產生的着法總數。nDepth爲當前搜索深度, //用於傳給AddMoveToQueue函數 int GenerateMove( int fSide, int nDepth ); // 將產生的着法加入着法隊列。nDepth爲當前搜索深度 inline void AddMoveToQueue( POINT ptFrom, POINT ptTo, int nDepth ); // 將產生的着法加入着法隊列。nDepth爲當前搜索深度 inline void AddMoveToQueue( POINT ptFrom, BYTE x, BYTE y, int nDepth ); ////////////////// Programmer-Defined Function //////////////////////////////// inline bool HaveFriend( POINT ptPosition, int fSide ) { if( CChessBoard[ptPosition.x][ptPosition.y] == 0 ) return false; else if( SideOfMan[ CChessBoard[ptPosition.x][ptPosition.y] ] == fSide ) return true; else return false; } inline bool HaveFriend( BYTE x, BYTE y, int fSide ) { if( CChessBoard[x][y] == 0 ) return false; else if( SideOfMan[ CChessBoard[x][y] ] == fSide ) return true; else return false; } inline bool HaveMan( POINT ptPosition ) { if( CChessBoard[ptPosition.x][ptPosition.y] == 0 ) return false; else return true; } inline bool HaveMan( BYTE x, BYTE y ) { if( CChessBoard[x][y] == 0 ) return false; else return true; } int IsKingFaceToFace( int x, int y, int fSide ) { bool bMayKingFaceToFace = false; int i, j ; if( fSide == RED ) { for( i = 9; i >= 7; i -- ) // 檢查黑將是否在同列 { if( CChessBoard[x][i] == BLACK_K ) { bMayKingFaceToFace = true; break; } } if( bMayKingFaceToFace == false ) return -1; for( j = y + 1; j <= i - 1 ; j ++ ) // 黑將在同列,檢查中間是否有隔擋 { if( CChessBoard[x][j] != 0 ) // 有其餘子 return -1; } return i; // 將帥碰面,返回黑將的 y 值座標 } else // fSide == BLACK { for( i = 0; i <= 2; i ++ ) // 檢查紅帥是否在同列 { if( CChessBoard[x][i] == RED_K ) { bMayKingFaceToFace = true; break; } } if( bMayKingFaceToFace == false ) return -1; for( j = y - 1; j >= i + 1 ; j -- ) // 紅帥在同列,檢查中間是否有隔擋 { if( CChessBoard[x][j] != 0 ) // 有其餘子 return -1; } return i; // 將帥碰面,返回紅帥的 y 值座標 } } int GenerateMove( int fSide, int nDepth ) { BYTE nCChessID ; POINT ptFrom , ptTo , ptHalf ; int i; nMoveCount = 0; int x, y; for( x = 0; x <= 8; x ++ ) for( y = 0; y <= 9; y ++ ) { if( CChessBoard[x][y] != 0 ) { nCChessID = CChessBoard[x][y]; if( SideOfMan[ nCChessID ] != fSide )//該子顏色與所要生成着法的顏色不一樣 continue; ptFrom.x = x ; ptFrom.y = y ; switch( nCChessID ) { //==========生成紅帥的着法 case RED_K: // 將帥碰面 i = IsKingFaceToFace( ptFrom.x, ptFrom.y, fSide ); if( i != -1 ) AddMoveToQueue( ptFrom, ptFrom.x, i, nDepth ); //縱向 ptTo.x = ptFrom.x ; //向前 ptTo.y = ptFrom.y + 1 ; if(( ptTo.y <= 2 ) && ( ! HaveFriend( ptTo, fSide ) )) AddMoveToQueue( ptFrom, ptTo, nDepth ); //向後 ptTo.y = ptFrom.y - 1 ; if(( ptTo.y >= 0 ) && ( ! HaveFriend( ptTo, fSide ) )) AddMoveToQueue( ptFrom, ptTo, nDepth ); //橫向 ptTo.y = ptFrom.y ; //向左 ptTo.x = ptFrom.x - 1 ; if(( ptTo.x >= 3 ) && ( ! HaveFriend( ptTo, fSide ) ) && ( IsKingFaceToFace( ptTo.x, ptTo.y, fSide ) == -1 ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //向右 ptTo.x = ptFrom.x + 1 ; if(( ptTo.x <= 5 ) && ( ! HaveFriend( ptTo, fSide ) ) && ( IsKingFaceToFace( ptTo.x, ptTo.y, fSide ) == -1 ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; //==========生成黑將的着法 case BLACK_K: // 將帥碰面 i = IsKingFaceToFace( ptFrom.x, ptFrom.y, fSide ); if( i != -1 ) AddMoveToQueue( ptFrom, ptFrom.x, i, nDepth ); //縱向 ptTo.x = ptFrom.x ; //向前 ptTo.y = ptFrom.y - 1 ; if(( ptTo.y >= 7 ) && ( ! HaveFriend( ptTo, fSide ) )) AddMoveToQueue( ptFrom, ptTo, nDepth ); //向後 ptTo.y = ptFrom.y + 1 ; if(( ptTo.y <= 9 ) && ( ! HaveFriend( ptTo, fSide ) )) AddMoveToQueue( ptFrom, ptTo, nDepth ); //橫向 ptTo.y = ptFrom.y ; //向左 ptTo.x = ptFrom.x + 1 ; if(( ptTo.x <= 5 ) && ( ! HaveFriend( ptTo, fSide ) ) && ( IsKingFaceToFace( ptTo.x, ptTo.y, fSide ) == -1 ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //向右 ptTo.x = ptFrom.x - 1 ; if(( ptTo.x >= 3 ) && ( ! HaveFriend( ptTo, fSide ) ) && ( IsKingFaceToFace( ptTo.x, ptTo.y, fSide ) == -1 ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; //==========生成紅車的着法 case RED_J: //縱向 ptTo.x = ptFrom.x ; //向前 for( ptTo.y = ptFrom.y + 1; ptTo.y <= 9; ptTo.y ++ ) { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } AddMoveToQueue( ptFrom, ptTo, nDepth ); } //向後 for( ptTo.y = ptFrom.y - 1; ptTo.y >= 0; ptTo.y -- ) { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } AddMoveToQueue( ptFrom, ptTo, nDepth ); } //橫向 ptTo.y = ptFrom.y ; //向左 for( ptTo.x = ptFrom.x - 1; ptTo.x >= 0; ptTo.x -- ) { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } AddMoveToQueue( ptFrom, ptTo, nDepth ); } //向右 for( ptTo.x = ptFrom.x + 1; ptTo.x <= 8; ptTo.x ++ ) { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } AddMoveToQueue( ptFrom, ptTo, nDepth ); } break; //==========生成黑車的着法 case BLACK_J: //縱向 ptTo.x = ptFrom.x ; //向前 for( ptTo.y = ptFrom.y - 1; ptTo.y >= 0; ptTo.y -- ) { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } AddMoveToQueue( ptFrom, ptTo, nDepth ); } //向後 for( ptTo.y = ptFrom.y + 1; ptTo.y <= 9; ptTo.y ++ ) { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } AddMoveToQueue( ptFrom, ptTo, nDepth ); } //橫向 ptTo.y = ptFrom.y ; //向左 for( ptTo.x = ptFrom.x + 1; ptTo.x <= 8; ptTo.x ++ ) { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } AddMoveToQueue( ptFrom, ptTo, nDepth ); } //向右 for( ptTo.x = ptFrom.x - 1; ptTo.x >= 0; ptTo.x -- ) { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } AddMoveToQueue( ptFrom, ptTo, nDepth ); } break; //==========生成紅馬的着法 case RED_M: //ptHalf用來存儲馬腿的位置,以判斷該位置是否有子憋馬腿 ptHalf.x = ptFrom.x ; ptHalf.y = ptFrom.y + 1 ; if( ptHalf.y <= 8 && ! HaveMan( ptHalf ) ) { //11點方向 ptTo.x = ptFrom.x - 1 ; ptTo.y = ptFrom.y + 2 ; if( ptTo.x >= 0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //1點方向 ptTo.x = ptFrom.x + 1 ; ptTo.y = ptFrom.y + 2 ; if( ptTo.x <= 8 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } ptHalf.x = ptFrom.x + 1 ; ptHalf.y = ptFrom.y ; if( ptHalf.x <= 7 && ! HaveMan( ptHalf ) ) { //2點方向 ptTo.x = ptFrom.x + 2 ; ptTo.y = ptFrom.y + 1 ; if( ptTo.y <= 9 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //4點方向 ptTo.x = ptFrom.x + 2 ; ptTo.y = ptFrom.y - 1 ; if( ptTo.y >= 0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } ptHalf.x = ptFrom.x ; ptHalf.y = ptFrom.y - 1 ; if( ptHalf.y >= 1 && ! HaveMan( ptHalf ) ) { //5點方向 ptTo.x = ptFrom.x + 1 ; ptTo.y = ptFrom.y - 2 ; if( ptTo.x <= 8 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //7點方向 ptTo.x = ptFrom.x - 1 ; ptTo.y = ptFrom.y - 2 ; if( ptTo.x >= 0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } ptHalf.x = ptFrom.x - 1 ; ptHalf.y = ptFrom.y ; if( ptHalf.x >= 1 && ! HaveMan( ptHalf ) ) { //8點方向 ptTo.x = ptFrom.x - 2 ; ptTo.y = ptFrom.y - 1 ; if( ptTo.y >= 0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //10點方向 ptTo.x = ptFrom.x - 2 ; ptTo.y = ptFrom.y + 1 ; if( ptTo.y <= 9 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } break; //==========生成黑馬的着法 case BLACK_M: //ptHalf用來存儲馬腿的位置,以判斷該位置是否有子憋馬腿 ptHalf.x = ptFrom.x ; ptHalf.y = ptFrom.y + 1 ; if( ptHalf.y <= 8 && ! HaveMan( ptHalf ) ) { //5點方向 ptTo.x = ptFrom.x - 1 ; ptTo.y = ptFrom.y + 2 ; if( ptTo.x >= 0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //7點方向 ptTo.x = ptFrom.x + 1 ; ptTo.y = ptFrom.y + 2 ; if( ptTo.x <= 8 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } ptHalf.x = ptFrom.x + 1 ; ptHalf.y = ptFrom.y ; if( ptHalf.x <= 7 && ! HaveMan( ptHalf ) ) { //8點方向 ptTo.x = ptFrom.x + 2 ; ptTo.y = ptFrom.y + 1 ; if( ptTo.y <= 9 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //10點方向 ptTo.x = ptFrom.x + 2 ; ptTo.y = ptFrom.y - 1 ; if( ptTo.y >= 0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } ptHalf.x = ptFrom.x ; ptHalf.y = ptFrom.y - 1 ; if( ptHalf.y >= 1 && ! HaveMan( ptHalf ) ) { //11點方向 ptTo.x = ptFrom.x + 1 ; ptTo.y = ptFrom.y - 2 ; if( ptTo.x <= 8 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //1點方向 ptTo.x = ptFrom.x - 1 ; ptTo.y = ptFrom.y - 2 ; if( ptTo.x >= 0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } ptHalf.x = ptFrom.x - 1 ; ptHalf.y = ptFrom.y ; if( ptHalf.x >= 1 && ! HaveMan( ptHalf ) ) { //2點方向 ptTo.x = ptFrom.x - 2 ; ptTo.y = ptFrom.y - 1 ; if( ptTo.y >= 0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //4點方向 ptTo.x = ptFrom.x - 2 ; ptTo.y = ptFrom.y + 1 ; if( ptTo.y <= 9 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } break; //==========生成紅炮的着法 case RED_P: //ptHalf用來存儲炮是否有隔子打子的中間子 //縱向 ptTo.x = ptFrom.x ; //向前 ptHalf.x = -1; //標誌還沒有發現中間子 for( ptTo.y = ptFrom.y + 1; ptTo.y <= 9; ptTo.y ++ ) { if( ptHalf.x == -1 ) // 無中間子 { if( ! HaveMan( ptTo ) ) { AddMoveToQueue( ptFrom, ptTo, nDepth ); } else // if( HaveMan( ptTo ) ) { ptHalf.x = ptTo.x ; ptHalf.y = ptTo.y ; } } else // 已有中間子 { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } } } //向後 ptHalf.x = -1; //標誌還沒有發現中間子 for( ptTo.y = ptFrom.y - 1; ptTo.y >= 0; ptTo.y -- ) { if( ptHalf.x == -1 ) // 無中間子 { if( ! HaveMan( ptTo ) ) { AddMoveToQueue( ptFrom, ptTo, nDepth ); } else // if( HaveMan( ptTo ) ) { ptHalf.x = ptTo.x ; ptHalf.y = ptTo.y ; } } else // 已有中間子 { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } } } //橫向 ptTo.y = ptFrom.y ; //向左 ptHalf.x = -1; //標誌還沒有發現中間子 for( ptTo.x = ptFrom.x - 1; ptTo.x >= 0; ptTo.x -- ) { if( ptHalf.x == -1 ) // 無中間子 { if( ! HaveMan( ptTo ) ) { AddMoveToQueue( ptFrom, ptTo, nDepth ); } else // if( HaveMan( ptTo ) ) { ptHalf.x = ptTo.x ; ptHalf.y = ptTo.y ; } } else // 已有中間子 { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } } } //向右 ptHalf.x = -1; //標誌還沒有發現中間子 for( ptTo.x = ptFrom.x + 1; ptTo.x <= 8; ptTo.x ++ ) { if( ptHalf.x == -1 ) // 無中間子 { if( ! HaveMan( ptTo ) ) { AddMoveToQueue( ptFrom, ptTo, nDepth ); } else // if( HaveMan( ptTo ) ) { ptHalf.x = ptTo.x ; ptHalf.y = ptTo.y ; } } else // 已有中間子 { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } } } break; //==========生成黑炮的着法 case BLACK_P: //ptHalf用來存儲炮是否有隔子打子的中間子 //縱向 ptTo.x = ptFrom.x ; //向後 ptHalf.x = -1; //標誌還沒有發現中間子 for( ptTo.y = ptFrom.y + 1; ptTo.y <= 9; ptTo.y ++ ) { if( ptHalf.x == -1 ) // 無中間子 { if( ! HaveMan( ptTo ) ) { AddMoveToQueue( ptFrom, ptTo, nDepth ); } else // if( HaveMan( ptTo ) ) { ptHalf.x = ptTo.x ; ptHalf.y = ptTo.y ; } } else // 已有中間子 { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } } } //向前 ptHalf.x = -1; //標誌還沒有發現中間子 for( ptTo.y = ptFrom.y - 1; ptTo.y >= 0; ptTo.y -- ) { if( ptHalf.x == -1 ) // 無中間子 { if( ! HaveMan( ptTo ) ) { AddMoveToQueue( ptFrom, ptTo, nDepth ); } else // if( HaveMan( ptTo ) ) { ptHalf.x = ptTo.x ; ptHalf.y = ptTo.y ; } } else // 已有中間子 { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } } } //橫向 ptTo.y = ptFrom.y ; //向右 ptHalf.x = -1; //標誌還沒有發現中間子 for( ptTo.x = ptFrom.x - 1; ptTo.x >= 0; ptTo.x -- ) { if( ptHalf.x == -1 ) // 無中間子 { if( ! HaveMan( ptTo ) ) { AddMoveToQueue( ptFrom, ptTo, nDepth ); } else // if( HaveMan( ptTo ) ) { ptHalf.x = ptTo.x ; ptHalf.y = ptTo.y ; } } else // 已有中間子 { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } } } //向左 ptHalf.x = -1; //標誌還沒有發現中間子 for( ptTo.x = ptFrom.x + 1; ptTo.x <= 8; ptTo.x ++ ) { if( ptHalf.x == -1 ) // 無中間子 { if( ! HaveMan( ptTo ) ) { AddMoveToQueue( ptFrom, ptTo, nDepth ); } else // if( HaveMan( ptTo ) ) { ptHalf.x = ptTo.x ; ptHalf.y = ptTo.y ; } } else // 已有中間子 { if( HaveMan( ptTo ) ) { if( ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); break; } } } break; //==========生成紅相的着法 case RED_X: if( ptFrom.x == 0 ) { if( ! HaveFriend(2, 4, fSide) && ! HaveMan(1, 3) ) AddMoveToQueue( ptFrom, 2, 4, nDepth ); if( ! HaveFriend(2, 0, fSide) && ! HaveMan(1, 1) ) AddMoveToQueue( ptFrom, 2, 0, nDepth ); } else if( ptFrom.x == 2 ) { if( ptFrom.y == 4 ) { if( ! HaveFriend(0, 2, fSide) && ! HaveMan(1, 3) ) AddMoveToQueue( ptFrom, 0, 2, nDepth ); if( ! HaveFriend(4, 2, fSide) && ! HaveMan(3, 3) ) AddMoveToQueue( ptFrom, 4, 2, nDepth ); } else // ptFrom.y == 0 { if( ! HaveFriend(0, 2, fSide) && ! HaveMan(1, 1) ) AddMoveToQueue( ptFrom, 0, 2, nDepth ); if( ! HaveFriend(4, 2, fSide) && ! HaveMan(3, 1) ) AddMoveToQueue( ptFrom, 4, 2, nDepth ); } } else if( ptFrom.x == 4 ) { if( ! HaveFriend(2, 4, fSide) && ! HaveMan(3, 3) ) AddMoveToQueue( ptFrom, 2, 4, nDepth ); if( ! HaveFriend(2, 0, fSide) && ! HaveMan(3, 1) ) AddMoveToQueue( ptFrom, 2, 0, nDepth ); if( ! HaveFriend(6, 4, fSide) && ! HaveMan(5, 3) ) AddMoveToQueue( ptFrom, 6, 4, nDepth ); if( ! HaveFriend(6, 0, fSide) && ! HaveMan(5, 1) ) AddMoveToQueue( ptFrom, 6, 0, nDepth ); } else if( ptFrom.x == 6 ) { if( ptFrom.y == 4 ) { if( ! HaveFriend(4, 2, fSide) && ! HaveMan(5, 3) ) AddMoveToQueue( ptFrom, 4, 2, nDepth ); if( ! HaveFriend(8, 2, fSide) && ! HaveMan(7, 3) ) AddMoveToQueue( ptFrom, 8, 2, nDepth ); } else // ptFrom.y == 0 { if( ! HaveFriend(4, 2, fSide) && ! HaveMan(5, 1) ) AddMoveToQueue( ptFrom, 4, 2, nDepth ); if( ! HaveFriend(8, 2, fSide) && ! HaveMan(7, 1) ) AddMoveToQueue( ptFrom, 8, 2, nDepth ); } } else // x == 8 { if( ! HaveFriend(6, 4, fSide) && ! HaveMan(7, 3) ) AddMoveToQueue( ptFrom, 6, 4, nDepth ); if( ! HaveFriend(6, 0, fSide) && ! HaveMan(7, 1) ) AddMoveToQueue( ptFrom, 6, 0, nDepth ); } break; //==========生成黑象的着法 case BLACK_X: if( ptFrom.x == 0 ) { if( ! HaveFriend(2, 5, fSide) && ! HaveMan(1, 6 ) ) AddMoveToQueue( ptFrom, 2, 5, nDepth ); if( ! HaveFriend(2, 9, fSide) && ! HaveMan(1, 8 ) ) AddMoveToQueue( ptFrom, 2, 9, nDepth ); } else if( ptFrom.x == 2 ) { if( ptFrom.y == 5 ) { if( ! HaveFriend(0, 7, fSide) && ! HaveMan(1, 6 ) ) AddMoveToQueue( ptFrom, 0, 7, nDepth ); if( ! HaveFriend(4, 7, fSide) && ! HaveMan(3, 6 ) ) AddMoveToQueue( ptFrom, 4, 7, nDepth ); } else // ptFrom.y == 9 { if( ! HaveFriend(0, 7, fSide) && ! HaveMan(1, 8 ) ) AddMoveToQueue( ptFrom, 0, 7, nDepth ); if( ! HaveFriend(4, 7, fSide) && ! HaveMan(3, 8 ) ) AddMoveToQueue( ptFrom, 4, 7, nDepth ); } } else if( ptFrom.x == 4 ) { if( ! HaveFriend(2, 5, fSide) && ! HaveMan(3, 6 ) ) AddMoveToQueue( ptFrom, 2, 5, nDepth ); if( ! HaveFriend(2, 9, fSide) && ! HaveMan(3, 8 ) ) AddMoveToQueue( ptFrom, 2, 9, nDepth ); if( ! HaveFriend(6, 5, fSide) && ! HaveMan(5, 6 ) ) AddMoveToQueue( ptFrom, 6, 5, nDepth ); if( ! HaveFriend(6, 9, fSide) && ! HaveMan(5, 8 ) ) AddMoveToQueue( ptFrom, 6, 9, nDepth ); } else if( ptFrom.x == 6 ) { if( ptFrom.y == 5 ) { if( ! HaveFriend(4, 7, fSide) && ! HaveMan(5, 6 ) ) AddMoveToQueue( ptFrom, 4, 7, nDepth ); if( ! HaveFriend(8, 7, fSide) && ! HaveMan(7, 6 ) ) AddMoveToQueue( ptFrom, 8, 7, nDepth ); } else // ptFrom.y == 9 { if( ! HaveFriend(4, 7, fSide) && ! HaveMan(5, 8 ) ) AddMoveToQueue( ptFrom, 4, 7, nDepth ); if( ! HaveFriend(8, 7, fSide) && ! HaveMan(7, 8 ) ) AddMoveToQueue( ptFrom, 8, 7, nDepth ); } } else // x == 8 { if( ! HaveFriend(6, 5, fSide) && ! HaveMan(7, 6 ) ) AddMoveToQueue( ptFrom, 6, 5, nDepth ); if( ! HaveFriend(6, 9, fSide) && ! HaveMan(7, 8 ) ) AddMoveToQueue( ptFrom, 6, 9, nDepth ); } break; //==========生成紅仕的着法 case RED_S: if( ptFrom.x == 3 ) { if( ! HaveFriend( 4, 1, fSide ) ) AddMoveToQueue( ptFrom, 4, 1, nDepth ); } else if( ptFrom.x == 4 ) { if( ! HaveFriend( 3, 2, fSide ) ) AddMoveToQueue( ptFrom, 3, 2, nDepth ); if( ! HaveFriend( 3, 0, fSide ) ) AddMoveToQueue( ptFrom, 3, 0, nDepth ); if( ! HaveFriend( 5, 2, fSide ) ) AddMoveToQueue( ptFrom, 5, 2, nDepth ); if( ! HaveFriend( 5, 0, fSide ) ) AddMoveToQueue( ptFrom, 5, 0, nDepth ); } else // ptFrom.x == 5 { if( ! HaveFriend( 4, 1, fSide ) ) AddMoveToQueue( ptFrom, 4, 1, nDepth ); } break; //==========生成黑士的着法 case BLACK_S: if( ptFrom.x == 3 ) { if( ! HaveFriend( 4, 8, fSide ) ) AddMoveToQueue( ptFrom, 4, 8, nDepth ); } else if( ptFrom.x == 4 ) { if( ! HaveFriend( 3, 7, fSide ) ) AddMoveToQueue( ptFrom, 3, 7, nDepth ); if( ! HaveFriend( 3, 9, fSide ) ) AddMoveToQueue( ptFrom, 3, 9, nDepth ); if( ! HaveFriend( 5, 7, fSide ) ) AddMoveToQueue( ptFrom, 5, 7, nDepth ); if( ! HaveFriend( 5, 9, fSide ) ) AddMoveToQueue( ptFrom, 5, 9, nDepth ); } else // ptFrom.x == 5 { if( ! HaveFriend( 4, 8, fSide ) ) AddMoveToQueue( ptFrom, 4, 8, nDepth ); } break; //==========生成紅兵的着法 case RED_B: //向前 ptTo.x = ptFrom.x ; ptTo.y = ptFrom.y + 1 ; if( ptTo.y <=9 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); if( ptFrom.y >= 5 ) //兵已過河 { ptTo.y = ptFrom.y ; //向左 ptTo.x = ptFrom.x - 1 ; if( ptTo.x >=0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //向右 ptTo.x = ptFrom.x + 1 ; if( ptTo.x <=8 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } break; //==========生成黑卒的着法 case BLACK_B: //向前 ptTo.x = ptFrom.x ; ptTo.y = ptFrom.y - 1 ; if( ptTo.y >=0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); if( ptFrom.y <= 4 ) //兵已過河 { ptTo.y = ptFrom.y ; //向右 ptTo.x = ptFrom.x - 1 ; if( ptTo.x >=0 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); //向左 ptTo.x = ptFrom.x + 1 ; if( ptTo.x <=8 && ! HaveFriend( ptTo, fSide ) ) AddMoveToQueue( ptFrom, ptTo, nDepth ); } break; } // end switch } // end if( CChessBoard[x][y] != 0 ) } // end for x 0 to 8, y 0 to 9 return nMoveCount; // 返回當前深度的走法總數 } inline void AddMoveToQueue( POINT ptFrom, POINT ptTo, int nDepth ) { MoveList[nDepth][nMoveCount].ptFrom.x = ptFrom.x ; MoveList[nDepth][nMoveCount].ptFrom.y = ptFrom.y ; MoveList[nDepth][nMoveCount].ptTo.x = ptTo.x ; MoveList[nDepth][nMoveCount].ptTo.y = ptTo.y ; nMoveCount ++; } inline void AddMoveToQueue( POINT ptFrom, BYTE x, BYTE y, int nDepth ) { MoveList[nDepth][nMoveCount].ptFrom.x = ptFrom.x ; MoveList[nDepth][nMoveCount].ptFrom.y = ptFrom.y ; MoveList[nDepth][nMoveCount].ptTo.x = x ; MoveList[nDepth][nMoveCount].ptTo.y = y ; nMoveCount ++; } // end of CChessMove.h