当前位置: 首页 > news >正文

[EGE-2]双人中国象棋(含代码)

国际象棋整出来了,那当然少不了中国象棋啦~

修复了以下BUG:

1.不可以送将(之前可以送将)

2.只有选中的棋子才能高亮显示(之前点过就是高亮)

3.将帅不见面

BUG:楚河汉界位置错位

1. 前面

和国际象棋差不多,不再赘述

2.特殊的走法

相较于国际象棋,中国象棋的难点在于:

1.马儿撇腿

2.将帅不见面

3.士不可出九宫,象不可以过河

4.兵过河可以横走

5.炮需要炮架

马撇腿

马走日的本质是向前走一个,在斜走一个,所以判断前方有没有棋子就可以

// 检查马腿是否被堵if (dx == 1) { // 竖着走int blockY = fromY + (toY > fromY ? 1 : -1);if (board[blockY][fromX].color != EMPTY) {return false;}} else { // 横着走int blockX = fromX + (toX > fromX ? 1 : -1);if (board[fromY][blockX].color != EMPTY) {return false;}}

将帅不见面

找到两个的位置,检查是否有其他的棋子存在于之间

bool areKingsFacing(const vector<vector<Piece>>& board) {int redKingX = -1, redKingY = -1;int blackKingX = -1, blackKingY = -1;// 找到红将和黑帅的位置for (int y = 0; y < BOARD_HEIGHT; y++) {for (int x = 0; x < BOARD_WIDTH; x++) {if (board[y][x].type == JIANG) {if (board[y][x].color == RED_PLAYER) {redKingX = x;redKingY = y;} else {blackKingX = x;blackKingY = y;}}}}// 如果有一个将/帅不存在,返回falseif (redKingX == -1 || blackKingX == -1) return false;// 检查是否在同一列if (redKingX != blackKingX) return false;// 检查中间是否有棋子int startY = min(redKingY, blackKingY) + 1;int endY = max(redKingY, blackKingY);for (int y = startY; y < endY; y++) {if (board[y][redKingX].color != EMPTY) {return false; // 中间有棋子,不构成面对面}}return true; // 将帅面对面
}

士象不过河

把九宫看做是一个结构体,或者说找到坐标,判断即可。

象眼和马腿一样的。

// 士移动规则if (fromPiece.type == SHI) {// 只能在九宫格内移动if (fromPiece.color == RED_PLAYER) {if (toX < 3 || toX > 5 || toY < 7) return false;} else {if (toX < 3 || toX > 5 || toY > 2) return false;}// 只能斜着移动一步if (abs(toX - fromX) != 1 || abs(toY - fromY) != 1) {return false;}return true;}// 相移动规则if (fromPiece.type == XIANG) {// 不能过河if (fromPiece.color == RED_PLAYER && toY < 5) return false;if (fromPiece.color == BLACK_PLAYER && toY > 4) return false;// 移动距离if (abs(toX - fromX) != 2 || abs(toY - fromY) != 2) {return false;}// 检查象眼是否被堵int eyeX = (fromX + toX) / 2;int eyeY = (fromY + toY) / 2;if (board[eyeY][eyeX].color != EMPTY) {return false;}return true;}

炮架

记录路径上面的棋子数,如果为1,则可以吃子,否则只能移动

// 炮移动规则if (fromPiece.type == PAO) {// 必须直线移动if (fromX != toX && fromY != toY) {return false;}int count = 0; // 路径上的棋子数if (fromX == toX) { // 垂直移动int startY = min(fromY, toY) + 1;int endY = max(fromY, toY);for (int y = startY; y < endY; y++) {if (board[y][fromX].color != EMPTY) {count++;}}} else { // 水平移动int startX = min(fromX, toX) + 1;int endX = max(fromX, toX);for (int x = startX; x < endX; x++) {if (board[fromY][x].color != EMPTY) {count++;}}}// 炮移动需要0个或1个炮架if (toPiece.color == EMPTY) { // 移动到空位if (count != 0) {return false;}} else { // 吃子if (count != 1) {return false;}}return true;}

