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编辑过]