📄 validate.c
字号:
//-----------------------------------------------------------------
// 名称: 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 + -