⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 validate.c

📁 单片机c语言程序设计100例--基于PIC+PROTEUS
💻 C
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------
//  名称: from位置上piececlour颜色的棋子当前所有可能的合法移动搜索程序
//-----------------------------------------------------------------
//  说明: 搜索结果将保存于有效移动掩码数组及捕获掩码数组
//
//-----------------------------------------------------------------
#include "chess.h"
//-----------------------------------------------------------------
// 搜索from位置上piececlour颜色的“兵”当前所有可能的合法移动
//-----------------------------------------------------------------
void val_pawn(BYTE from[],BOOL piececolour)
{
   COORD r = from[0],c = from[1];  BOOL piecefound = FALSE;
   //得到对手中王的位置,当前是执白子的,则找黑子“王”,否则找白子“王”
   if (piececolour == WHITE)
   { opp_king_pos[0] = bl_king_pos[0]; opp_king_pos[1] = bl_king_pos[1];
   }
   else
   { opp_king_pos[0] = wh_king_pos[0]; opp_king_pos[1] = wh_king_pos[1];
   }  
   //“兵”向对方直进一格(白子行递增,黑子行递减)[棋盘行号由下至上编号为0 ~ 7]
   if (piececolour == WHITE) r++; else r--;
   //前方格子为空格则置位该行掩码中的第c位为1,否则设piecefound为真
   if (board[r][c] == EMPTY) validmovemask[r] |= (1<<c); else piecefound = TRUE;
   //判断是否可沿斜线吃左前方的对方棋子(兵:直进斜吃)
   if ((is_opp_piece(r,c-1,piececolour)) && (c > MIN_COL))
   { 
      validmovemask[r] |= (1<<(c - 1));
      capturemask[r]   |= (1<<(c - 1));
      //如果欲捕获位置上是对方的“王”时设kingcapture为真
      if (capturemask[opp_king_pos[0]] & (1 << opp_king_pos[1])) kingcapture = TRUE;
   }
   //判断是否可沿斜线吃右前方的对方棋子(兵:直进斜吃)
   if ((is_opp_piece(r,c+1,piececolour)) && (c < MAX_COL))
   {
      validmovemask[r] |= (1<<(c + 1));
      capturemask[r]   |= (1<<(c + 1));
      //如果欲捕获位置上是对方的“王”时设kingcapture为真
      if (capturemask[opp_king_pos[0]] & (1 << opp_king_pos[1])) kingcapture = TRUE;
   }
   //如果“兵”在属于自己的底行时可直进两格(2行)[白兵底行为1,黑兵底行为6]
   //(代码第19行已直进1行,故这里只需要尝试再直进1行,共直进2行)
   if ((piececolour == BLACK && from[0] == BL_PAWN_BASEROW) || 
       (piececolour == WHITE && from[0] == WH_PAWN_BASEROW))
   {  
      if (piececolour == WHITE) r++; else r--; //白兵再直进时r++,黑兵再直进时r--
      //如果本次直进一格所到的位置为空,且此前代码尝试的直进1格也不曾遇到棋子时
      //(piecefound为假),即直进两格无障碍时,将合法移动掩码中r行第c位置1
      if ((board[r][c] == EMPTY) && (piecefound == FALSE)) validmovemask[r] |= (1<<c);
   }
}

//-----------------------------------------------------------------
// 搜索from位置上piececlour颜色的“象”当前所有可能的合法移动
//-----------------------------------------------------------------
void val_bishop(BYTE from[],BOOL piececolour)
{ 
   //先得到对方"王"的位置
   if (piececolour == WHITE)
   {  opp_king_pos[0] = bl_king_pos[0];
      opp_king_pos[1] = bl_king_pos[1];
   }
   else
   {  opp_king_pos[0] = wh_king_pos[0];
      opp_king_pos[1] = wh_king_pos[1];
   }
   //“象”向四个方向移动,直到遇到边线或遇到棋子
   //最大搜索深度全部设为-1,即255(最大值),实际搜索不会到达该值就会返回.
   val_northeast(from,piececolour,-1); //东北
   val_northwest(from,piececolour,-1); //西北
   val_southeast(from,piececolour,-1); //东南
   val_southwest(from,piececolour,-1); //西南
 }