兵横着走(确实是横行霸道qwq)

注意红方和黑方的坐标不一样,因为红方是向上,黑方是向下,判断坐标即可。

// 兵移动规则if (fromPiece.type == BING) {// 红方if (fromPiece.color == RED_PLAYER) {// 过河前只能向上if (fromY > 4 && toY != fromY - 1) {return false;}// 过河后可以左右移动if (fromY <= 4) {if (!((toX == fromX && toY == fromY - 1) || (toY == fromY && abs(toX - fromX) == 1))) {return false;}}} // 黑方else {// 过河前只能向下if (fromY < 5 && toY != fromY + 1) {return false;}// 过河后可以左右移动if (fromY >= 5) {if (!((toX == fromX && toY == fromY + 1) || (toY == fromY && abs(toX - fromX) == 1))) {return false;}}}return true;}

部分国际象棋里面没有的走法

首先是绘制游戏状态,将军则需要更加详细,写清楚是红方或者黑方。

// 绘制游戏状态
void drawGameState(GameState state) {setfont(30, 0, "楷体");setcolor(EGE_WHITE);setbkmode(TRANSPARENT);const char* stateText = "";switch (state) {case RED_TURN: stateText = "红方回合"; break;case BLACK_TURN: stateText = "黑方回合"; break;case RED_WIN: stateText = "红方胜利!"; break;case BLACK_WIN: stateText = "黑方胜利!"; break;case RED_CHECK: stateText = "红方被将军!"; break;case BLACK_CHECK: stateText = "黑方被将军!"; break;}xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y, stateText);// 绘制操作提示setfont(20, 0, "宋体");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 40, "操作说明:");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 70, "鼠标点击选择棋子");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 100, "点击目标位置移动");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 130, "按R键重新开始");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 160, "按ESC键退出");// 在将军时显示"将军!"提示if (state == RED_CHECK || state == BLACK_CHECK) {setfont(40, 0, "楷体");setcolor(EGE_ORANGE);setbkmode(TRANSPARENT);outtextxy(BOARD_X + BOARD_WIDTH * CELL_SIZE / 2 - 50, BOARD_Y + BOARD_HEIGHT * CELL_SIZE + 20, "将军!");}
}

取消选取的状态,这个是刚刚修复的BUG,因为我们在棋子结构体里面是重复使用的光标,所以需要特地的消除函数。

// 取消所有棋子的选中状态
void clearAllSelections(vector<vector<Piece>>& board) {for (int i = 0; i < BOARD_HEIGHT; i++) {for (int j = 0; j < BOARD_WIDTH; j++) {board[i][j].selected = false;}}
}

剩余的撤销模拟移动,模拟移动,检查困毙,棋子的结构体和绘制,不可送将等全部和国际象棋差不多,自己去改造吧。

好吧,由于部分代码没有给出,所以这一期上完整代码(738行)。

源代码制作不易,请体谅哦~

完整代码

