📄 xqwl03.cpp
字号:
// 判断棋子是否在九宫中
inline BOOL IN_FORT(int sq) {
return ccInFort[sq] != 0;
}
// 获得格子的横坐标
inline int RANK_Y(int sq) {
return sq >> 4;
}
// 获得格子的纵坐标
inline int FILE_X(int sq) {
return sq & 15;
}
// 根据纵坐标和横坐标获得格子
inline int COORD_XY(int x, int y) {
return x + (y << 4);
}
// 翻转格子
inline int SQUARE_FLIP(int sq) {
return 254 - sq;
}
// 纵坐标水平镜像
inline int FILE_FLIP(int x) {
return 14 - x;
}
// 横坐标垂直镜像
inline int RANK_FLIP(int y) {
return 15 - y;
}
// 格子水平镜像
inline int MIRROR_SQUARE(int sq) {
return COORD_XY(FILE_FLIP(FILE_X(sq)), RANK_Y(sq));
}
// 格子水平镜像
inline int SQUARE_FORWARD(int sq, int sd) {
return sq - 16 + (sd << 5);
}
// 走法是否符合帅(将)的步长
inline BOOL KING_SPAN(int sqSrc, int sqDst) {
return ccLegalSpan[sqDst - sqSrc + 256] == 1;
}
// 走法是否符合仕(士)的步长
inline BOOL ADVISOR_SPAN(int sqSrc, int sqDst) {
return ccLegalSpan[sqDst - sqSrc + 256] == 2;
}
// 走法是否符合相(象)的步长
inline BOOL BISHOP_SPAN(int sqSrc, int sqDst) {
return ccLegalSpan[sqDst - sqSrc + 256] == 3;
}
// 相(象)眼的位置
inline int BISHOP_PIN(int sqSrc, int sqDst) {
return (sqSrc + sqDst) >> 1;
}
// 马腿的位置
inline int KNIGHT_PIN(int sqSrc, int sqDst) {
return sqSrc + ccKnightPin[sqDst - sqSrc + 256];
}
// 是否未过河
inline BOOL HOME_HALF(int sq, int sd) {
return (sq & 0x80) != (sd << 7);
}
// 是否已过河
inline BOOL AWAY_HALF(int sq, int sd) {
return (sq & 0x80) == (sd << 7);
}
// 是否在河的同一边
inline BOOL SAME_HALF(int sqSrc, int sqDst) {
return ((sqSrc ^ sqDst) & 0x80) == 0;
}
// 是否在同一行
inline BOOL SAME_RANK(int sqSrc, int sqDst) {
return ((sqSrc ^ sqDst) & 0xf0) == 0;
}
// 是否在同一列
inline BOOL SAME_FILE(int sqSrc, int sqDst) {
return ((sqSrc ^ sqDst) & 0x0f) == 0;
}
// 获得红黑标记(红子是8,黑子是16)
inline int SIDE_TAG(int sd) {
return 8 + (sd << 3);
}
// 获得对方红黑标记
inline int OPP_SIDE_TAG(int sd) {
return 16 - (sd << 3);
}
// 获得走法的起点
inline int SRC(int mv) {
return mv & 255;
}
// 获得走法的终点
inline int DST(int mv) {
return mv >> 8;
}
// 根据起点和终点获得走法
inline int MOVE(int sqSrc, int sqDst) {
return sqSrc + sqDst * 256;
}
// 走法水平镜像
inline int MIRROR_MOVE(int mv) {
return MOVE(MIRROR_SQUARE(SRC(mv)), MIRROR_SQUARE(DST(mv)));
}
// 局面结构
struct PositionStruct {
int sdPlayer; // 轮到谁走,0=红方,1=黑方
BYTE ucpcSquares[256]; // 棋盘上的棋子
int vlWhite, vlBlack; // 红、黑双方的子力价值
int nDistance; // 距离根节点的步数
void Startup(void); // 初始化棋盘
void ChangeSide(void) { // 交换走子方
sdPlayer = 1 - sdPlayer;
}
void AddPiece(int sq, int pc) { // 在棋盘上放一枚棋子
ucpcSquares[sq] = pc;
// 红方加分,黑方(注意"cucvlPiecePos"取值要颠倒)减分
if (pc < 16) {
vlWhite += cucvlPiecePos[pc - 8][sq];
} else {
vlBlack += cucvlPiecePos[pc - 16][SQUARE_FLIP(sq)];
}
}
void DelPiece(int sq, int pc) { // 从棋盘上拿走一枚棋子
ucpcSquares[sq] = 0;
// 红方减分,黑方(注意"cucvlPiecePos"取值要颠倒)加分
if (pc < 16) {
vlWhite -= cucvlPiecePos[pc - 8][sq];
} else {
vlBlack -= cucvlPiecePos[pc - 16][SQUARE_FLIP(sq)];
}
}
int Evaluate(void) const { // 局面评价函数
return (sdPlayer == 0 ? vlWhite - vlBlack : vlBlack - vlWhite) + ADVANCED_VALUE;
}
int MovePiece(int mv); // 搬一步棋的棋子
void UndoMovePiece(int mv, int pcCaptured); // 撤消搬一步棋的棋子
BOOL MakeMove(int mv, int &pcCaptured); // 走一步棋
void UndoMakeMove(int mv, int pcCaptured) { // 撤消走一步棋
nDistance --;
ChangeSide();
UndoMovePiece(mv, pcCaptured);
}
int GenerateMoves(int *mvs) const; // 生成所有走法
BOOL LegalMove(int mv) const; // 判断走法是否合理
BOOL Checked(void) const; // 判断是否被将军
BOOL IsMate(void); // 判断是否被杀
};
// 初始化棋盘
void PositionStruct::Startup(void) {
int sq, pc;
sdPlayer = vlWhite = vlBlack = nDistance = 0;
memset(ucpcSquares, 0, 256);
for (sq = 0; sq < 256; sq ++) {
pc = cucpcStartup[sq];
if (pc != 0) {
AddPiece(sq, pc);
}
}
}
// 搬一步棋的棋子
int PositionStruct::MovePiece(int mv) {
int sqSrc, sqDst, pc, pcCaptured;
sqSrc = SRC(mv);
sqDst = DST(mv);
pcCaptured = ucpcSquares[sqDst];
if (pcCaptured != 0) {
DelPiece(sqDst, pcCaptured);
}
pc = ucpcSquares[sqSrc];
DelPiece(sqSrc, pc);
AddPiece(sqDst, pc);
return pcCaptured;
}
// 撤消搬一步棋的棋子
void PositionStruct::UndoMovePiece(int mv, int pcCaptured) {
int sqSrc, sqDst, pc;
sqSrc = SRC(mv);
sqDst = DST(mv);
pc = ucpcSquares[sqDst];
DelPiece(sqDst, pc);
AddPiece(sqSrc, pc);
if (pcCaptured != 0) {
AddPiece(sqDst, pcCaptured);
}
}
// 走一步棋
BOOL PositionStruct::MakeMove(int mv, int &pcCaptured) {
pcCaptured = MovePiece(mv);
if (Checked()) {
UndoMovePiece(mv, pcCaptured);
return FALSE;
}
ChangeSide();
nDistance ++;
return TRUE;
}
// 生成所有走法
int PositionStruct::GenerateMoves(int *mvs) const {
int i, j, nGenMoves, nDelta, sqSrc, sqDst;
int pcSelfSide, pcOppSide, pcSrc, pcDst;
// 生成所有走法,需要经过以下几个步骤:
nGenMoves = 0;
pcSelfSide = SIDE_TAG(sdPlayer);
pcOppSide = OPP_SIDE_TAG(sdPlayer);
for (sqSrc = 0; sqSrc < 256; sqSrc ++) {
// 1. 找到一个本方棋子,再做以下判断:
pcSrc = ucpcSquares[sqSrc];
if ((pcSrc & pcSelfSide) == 0) {
continue;
}
// 2. 根据棋子确定走法
switch (pcSrc - pcSelfSide) {
case PIECE_KING:
for (i = 0; i < 4; i ++) {
sqDst = sqSrc + ccKingDelta[i];
if (!IN_FORT(sqDst)) {
continue;
}
pcDst = ucpcSquares[sqDst];
if ((pcDst & pcSelfSide) == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
}
break;
case PIECE_ADVISOR:
for (i = 0; i < 4; i ++) {
sqDst = sqSrc + ccAdvisorDelta[i];
if (!IN_FORT(sqDst)) {
continue;
}
pcDst = ucpcSquares[sqDst];
if ((pcDst & pcSelfSide) == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
}
break;
case PIECE_BISHOP:
for (i = 0; i < 4; i ++) {
sqDst = sqSrc + ccAdvisorDelta[i];
if (!(IN_BOARD(sqDst) && HOME_HALF(sqDst, sdPlayer) && ucpcSquares[sqDst] == 0)) {
continue;
}
sqDst += ccAdvisorDelta[i];
pcDst = ucpcSquares[sqDst];
if ((pcDst & pcSelfSide) == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
}
break;
case PIECE_KNIGHT:
for (i = 0; i < 4; i ++) {
sqDst = sqSrc + ccKingDelta[i];
if (ucpcSquares[sqDst] != 0) {
continue;
}
for (j = 0; j < 2; j ++) {
sqDst = sqSrc + ccKnightDelta[i][j];
if (!IN_BOARD(sqDst)) {
continue;
}
pcDst = ucpcSquares[sqDst];
if ((pcDst & pcSelfSide) == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
}
}
break;
case PIECE_ROOK:
for (i = 0; i < 4; i ++) {
nDelta = ccKingDelta[i];
sqDst = sqSrc + nDelta;
while (IN_BOARD(sqDst)) {
pcDst = ucpcSquares[sqDst];
if (pcDst == 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
} else {
if ((pcDst & pcOppSide) != 0) {
mvs[nGenMoves] = MOVE(sqSrc, sqDst);
nGenMoves ++;
}
break;
}
sqDst += nDelta;
}
}
break;
case PIECE_CANNON:
for (i = 0; i < 4; i ++) {
nDelta = ccKingDelta[i];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -