C语言从零起步分析《象眼》象棋引擎的源码(16)
我们来看看走法合理性判断函数:
程序代码:
// 判断走法是否合理
BOOL PositionStruct::LegalMove(int mv) const {
int sqSrc, sqDst, sqPin;
int pcSelfSide, pcSrc, pcDst, nDelta;
// 判断走法是否合法,需要经过以下的判断过程:
// 1. 判断起始格是否有自己的棋子
sqSrc = SRC(mv);
pcSrc = ucpcSquares[sqSrc];
pcSelfSide = SIDE_TAG(sdPlayer);
if ((pcSrc & pcSelfSide) == 0) {
return FALSE;
}
// 2. 判断目标格是否有自己的棋子
sqDst = DST(mv);
pcDst = ucpcSquares[sqDst];
if ((pcDst & pcSelfSide) != 0) {
return FALSE;
}
// 3. 根据棋子的类型检查走法是否合理
switch (pcSrc - pcSelfSide) {
case PIECE_KING:
return IN_FORT(sqDst) && KING_SPAN(sqSrc, sqDst);
case PIECE_ADVISOR:
return IN_FORT(sqDst) && ADVISOR_SPAN(sqSrc, sqDst);
case PIECE_BISHOP:
return SAME_HALF(sqSrc, sqDst) && BISHOP_SPAN(sqSrc, sqDst) &&
ucpcSquares[BISHOP_PIN(sqSrc, sqDst)] == 0;
case PIECE_KNIGHT:
sqPin = KNIGHT_PIN(sqSrc, sqDst);
return sqPin != sqSrc && ucpcSquares[sqPin] == 0;
case PIECE_ROOK:
case PIECE_CANNON:
if (SAME_RANK(sqSrc, sqDst)) {
nDelta = (sqDst < sqSrc ? -1 : 1);
} else if (SAME_FILE(sqSrc, sqDst)) {
nDelta = (sqDst < sqSrc ? -16 : 16);
} else {
return FALSE;
}
sqPin = sqSrc + nDelta;
while (sqPin != sqDst && ucpcSquares[sqPin] == 0) {
sqPin += nDelta;
}
if (sqPin == sqDst) {
return pcDst == 0 || pcSrc - pcSelfSide == PIECE_ROOK;
} else if (pcDst != 0 && pcSrc - pcSelfSide == PIECE_CANNON) {
sqPin += nDelta;
while (sqPin != sqDst && ucpcSquares[sqPin] == 0) {
sqPin += nDelta;
}
return sqPin == sqDst;
} else {
return FALSE;
}
case PIECE_PAWN:
if (AWAY_HALF(sqDst, sdPlayer) && (sqDst == sqSrc - 1 || sqDst == sqSrc + 1)) {
return TRUE;
}
return sqDst == SQUARE_FORWARD(sqSrc, sdPlayer);
default:
return FALSE;
}
}
在格子事件处理中有这样两行代码,来使用走法合理性判断函数:
mv = MOVE(Xqwl.sqSelected, sq);
if (pos.LegalMove(mv)) {//<---------- 判断走法是否合理
根据起点和终点获得走法inline int MOVE(int sqSrc, int sqDst) { return sqSrc + sqDst * 256;}
从这里可以看出:mv的低位存放这源点(即一步棋的起点),而高位存放目标点(即一步棋的终点);
第一小段代码分析:
程序代码:
BOOL PositionStruct::LegalMove(int mv) const {
int sqSrc, sqDst, sqPin;
int pcSelfSide, pcSrc, pcDst, nDelta;
// 判断走法是否合法,需要经过以下的判断过程:
// 1. 判断起始格是否有自己的棋子
sqSrc = SRC(mv);// 获得走法的起点
pcSrc = ucpcSquares[sqSrc];
//获取盘面中某格子的棋子的编号;这个格子就是下法起点格子;
pcSelfSide = SIDE_TAG(sdPlayer);
//SIDE_TAG 获得红黑标记(红子是8,黑子是16)
//int sdPlayer; // 轮到谁走,0=红方,1=黑方
//即:目前是轮到红方走,返回8,轮到黑方走,返回16;
if ((pcSrc & pcSelfSide) == 0) {
//如果目前是轮到红方走,起点格子中是黑棋,则==0;
//如果目前是轮到黑方走,起点格子中是红棋,则==0;
return FALSE;//判断为,下棋不合理,因为起点处,不是自己的子;
}
第二小段分析:
程序代码:
// 2. 判断目标格是否有自己的棋子
sqDst = DST(mv);// 获得走法的终点;
pcDst = ucpcSquares[sqDst]; //获取盘终点棋子编号;
if ((pcDst & pcSelfSide) != 0) {
//目前是轮到红方走,pcSelfSide =8,轮到黑方走,pcSelfSide =16;
//如果目前是轮到红方走8,终点格子中是红棋,则==8;
//如果目前是轮到黑方走16,终点格子中是黑棋,则==16;
return FALSE;//判断为,下棋不合理,因为终点处,有自己的子;
}
第3小段,内容蛮多,暂告一段落。

[此贴子已经被作者于2016-3-27 16:33编辑过]












.
),