#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;// 解决颜色常量冲突
#define EGE_RED 0xAA0028
#define EGE_BLACK 0x000000
#define EGE_YELLOW 0xFFFF00
#define EGE_WHITE 0xFFFFFF
#define EGE_DARKGRAY 0x555555
#define EGE_ORANGE 0xFFA500// 游戏常量
const int BOARD_X = 50;        // 棋盘左上角X坐标
const int BOARD_Y = 50;        // 棋盘左上角Y坐标
const int CELL_SIZE = 60;      // 格子大小
const int PIECE_RADIUS = 25;   // 棋子半径
const int BOARD_WIDTH = 9;     // 棋盘宽度(格子数)
const int BOARD_HEIGHT = 10;   // 棋盘高度(格子数)// 棋子类型枚举
enum PieceType {JIANG, SHI, XIANG, MA, JU, PAO, BING, NONE
};// 棋子颜色枚举
enum PieceColor {RED_PLAYER, BLACK_PLAYER, EMPTY
};// 棋子结构体
struct Piece {PieceType type;PieceColor color;int x, y;bool selected;
};// 游戏状态
enum GameState {RED_TURN, BLACK_TURN, RED_WIN, BLACK_WIN, RED_CHECK, BLACK_CHECK
};// 初始化棋盘
void initBoard(vector<vector<Piece>>& board) {board.resize(BOARD_HEIGHT, vector<Piece>(BOARD_WIDTH));// 初始化棋盘(红方在下,黑方在上)for (int i = 0; i < BOARD_HEIGHT; i++) {for (int j = 0; j < BOARD_WIDTH; j++) {board[i][j] = {NONE, EMPTY, j, i, false};}}// 布置红方棋子board[9][0] = {JU, RED_PLAYER, 0, 9, false};board[9][1] = {MA, RED_PLAYER, 1, 9, false};board[9][2] = {XIANG, RED_PLAYER, 2, 9, false};board[9][3] = {SHI, RED_PLAYER, 3, 9, false};board[9][4] = {JIANG, RED_PLAYER, 4, 9, false};board[9][5] = {SHI, RED_PLAYER, 5, 9, false};board[9][6] = {XIANG, RED_PLAYER, 6, 9, false};board[9][7] = {MA, RED_PLAYER, 7, 9, false};board[9][8] = {JU, RED_PLAYER, 8, 9, false};board[7][1] = {PAO, RED_PLAYER, 1, 7, false};board[7][7] = {PAO, RED_PLAYER, 7, 7, false};board[6][0] = {BING, RED_PLAYER, 0, 6, false};board[6][2] = {BING, RED_PLAYER, 2, 6, false};board[6][4] = {BING, RED_PLAYER, 4, 6, false};board[6][6] = {BING, RED_PLAYER, 6, 6, false};board[6][8] = {BING, RED_PLAYER, 8, 6, false};// 布置黑方棋子board[0][0] = {JU, BLACK_PLAYER, 0, 0, false};board[0][1] = {MA, BLACK_PLAYER, 1, 0, false};board[0][2] = {XIANG, BLACK_PLAYER, 2, 0, false};board[0][3] = {SHI, BLACK_PLAYER, 3, 0, false};board[0][4] = {JIANG, BLACK_PLAYER, 4, 0, false};board[0][5] = {SHI, BLACK_PLAYER, 5, 0, false};board[0][6] = {XIANG, BLACK_PLAYER, 6, 0, false};board[0][7] = {MA, BLACK_PLAYER, 7, 0, false};board[0][8] = {JU, BLACK_PLAYER, 8, 0, false};board[2][1] = {PAO, BLACK_PLAYER, 1, 2, false};board[2][7] = {PAO, BLACK_PLAYER, 7, 2, false};board[3][0] = {BING, BLACK_PLAYER, 0, 3, false};board[3][2] = {BING, BLACK_PLAYER, 2, 3, false};board[3][4] = {BING, BLACK_PLAYER, 4, 3, false};board[3][6] = {BING, BLACK_PLAYER, 6, 3, false};board[3][8] = {BING, BLACK_PLAYER, 8, 3, false};
}// 绘制棋盘
void drawBoard() {// 绘制背景setbkcolor(EGERGB(0xCC, 0x99, 0x33));cleardevice();// 绘制棋盘边框setfillcolor(EGERGB(0x99, 0x66, 0x33));bar(BOARD_X - 10, BOARD_Y - 10, BOARD_X + BOARD_WIDTH * CELL_SIZE + 10, BOARD_Y + BOARD_HEIGHT * CELL_SIZE + 10);// 绘制棋盘格子(修复:纵向线条多一列问题,i < BOARD_WIDTH)setcolor(EGE_BLACK);// 横向线条(分隔行,10行需11条线,i <= BOARD_HEIGHT)for (int i = 0; i <= BOARD_HEIGHT; i++) {line(BOARD_X, BOARD_Y + i * CELL_SIZE, BOARD_X + BOARD_WIDTH * CELL_SIZE, BOARD_Y + i * CELL_SIZE);}// 纵向线条(分隔列,9列需9条线,i < BOARD_WIDTH)for (int i = 0; i < BOARD_WIDTH; i++) {line(BOARD_X + i * CELL_SIZE, BOARD_Y, BOARD_X + i * CELL_SIZE, BOARD_Y + BOARD_HEIGHT * CELL_SIZE);}// 绘制楚河汉界(修复:位置错位,调整x和y坐标)setfont(40, 0, "楷体");setcolor(EGE_BLACK);// 楚河:x右移2格,y居中(4行+格子一半-文字一半)xyprintf(BOARD_X + 2 * CELL_SIZE, BOARD_Y + 4 * CELL_SIZE + CELL_SIZE/2 - 20, "楚 河");// 汉界:x右移2格,y居中(5行+格子一半-文字一半)xyprintf(BOARD_X + 2 * CELL_SIZE, BOARD_Y + 5 * CELL_SIZE + CELL_SIZE/2 - 20, "汉 界");// 绘制九宫格(未修改)line(BOARD_X + 3 * CELL_SIZE, BOARD_Y, BOARD_X + 5 * CELL_SIZE, BOARD_Y + 2 * CELL_SIZE);line(BOARD_X + 5 * CELL_SIZE, BOARD_Y, BOARD_X + 3 * CELL_SIZE, BOARD_Y + 2 * CELL_SIZE);line(BOARD_X + 3 * CELL_SIZE, BOARD_Y + 7 * CELL_SIZE, BOARD_X + 5 * CELL_SIZE, BOARD_Y + 9 * CELL_SIZE);line(BOARD_X + 5 * CELL_SIZE, BOARD_Y + 7 * CELL_SIZE, BOARD_X + 3 * CELL_SIZE, BOARD_Y + 9 * CELL_SIZE);
}// 获取棋子名称
const char* getPieceName(PieceType type) {switch (type) {case JIANG: return "将";case SHI: return "士";case XIANG: return "相";case MA: return "马";case JU: return "车";case PAO: return "炮";case BING: return "兵";default: return "";}
}// 绘制棋子
void drawPiece(const Piece& piece) {if (piece.color == EMPTY) return;int x = BOARD_X + piece.x * CELL_SIZE;int y = BOARD_Y + piece.y * CELL_SIZE;// 绘制棋子圆形setfillcolor(piece.color == RED_PLAYER ? EGE_WHITE : EGE_DARKGRAY);setcolor(piece.selected ? EGE_YELLOW : EGE_BLACK);setlinewidth(2);fillellipse(x, y, PIECE_RADIUS, PIECE_RADIUS);// 绘制棋子文字setfont(30, 0, "楷体");setcolor(piece.color == RED_PLAYER ? EGE_RED : EGE_WHITE);setbkmode(TRANSPARENT);const char* name = getPieceName(piece.type);int textWidth = textwidth(name);int textHeight = textheight(name);outtextxy(x - textWidth/2, y - textHeight/2, name);
}// 绘制所有棋子
void drawPieces(const vector<vector<Piece>>& board) {// 先循环列(x轴,j),再循环行(y轴,i),确保覆盖所有格子for (int i = 0; i < BOARD_HEIGHT; i++) {for (int j = 0; j < BOARD_WIDTH; j++) {if (board[i][j].color != EMPTY) {drawPiece(board[i][j]);}}}
}// 绘制游戏状态
void drawGameState(GameState state) {setfont(30, 0, "楷体");setcolor(EGE_WHITE);setbkmode(TRANSPARENT);const char* stateText = "";switch (state) {case RED_TURN: stateText = "红方回合"; break;case BLACK_TURN: stateText = "黑方回合"; break;case RED_WIN: stateText = "红方胜利!"; break;case BLACK_WIN: stateText = "黑方胜利!"; break;case RED_CHECK: stateText = "红方被将军!"; break;case BLACK_CHECK: stateText = "黑方被将军!"; break;}xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y, stateText);// 绘制操作提示setfont(20, 0, "宋体");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 40, "操作说明:");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 70, "鼠标点击选择棋子");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 100, "点击目标位置移动");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 130, "按R键重新开始");xyprintf(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 160, "按ESC键退出");// 在将军时显示"将军!"提示if (state == RED_CHECK || state == BLACK_CHECK) {setfont(40, 0, "楷体");setcolor(EGE_ORANGE);setbkmode(TRANSPARENT);outtextxy(BOARD_X + BOARD_WIDTH * CELL_SIZE / 2 - 50, BOARD_Y + BOARD_HEIGHT * CELL_SIZE + 20, "将军!");}
}// 取消所有棋子的选中状态
void clearAllSelections(vector<vector<Piece>>& board) {for (int i = 0; i < BOARD_HEIGHT; i++) {for (int j = 0; j < BOARD_WIDTH; j++) {board[i][j].selected = false;}}
}// 检查移动是否合法
bool isValidMove(const vector<vector<Piece>>& board, int fromX, int fromY, int toX, int toY) {const Piece& fromPiece = board[fromY][fromX];const Piece& toPiece = board[toY][toX];// 不能移动到自己的棋子上if (toPiece.color == fromPiece.color) {return false;}// 将军移动规则if (fromPiece.type == JIANG) {// 只能在九宫格内移动if (fromPiece.color == RED_PLAYER) {if (toX < 3 || toX > 5 || toY < 7) return false;} else {if (toX < 3 || toX > 5 || toY > 2) return false;}// 只能移动一步if (abs(toX - fromX) + abs(toY - fromY) != 1) {return false;}return true;}// 士移动规则if (fromPiece.type == SHI) {// 只能在九宫格内移动if (fromPiece.color == RED_PLAYER) {if (toX < 3 || toX > 5 || toY < 7) return false;} else {if (toX < 3 || toX > 5 || toY > 2) return false;}// 只能斜着移动一步if (abs(toX - fromX) != 1 || abs(toY - fromY) != 1) {return false;}return true;}// 相移动规则if (fromPiece.type == XIANG) {// 不能过河if (fromPiece.color == RED_PLAYER && toY < 5) return false;if (fromPiece.color == BLACK_PLAYER && toY > 4) return false;// 移动距离if (abs(toX - fromX) != 2 || abs(toY - fromY) != 2) {return false;}// 检查象眼是否被堵int eyeX = (fromX + toX) / 2;int eyeY = (fromY + toY) / 2;if (board[eyeY][eyeX].color != EMPTY) {return false;}return true;}// 马移动规则if (fromPiece.type == MA) {int dx = abs(toX - fromX);int dy = abs(toY - fromY);if (!((dx == 1 && dy == 2) || (dx == 2 && dy == 1))) {return false;}// 检查马腿是否被堵if (dx == 1) { // 竖着走int blockY = fromY + (toY > fromY ? 1 : -1);if (board[blockY][fromX].color != EMPTY) {return false;}} else { // 横着走int blockX = fromX + (toX > fromX ? 1 : -1);if (board[fromY][blockX].color != EMPTY) {return false;}}return true;}// 车移动规则if (fromPiece.type == JU) {// 必须直线移动if (fromX != toX && fromY != toY) {return false;}// 检查路径上是否有其他棋子if (fromX == toX) { // 垂直移动int startY = min(fromY, toY) + 1;int endY = max(fromY, toY);for (int y = startY; y < endY; y++) {if (board[y][fromX].color != EMPTY) {return false;}}} else { // 水平移动int startX = min(fromX, toX) + 1;int endX = max(fromX, toX);for (int x = startX; x < endX; x++) {if (board[fromY][x].color != EMPTY) {return false;}}}return true;}// 炮移动规则if (fromPiece.type == PAO) {// 必须直线移动if (fromX != toX && fromY != toY) {return false;}int count = 0; // 路径上的棋子数if (fromX == toX) { // 垂直移动int startY = min(fromY, toY) + 1;int endY = max(fromY, toY);for (int y = startY; y < endY; y++) {if (board[y][fromX].color != EMPTY) {count++;}}} else { // 水平移动int startX = min(fromX, toX) + 1;int endX = max(fromX, toX);for (int x = startX; x < endX; x++) {if (board[fromY][x].color != EMPTY) {count++;}}}// 炮移动需要0个或1个炮架if (toPiece.color == EMPTY) { // 移动到空位if (count != 0) {return false;}} else { // 吃子if (count != 1) {return false;}}return true;}// 兵移动规则if (fromPiece.type == BING) {// 红方if (fromPiece.color == RED_PLAYER) {// 过河前只能向上if (fromY > 4 && toY != fromY - 1) {return false;}// 过河后可以左右移动if (fromY <= 4) {if (!((toX == fromX && toY == fromY - 1) || (toY == fromY && abs(toX - fromX) == 1))) {return false;}}} // 黑方else {// 过河前只能向下if (fromY < 5 && toY != fromY + 1) {return false;}// 过河后可以左右移动if (fromY >= 5) {if (!((toX == fromX && toY == fromY + 1) || (toY == fromY && abs(toX - fromX) == 1))) {return false;}}}return true;}return true;
}// 检查是否将军
bool isCheck(const vector<vector<Piece>>& board, PieceColor kingColor) {// 找到将/帅的位置int kingX = -1, kingY = -1;for (int y = 0; y < BOARD_HEIGHT; y++) {for (int x = 0; x < BOARD_WIDTH; x++) {if (board[y][x].type == JIANG && board[y][x].color == kingColor) {kingX = x;kingY = y;break;}}if (kingX != -1) break;}if (kingX == -1) return false; // 将/帅不存在,游戏应该已经结束// 检查所有对方棋子是否能攻击到将/帅PieceColor opponentColor = (kingColor == RED_PLAYER) ? BLACK_PLAYER : RED_PLAYER;for (int y = 0; y < BOARD_HEIGHT; y++) {for (int x = 0; x < BOARD_WIDTH; x++) {if (board[y][x].color == opponentColor) {if (isValidMove(board, x, y, kingX, kingY)) {return true;}}}}return false;
}// 检查将帅是否面对面(中间没有棋子)
bool areKingsFacing(const vector<vector<Piece>>& board) {int redKingX = -1, redKingY = -1;int blackKingX = -1, blackKingY = -1;// 找到红将和黑帅的位置for (int y = 0; y < BOARD_HEIGHT; y++) {for (int x = 0; x < BOARD_WIDTH; x++) {if (board[y][x].type == JIANG) {if (board[y][x].color == RED_PLAYER) {redKingX = x;redKingY = y;} else {blackKingX = x;blackKingY = y;}}}}// 如果有一个将/帅不存在,返回falseif (redKingX == -1 || blackKingX == -1) return false;// 检查是否在同一列if (redKingX != blackKingX) return false;// 检查中间是否有棋子int startY = min(redKingY, blackKingY) + 1;int endY = max(redKingY, blackKingY);for (int y = startY; y < endY; y++) {if (board[y][redKingX].color != EMPTY) {return false; // 中间有棋子,不构成面对面}}return true; // 将帅面对面
}// 检查移动后是否会导致自己的将/帅被将军(防止送将)
bool moveCausesSelfCheck(vector<vector<Piece>> board, int fromX, int fromY, int toX, int toY) {// 模拟移动Piece movedPiece = board[fromY][fromX];board[toY][toX] = movedPiece;board[toY][toX].x = toX;board[toY][toX].y = toY;board[fromY][fromX] = {NONE, EMPTY, fromX, fromY, false};// 检查移动后自己的将/帅是否被将军return isCheck(board, movedPiece.color);
}// 检查移动是否能解除将军
bool canResolveCheck(vector<vector<Piece>> board, int fromX, int fromY, int toX, int toY) {// 模拟移动Piece movedPiece = board[fromY][fromX];board[toY][toX] = movedPiece;board[toY][toX].x = toX;board[toY][toX].y = toY;board[fromY][fromX] = {NONE, EMPTY, fromX, fromY, false};// 检查移动后是否仍然被将军return !isCheck(board, movedPiece.color);
}// 检查是否困毙(无棋可走)
bool isStalemate(vector<vector<Piece>> board, PieceColor currentColor) {// 尝试所有可能的移动for (int fromY = 0; fromY < BOARD_HEIGHT; fromY++) {for (int fromX = 0; fromX < BOARD_WIDTH; fromX++) {// 只检查当前玩家的棋子if (board[fromY][fromX].color != currentColor) continue;// 尝试移动到所有可能的位置for (int toY = 0; toY < BOARD_HEIGHT; toY++) {for (int toX = 0; toX < BOARD_WIDTH; toX++) {// 跳过无效移动if (!isValidMove(board, fromX, fromY, toX, toY)) continue;// 检查移动是否能解除将军且不会导致自己被将军if (!moveCausesSelfCheck(board, fromX, fromY, toX, toY) && canResolveCheck(board, fromX, fromY, toX, toY)) {return false; // 有合法移动,不是困毙}}}}}return true; // 没有合法移动,困毙
}// 检查游戏是否结束
GameState checkGameState(vector<vector<Piece>>& board, GameState currentState) {// 检查将/帅是否存在bool redGeneral = false;bool blackGeneral = false;for (int i = 0; i < BOARD_HEIGHT; i++) {for (int j = 0; j < BOARD_WIDTH; j++) {if (board[i][j].type == JIANG) {if (board[i][j].color == RED_PLAYER) {redGeneral = true;} else {blackGeneral = true;}}}}if (!redGeneral) return BLACK_WIN;if (!blackGeneral) return RED_WIN;// 检查是否将军bool redInCheck = isCheck(board, RED_PLAYER);bool blackInCheck = isCheck(board, BLACK_PLAYER);// 根据当前回合确定状态if (currentState == RED_TURN || currentState == RED_CHECK) {if (redInCheck) {// 检查是否困毙if (isStalemate(board, RED_PLAYER)) {return BLACK_WIN;}return RED_CHECK;}} else if (currentState == BLACK_TURN || currentState == BLACK_CHECK) {if (blackInCheck) {// 检查是否困毙if (isStalemate(board, BLACK_PLAYER)) {return RED_WIN;}return BLACK_CHECK;}}// 如果没有将军,返回正常回合状态if (currentState == RED_CHECK) return RED_TURN;if (currentState == BLACK_CHECK) return BLACK_TURN;return currentState;
}int main() {// 初始化图形窗口initgraph(800, 700);setbkcolor(EGERGB(0x33, 0x66, 0x99));cleardevice();// 初始化游戏状态vector<vector<Piece>> board;initBoard(board);GameState state = RED_TURN;Piece* selectedPiece = nullptr;// 主游戏循环while (true) {// 处理鼠标事件if (mousemsg()) {mouse_msg msg = getmouse();if (msg.is_left() && msg.is_down()) {// 计算点击的棋盘位置int boardX = (msg.x - BOARD_X + CELL_SIZE/2) / CELL_SIZE;int boardY = (msg.y - BOARD_Y + CELL_SIZE/2) / CELL_SIZE;// 确保在棋盘范围内if (boardX >= 0 && boardX < BOARD_WIDTH && boardY >= 0 && boardY < BOARD_HEIGHT) {Piece& clickedPiece = board[boardY][boardX];// 如果没有选中棋子if (selectedPiece == nullptr) {// 点击了自己的棋子if ((state == RED_TURN && clickedPiece.color == RED_PLAYER) ||(state == BLACK_TURN && clickedPiece.color == BLACK_PLAYER) ||(state == RED_CHECK && clickedPiece.color == RED_PLAYER) ||(state == BLACK_CHECK && clickedPiece.color == BLACK_PLAYER)) {// 取消所有棋子的选中状态clearAllSelections(board);// 选中当前点击的棋子clickedPiece.selected = true;selectedPiece = &clickedPiece;}} // 如果已经选中了棋子else {// 检查移动是否合法bool validMove = isValidMove(board, selectedPiece->x, selectedPiece->y, boardX, boardY);// 防止送将:检查移动后是否会导致自己的将/帅被将军if (validMove && moveCausesSelfCheck(board, selectedPiece->x, selectedPiece->y, boardX, boardY)) {validMove = false;// 显示不能送将的提示setfont(20, 0, "宋体");setcolor(EGE_ORANGE);setbkmode(TRANSPARENT);outtextxy(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 200, "不能送将!");}// 检查将帅是否面对面if (validMove) {// 模拟移动vector<vector<Piece>> tempBoard = board;tempBoard[boardY][boardX] = tempBoard[selectedPiece->y][selectedPiece->x];tempBoard[boardY][boardX].x = boardX;tempBoard[boardY][boardX].y = boardY;tempBoard[selectedPiece->y][selectedPiece->x] = {NONE, EMPTY, selectedPiece->x, selectedPiece->y, false};// 检查移动后是否会导致将帅面对面if (areKingsFacing(tempBoard)) {validMove = false;// 显示不能面对面的提示setfont(20, 0, "宋体");setcolor(EGE_ORANGE);setbkmode(TRANSPARENT);outtextxy(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 220, "将帅不能见面!");}}// 如果在将军状态下,还需要检查移动是否能解除将军if (validMove && (state == RED_CHECK || state == BLACK_CHECK)) {validMove = canResolveCheck(board, selectedPiece->x, selectedPiece->y, boardX, boardY);if (!validMove) {// 显示不能移动的提示setfont(20, 0, "宋体");setcolor(EGE_ORANGE);setbkmode(TRANSPARENT);outtextxy(BOARD_X + BOARD_WIDTH * CELL_SIZE + 20, BOARD_Y + 200, "必须解除将军!");}}if (validMove) {// 移动棋子board[boardY][boardX] = *selectedPiece;board[boardY][boardX].x = boardX;board[boardY][boardX].y = boardY;board[selectedPiece->y][selectedPiece->x] = {NONE, EMPTY, selectedPiece->x, selectedPiece->y, false};// 切换回合state = (state == RED_TURN || state == RED_CHECK) ? BLACK_TURN : RED_TURN;// 检查游戏状态state = checkGameState(board, state);}// 取消选中状态selectedPiece->selected = false;selectedPiece = nullptr;}}}}// 处理键盘事件if (kbhit()) {int key = getch();// 按ESC退出if (key == 27) {break;}// 按R重新开始else if (key == 'r' || key == 'R') {initBoard(board);state = RED_TURN;selectedPiece = nullptr;}}// 绘制游戏drawBoard();drawPieces(board);drawGameState(state);// 延迟一下,避免过快刷新delay_ms(5);}closegraph();return 0;
}