//-----------------------------------------------------------------
// 搜索from位置上piececlour颜色的“马”当前所有可能的合法移动
//-----------------------------------------------------------------
void val_knight(BYTE from[],BOOL piececolour)
{  
   BYTE mask = 0, i = 0;
   BYTE r = 0,c = 0;
   //马的各种走法如下,数组中第0,3,6,9,12,15,18,21号元素分别标识
   //出这8种走法是否可行,初始时默认为全部不可行(全设为0)
   INT move[] =   
   {
       0,  2,  1, //+2行,+1列 
       0,  2, -1, //+2行,-1列
       0,  1,  2, //+1行,+2列
       0,  1, -2, //+1行,-2列
       0, -1,  2, //-1行,+2列
       0, -1, -2, //-1行,-2列
       0, -2, -1, //-2行,-1列
       0, -2,  1  //-2行,+1列
   };
   //获取对方王的位置
   if (piececolour == WHITE)
   {  opp_king_pos[0] = bl_king_pos[0];
      opp_king_pos[1] = bl_king_pos[1];
   }
   else
   {  opp_king_pos[0] = wh_king_pos[0];
      opp_king_pos[1] = wh_king_pos[1];
   }
   //--------------------------------------------------------------  
   // 为便于判断,可将以下8种直行移动分别用掩码变量mask中的8位来对应表示
   // 0: 上1行(0x01), 1:上2行(0x02), 2:下1行(0x04), 3:下2行(0x08)
   // 4: 左1列(0x10), 5:左2列(0x20), 6:右1列(0x40), 7:右2列(0x80)
   // 例如,当可上走1行或下走1,2行,有:
   // mask = 0x01 | 0x04 | 0x08 = 0x0D = 0B00001101
   //--------------------------------------------------------------
   //下面根据起始行号,设置掩码标识出可向上走或向下走的行数
   switch (from[0])
   {  case 0 : mask |=  0x03;   break; //可上1,2行       (00000011)
      case 1 : mask |=  0x07;   break; //可上1,2行或下1行(00000111)
      case 6 : mask |=  0x0D;   break; //可上1行或下1,2行(00001101)
      case 7 : mask |=  0x0C;   break; //可下1,2行       (00001100)
      case 2 :
      case 3 :
      case 4 :
      case 5 : mask |=  0x0F;   break; //处于2,3,4,5时可上或下1,2行(00001111)
   }
   //根据起始列号,设置掩码标识出可左走或右走的列数
   switch (from[1])
   {  
      case 0 : mask |=  0xC0;   break; //可右走1,2列
      case 1 : mask |=  0xD0;   break; //可左走1列或右走1,2列
      case 6 : mask |=  0x70;   break; //可左走1,2列或右走1列
      case 7 : mask |=  0x30;   break; //可左走1,2列
      case 2 :
      case 3 :
      case 4 :
      case 5 : mask |=  0xF0;   break; //可左走1,2列或右走1,2列
   }
   //马的8种可能的移动判断的宏定义
   #define up2_rgt1   ((mask & 0x40) && (mask & 0x02))  //+2行,+1列
   #define up2_lft1   ((mask & 0x10) && (mask & 0x02))  //+2行,-1列
   #define up1_rgt2   ((mask & 0x80) && (mask & 0x01))  //+1行,+2列
   #define up1_lft2   ((mask & 0x20) && (mask & 0x01))  //+1行,-2列
   #define dwn1_rgt2  ((mask & 0x80) && (mask & 0x04))  //-1行,+2列
   #define dwn1_lft2  ((mask & 0x20) && (mask & 0x04))  //-1行,-2列
   #define dwn2_lft1  ((mask & 0x10) && (mask & 0x08))  //-2行,-1列
   #define dwn2_rgt1  ((mask & 0x40) && (mask & 0x08))  //-2行,+1列     
   //move[0,3,6,9,12,15,18,12]分别标识出对应的8种走法是否可行
   //宏的计算结果为1时表示可行,否则为0,表示不可行.
   move[0]  = up2_rgt1;
   move[3]  = up2_lft1;
   move[6]  = up1_rgt2;
   move[9]  = up1_lft2;
   move[12] = dwn1_rgt2;
   move[15] = dwn1_lft2;
   move[18] = dwn2_lft1;
   move[21] = dwn2_rgt1;
   //对所有的可能性进行处理
   for (i = 0; i <= 21; i += 3)
   {  
       if (move[i]) //如果[0,3,6,9,12,15,18,21]值为真(1)则可行,继续进行处理
       {
         //如果move[i]标识为可行,则从该三元组move[i],move[i+1],move[i+2]的后两个
         //元素中取得行,列的偏移值,加上起始行列号(from[0],from[1]),
         //得到目标位置的行/列号[r,c]
         r = (from[0] + move[i+1]); c = (from[1] + move[i+2]);
         //若[r,c]为空格,则将r行的移动掩码validmovemask[r]中的第c位设为1
         if (board[r][c] == EMPTY)  validmovemask[r] |= (1<<c);
         //否则如果[r,c]中是对方棋子则同时设置移动掩码与捕获掩码
         else if (is_opp_piece(r,c,piececolour))
         {
            validmovemask[r] |= (1<<c);
            capturemask[r]   |= (1<<c);
            //如果从更新后的捕获掩码中发现对方王被捕获,则设置kingcapture = TRUE
            if (capturemask[opp_king_pos[0]] & (1 << opp_king_pos[1])) 
              kingcapture = TRUE;
         }
       }
    }
}

//-----------------------------------------------------------------
// 搜索from位置上piececlour颜色的“车”当前所有可能的合法移动
//-----------------------------------------------------------------
void val_rook(BYTE from[],BOOL piececolour)
{  //取得对方“王”的位置
   if (piececolour == WHITE)
   {  opp_king_pos[0] = bl_king_pos[0];
      opp_king_pos[1] = bl_king_pos[1];
   }
   else
   {  opp_king_pos[0] = wh_king_pos[0];
      opp_king_pos[1] = wh_king_pos[1];
   }
   //向上下左右四个方向搜索得到所有有效移动的掩码与捕获掩码
   val_north(from,piececolour,-1);
   val_south(from,piececolour,-1);
   val_east (from,piececolour,-1);
   val_west (from,piececolour,-1);
 }

//-----------------------------------------------------------------
// 搜索from位置上piececlour颜色的“后”当前所有可能的合法移动
//-----------------------------------------------------------------
void val_queen(BYTE from[],BOOL piececolour)
{
   //取得对方“王”的位置
   if (piececolour == WHITE)
   { 
     opp_king_pos[0] = bl_king_pos[0];
     opp_king_pos[1] = bl_king_pos[1];
   }
   else
   { 
      opp_king_pos[0] = wh_king_pos[0];
      opp_king_pos[1] = wh_king_pos[1];
   }
   //向八个方向(米字形)搜索所有有效移动
   val_north    (from,piececolour,-1);
   val_south    (from,piececolour,-1);
   val_east     (from,piececolour,-1);
   val_west     (from,piececolour,-1);
   val_northeast(from,piececolour,-1);
   val_northwest(from,piececolour,-1);
   val_southeast(from,piececolour,-1);
   val_southwest(from,piececolour,-1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -