#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
// 棋子类型枚举
typedef enum {
GENERAL, // 将/帅
ADVISOR, // 士/仕
ELEPHANT, // 象/相
HORSE, // 马/傌
CHARIOT, // 车/俥
CANNON, // 炮/炮
SOLDIER // 卒/兵
} PieceType;
// 棋子颜色枚举
typedef enum {
RED, // 红方
BLACK // 黑方
} PieceColor;
// 棋子结构体
typedef struct {
PieceType type;
PieceColor color;
int x; // 横坐标(0-9)
int y; // 纵坐标(0-8)
bool alive; //是否存活
} ChessPiece;
// 棋盘结构体
typedef struct {
ChessPiece pieces[32]; //棋子结构体数组用于装棋子的信息
ChessPiece* board[10][9]; // 棋子结构体指针二维数组 用于装载棋子所在棋盘的位置
int isRedTurn;//当前回合
int isGameOver;//游戏是否结束
int moveCount;//移动计数
} ChessBoard;
// 初始化棋子
void init_piece(ChessPiece* piece, PieceType type, PieceColor color, int x, int y) {
piece->type = type;
piece->color = color;
piece->x = x;
piece->y = y;
piece->alive = 1;
}
// 初始化棋盘
void init_board(ChessBoard* board) {
memset(board->board, 0, sizeof(board->board));
board->isRedTurn = 1;
board->isGameOver = 1;
board->moveCount = 0;
// 红方棋子(索引0-15)
init_piece(&board->pieces[0], CHARIOT, RED, 9, 0);
init_piece(&board->pieces[1], HORSE, RED, 9, 1);
init_piece(&board->pieces[2], ELEPHANT, RED, 9, 2);
init_piece(&board->pieces[3], ADVISOR, RED, 9, 3);
init_piece(&board->pieces[4], GENERAL, RED, 9, 4);
init_piece(&board->pieces[5], ADVISOR, RED, 9, 5);
init_piece(&board->pieces[6], ELEPHANT, RED, 9, 6);
init_piece(&board->pieces[7], HORSE, RED, 9, 7);
init_piece(&board->pieces[8], CHARIOT, RED, 9, 8);
init_piece(&board->pieces[9], CANNON, RED, 7, 1);
init_piece(&board->pieces[10], CANNON, RED, 7, 7);
init_piece(&board->pieces[11], SOLDIER, RED, 6, 0);
init_piece(&board->pieces[12], SOLDIER, RED, 6, 2);
init_piece(&board->pieces[13], SOLDIER, RED, 6, 4);
init_piece(&board->pieces[14], SOLDIER, RED, 6, 6);
init_piece(&board->pieces[15], SOLDIER, RED, 6, 8);
// 黑方棋子(索引16-31)
init_piece(&board->pieces[16], CHARIOT, BLACK, 0, 0);
init_piece(&board->pieces[17], HORSE, BLACK, 0, 1);
init_piece(&board->pieces[18], ELEPHANT, BLACK, 0, 2);
init_piece(&board->pieces[19], ADVISOR, BLACK, 0, 3);
init_piece(&board->pieces[20], GENERAL, BLACK, 0, 4);
init_piece(&board->pieces[21], ADVISOR, BLACK, 0, 5);
init_piece(&board->pieces[22], ELEPHANT, BLACK, 0, 6);
init_piece(&board->pieces[23], HORSE, BLACK, 0, 7);
init_piece(&board->pieces[24], CHARIOT, BLACK, 0, 8);
init_piece(&board->pieces[25], CANNON, BLACK, 2, 1);
init_piece(&board->pieces[26], CANNON, BLACK, 2, 7);
init_piece(&board->pieces[27], SOLDIER, BLACK, 3, 0);
init_piece(&board->pieces[28], SOLDIER, BLACK, 3, 2);
init_piece(&board->pieces[29], SOLDIER, BLACK, 3, 4);
init_piece(&board->pieces[30], SOLDIER, BLACK, 3, 6);
init_piece(&board->pieces[31], SOLDIER, BLACK, 3, 8);
// 将棋子放置到棋盘上
for (int i = 0; i < 32; i++) {
ChessPiece* piece = &board->pieces[i];
board->board[piece->x][piece->y] = piece;
}
}
// 获取棋子名称(中文)
char* get_piece_name(ChessPiece* piece) {
if (piece == NULL || !piece->alive) return 0 ;
char* names[2][7] = {
{"帅", "仕", "相", "马", "车", "炮", "兵"}, // 红方
{"将", "士", "象", "马", "车", "炮", "卒"} // 黑方
};
return names[piece->color][piece->type];
}
// 绘制标准象棋棋盘
void draw_board(ChessBoard* board) {
printf("\n");
printf(" 0 1 2 3 4 5 6 7 8");
printf("\n");
for (int x = 0; x < 10; x++)
{
printf("%d ",x);
for (int y = 0; y< 9; y++)
{
ChessPiece* piece = board->board[x][y];
if (piece != NULL && piece->alive)
{
if (piece->color == RED) {
printf("\033[47;31m%s\033[0m ", get_piece_name(piece));
} else {
printf("\033[47;30m%s\033[0m ", get_piece_name(piece));
}
}
else printf(" + ");
}
printf("\n");
// 楚河汉界标记
if (x == 4)
{
printf(" 楚 河");
printf(" 汉 界");
printf("\n");
}
}
printf("回合: %s方 步数: %d\n", board->isRedTurn ? "红" : "黑", board->moveCount);
}
// 检查坐标是否有效
int is_valid_position(int x, int y) {
return x >= 0 && x < 10 && y >= 0 && y < 9;
}
// 车移动规则验证
int is_valid_chariot_move(ChessBoard* board, int fromX, int fromY, int toX, int toY) {
if (fromX != toX && fromY != toY) return 0;
int step, i;
//判断原坐标与目标中间有没有其他棋子
if (fromX == toX) {
step = (fromY < toY) ? 1 : -1;
for (i = fromY + step; i != toY; i += step) {
if (board->board[fromX][i] != NULL && board->board[fromX][i]->alive) {
return 0;
}
}
} else {
step = (fromX < toX) ? 1 : -1;
for (i = fromX + step; i != toX; i += step) {
if (board->board[i][fromY] != NULL && board->board[i][fromY]->alive) {
return 0;
}
}
}
return 1;
}
// 炮移动规则验证
int is_valid_cannon_move(ChessBoard* board, int fromX, int fromY, int toX, int toY) {
if (fromX != toX && fromY != toY) return 0;
int step, i,count=0;
//判断原坐标与目标中间有没有其他棋子
if (fromX == toX) {
step = (fromY < toY) ? 1 : -1;
for (i = fromY + step; i != toY; i += step) {
if (board->board[fromX][i] != NULL && board->board[fromX][i]->alive) {
count++;
}
}
} else {
step = (fromX < toX) ? 1 : -1;
for (i = fromX + step; i != toX; i += step) {
if (board->board[i][fromY] != NULL && board->board[i][fromY]->alive) {
count++;
}
}
}
ChessPiece *fromPiece=board->board[fromX][fromY];
ChessPiece *toPiece = board->board[toX][toY];
if(count==0)
{
if(toPiece==NULL)return 1;
}
if(count==1)
{
if(toPiece->color!=fromPiece->color) return 1;
}
return 0;
}
// 马移动规则验证
int is_valid_horse_move(ChessBoard* board, int fromX, int fromY, int toX, int toY) {
int dx = abs(toX - fromX);
int dy = abs(toY - fromY);
if (!((dx == 2 && dy == 1) || (dx == 1 && dy == 2))) return 0;
// 检查马脚
// 上下方向有没有棋子
if (dx == 2) {
int middleX = fromX + (toX > fromX ? 1 : -1);
if (board->board[middleX][fromY] != NULL && board->board[middleX][fromY]->alive) {
return 0;
}
}
//左右方向有没有棋子
else
{
int middleY = fromY + (toY > fromY ? 1 : -1);
if (board->board[fromX][middleY] != NULL && board->board[fromX][middleY]->alive) {
return 0;
}
}
return 1;
}
// 象移动规则验证
int is_valid_elephant_move(ChessBoard* board, int fromX, int fromY, int toX, int toY, bool isRed) {
int dx = abs(toX - fromX);
int dy = abs(toY - fromY);
if (dx != 2 || dy != 2) return 0;
// 检查象眼
int middleX = (fromX + toX) / 2;
int middleY = (fromY + toY) / 2;
if (board->board[middleX][middleY] != NULL && board->board[middleX][middleY]->alive) {
return 0;
}
// 象不能过河
if (isRed && toX < 5) return 0;
if (!isRed && toX > 4) return 0;
return 1;
}
// 士移动规则验证
int is_valid_advisor_move(int fromX, int fromY, int toX, int toY, bool isRed) {
int dx = abs(toX - fromX);
int dy = abs(toY - fromY);
// 士只能在九宫格内移动
if (toY < 3 || toY > 5) return 0;
if (dx != 1 || dy != 1) return 0;
if (isRed) {
return toX >= 7 && toX <= 9;
} else {
return toX >= 0 && toX <= 2;
}
}
// 将帅移动规则验证
int is_valid_general_move(int fromX, int fromY, int toX, int toY, bool isRed) {
int dx = abs(toX - fromX);
int dy = abs(toY - fromY);
// 将帅只能在九宫格内移动
if (toY < 3 || toY > 5) return 0;
if (isRed) {
if (toX < 7 || toX > 9) return 0;
} else {
if (toX < 0 || toX> 2) return 0;
}
// 将帅只能走一步
if ((dx == 1 && dy == 0) || (dx == 0 && dy == 1)) {
return 1;
}
return 0;
}
// 兵卒移动规则验证
int is_valid_soldier_move(int fromX, int fromY, int toX, int toY, bool isRed) {
int dx = toX - fromX;
int dy = toY - fromY;
if (isRed) {
// 红方兵向上移动
if (dx == -1 && dy == 0) return 1; // 向前
if (fromX < 5 && (dx == -1 || dx == 0)) return 1; // 过河后可以横向移动
} else {
// 黑方卒向下移动
if (dx == 1 && dy == 0) return 1; // 向前
if (fromX > 4 &&(dx == 1 || dx == 0 )) return 1; // 过河后可以横向移动
}
return 0;
}
// 检查移动是否合法
int is_valid_move(ChessBoard* board, int fromX, int fromY, int toX, int toY) {
// 检查坐标是否有效
if (!is_valid_position(fromX, fromY) || !is_valid_position(toX, toY)) {
return 0;
}
ChessPiece* fromPiece = board->board[fromX][fromY];
ChessPiece* toPiece = board->board[toX][toY];
// 检查是否有棋子可移动
if (fromPiece == NULL || !fromPiece->alive) {
return 0;
}
// 检查是否轮到当前玩家
if (fromPiece->color == RED && !board->isRedTurn) return 0;
if (fromPiece->color == BLACK && board->isRedTurn) return 0;
// 检查目标位置是否有己方棋子
if (toPiece != NULL && toPiece->alive && toPiece->color == fromPiece->color) {
return 0;
}
// 根据不同棋子类型检查移动规则
switch (fromPiece->type) {
case CHARIOT:
return is_valid_chariot_move(board, fromX, fromY, toX, toY);
case HORSE:
return is_valid_horse_move(board, fromX, fromY, toX, toY);
case CANNON:
return is_valid_cannon_move(board, fromX, fromY, toX, toY);
case ELEPHANT:
return is_valid_elephant_move(board, fromX, fromY, toX, toY, fromPiece->color == RED);
case ADVISOR:
return is_valid_advisor_move(fromX, fromY, toX, toY, fromPiece->color == RED);
case GENERAL:
return is_valid_general_move(fromX, fromY, toX, toY, fromPiece->color == RED);
case SOLDIER:
return is_valid_soldier_move(fromX, fromY, toX, toY, fromPiece->color == RED);
default:
return 0;
}
}
// 移动棋子
int move_piece(ChessBoard* board, int fromX, int fromY, int toX, int toY) {
if (!is_valid_move(board, fromX, fromY, toX, toY))
{
printf("无效移动!\n");
return 0;
}
ChessPiece* fromPiece = board->board[fromX][fromY];
ChessPiece* toPiece = board->board[toX][toY];
// 执行移动
if (toPiece != NULL)
{
toPiece->alive = 0; // 吃掉对方棋子
if(toPiece->type==GENERAL)
{
printf("%s方已死,游戏结束!\n",board->isRedTurn?"黑":"红");
board->isGameOver=0;
}
}
board->board[fromX][fromY] = NULL;
board->board[toX][toY] = fromPiece;
fromPiece->x = toX;
fromPiece->y = toY;
// 切换玩家
board->isRedTurn = !board->isRedTurn;
board->moveCount++;
return 1;
}
int main() {
ChessBoard board;
init_board(&board);
printf("********* 开始游戏!*********\n");
// 主游戏循环
while (board.isGameOver)
{
printf("********* 象棋游戏!*********\n");
draw_board(&board);
printf("输入格式: 起始行列 目标行列 (如: 51 52)\n");
printf("%s方走棋 > ", board.isRedTurn ? "红" : "黑");
int fromCol, fromRow, toCol, toRow;
if (scanf("%1d%1d %1d%1d", &fromRow, &fromCol, &toRow, &toCol) != 4) {
printf("输入格式错误!\n");
continue;
}
if (!move_piece(&board, fromRow, fromCol, toRow, toCol)) {
printf("按回车键继续...");
while (getchar() != '\n'); // 清除输入缓冲区
getchar();
}
system("clear");
}
// 游戏结束显示
draw_board(&board);
printf("游戏结束!%s方获胜!\n", board.isRedTurn ? "红" : "黑");
return 0;
}