http://www.dtcms.com/a/435885.html

相关文章:

  • 房产网站源码wordpresswordpress知识库
  • 南京做网站的额wordpress使用文档
  • 新手学做网站学要做哪些亚马逊amz123
  • 三河建设厅网站湛江网站建设制作维护
  • 深入理解 Linux 进程间通信(下):System V IPC 与内核管理机制
  • 谷歌seo建站网页搭建流程
  • SOME/IP协议保姆级教程
  • ps做登录网站手游平台免费代理加盟
  • 数据库做网站和做软件有什么不一样局域网多网站建设
  • 【面板数据】地市合作创新数据集(2006-2023年)
  • 怎么在自己的网站上做链接互联网建设
  • 北京新机场建设指挥部网站旅游网站模块分类
  • 四川手机网站设计小公司简介模板
  • 潍坊网站建设 APP开发小程序公司官方网站建设
  • 5G MIB / SIB in a Nutshell
  • 衡水外贸网站建设今天济南刚刚发生的新闻
  • 内蒙古001
  • Python常用三方模块——requests
  • 企业官网怎么和别的网站做链接网站淘宝客怎么做
  • 邯郸的网站建设深圳网站建设 利科技有限公司
  • 做网站算 自由职业者莞城发布最新通告
  • 网站定制的公司深圳建设营销型网站
  • 网站推广网络推广网站视频如何下载
  • 好的网站设计中国空间站太小了
  • 建站平台 在线提交表格功能太原营销型网站建设
  • 工信部 网站备案规定网页设计的要点有哪些
  • 网络营销导向的企业网站建设的要求pc营销型网站
  • 老干支部网站建设方案网站建设服务杭州
  • 生成器软件长沙谷歌seo收费
  • C语言计算行列式的值