# C++ 中国象棋的实现流程详解

```enum Pieces //棋子
{
NONE = -1,
車, 馬, 象, 士, 将, 砲, 卒,
俥, 马, 相, 仕, 帥, 炮, 兵,
BEGIN, END,
};
//给id赋值
enum Pieces redChess[] = { 車, 馬, 象, 士, 将, 砲, 卒 };
enum Pieces blackChess[] = { 俥, 马, 相, 仕, 帥, 炮, 兵 };
//绘制时转化成字符串
const char* ChessName[] = { "車","馬","象","士","将","砲","卒","俥", "马", "相", "仕", "帥", "炮", "兵" };```

```//每一个棋子的属性
struct Chess
{
enum Pieces id;		//棋子名称
DWORD type;			//棋子类型，红？黑？
short x;
short y;
bool  isRiver;			//是否过了河
};

//游戏地图
struct Chess map[ROW][COL];

struct State
{
int begr;
int begc;
int endr;
int endc;
int state;
}state = {-1,-1,-1,-1,BEGIN};```

```//初始化数据
void init()
{
//遍历地图
for (size_t i = 0; i < ROW; i++)
{
size_t temp = 0;
for (size_t k = 0; k < COL; k++)
{
map[i][k].id = NONE;	//先把棋子置为没有
if (i <= 4)	//黑棋子
{
map[i][k].type = BLACK;
if (i == 0)	//放置第一行的棋子
{
//0 1 2 3 4
if (k <= 4)
{
temp = k;
}
// 3 2 1 0
else
{
// k == 5
temp = 4 - (k - 4);
/*
4 - (5-4)	//3
4 - (6-4)	//2
4 - (7-4)	//1
4 - (8-4)	//0
*/
}
map[i][k].id = blackChess[temp];
}
//设置炮
if (i == 2 && (k == 1 || k == 7))
{
map[i][k].id = blackChess[5];
}
//设置兵
if (i == 3 && k % 2 == 0)
{
map[i][k].id = blackChess[6];
}
}
else       //红棋
{
map[i][k].type = RED;
if (i == 9)	//放置第一行的棋子
{
//0 1 2 3 4
if (k <= 4)
{
temp = k;
}
// 3 2 1 0
else
{
// k == 5
temp = 4 - (k - 4);
/*
4 - (5-4)	//3
4 - (6-4)	//2
4 - (7-4)	//1
4 - (8-4)	//0
*/
}
map[i][k].id = redChess[temp];
}
//设置炮
if (i == 7 && (k == 1 || k == 7))
{
map[i][k].id = redChess[5];
}
//设置兵
if (i == 6 && k % 2 == 0)
{
map[i][k].id = redChess[6];
}
}
map[i][k].isRiver = false;
map[i][k].x = k * GRID_SIZE + INTERVAL;
map[i][k].y = i * GRID_SIZE + INTERVAL;
}
}
}```

```//绘制
void draw()
{
setfillcolor(RGB(252, 215, 162));
setlinestyle(PS_SOLID, 2);
//设置文字的样式
settextstyle(30, 0, "楷体");
for (size_t i = 0; i < ROW; i++)
{
for (size_t k = 0; k < COL; k++)
{
if (map[i][k].id == NONE)
continue;
settextcolor(map[i][k].type);
setlinecolor(map[i][k].type);
//绘制棋子
fillcircle(map[i][k].x, map[i][k].y, 30);
fillcircle(map[i][k].x, map[i][k].y, 25);
outtextxy(map[i][k].x - 15, map[i][k].y - 15, ChessName[map[i][k].id]);
}
}
}```

```//鼠标操作
void mouseEvent()
{
ExMessage msg;	//定义消息结构体变量
if(peekmessage(&msg, EM_MOUSE))
{
if (msg.message == WM_LBUTTONDOWN)	//鼠标左键按下
{
//通过鼠标坐标得出点击的数组的下标
//k * GRID_SIZE + INTERVAL = x;
int col = (msg.x - INTERVAL) / GRID_SIZE;
int row = (msg.y - INTERVAL) / GRID_SIZE;

//下标校准
if (msg.x > map[row][col].x + 30 && msg.y < map[row][col].y + 30)
{
col++;
}
if (msg.x < map[row][col].x + 30 && msg.y > map[row][col].y + 30)
{
row++;
}
if (msg.x > map[row][col].x + 30 && msg.y > map[row][col].y + 30)
{
row++;
col++;
}
//printf("(%d %d)\n", row, col);

if (state.state == BEGIN)
{
state.begr = row;
state.begc = col;
state.state = END;
}
else if (state.state == END)
{
state.endr = row;
state.endc = col;
state.state = BEGIN;
}
chessMove();
}
}
}```

```//移动棋子
void chessMove()
{
printf("beg(%d %d) end(%d %d)\n", state.begr, state.begc, state.endr, state.endc);
bool canMove = false;
//什么情况下能够移动棋子
if (!(state.begr == state.endr && state.begc == state.endc) &&	//点击的不是同一个棋子
state.endr!=-1 && state.begr!=-1&&		//下标必须合法
map[state.begr][state.begc].id != NONE//没有棋子不能移动
/*&&map[state.begr][state.begc].type != map[state.endr][state.endc].type*/)	//不能自己吃自己
{

switch (map[state.begr][state.begc].id)
{
case 車:
case 俥:
if (state.begr == state.endr || state.begc == state.endc)
{
//起始点和结束点之间是否有阻碍
if (hasBlock(&state))
{
canMove = true;
}

}
break;
case 馬:
case 马:
break;
case 象:
case 相:
break;
case 士:
case 仕:
break;
case 将:
case 帥:
break;
case 砲:
case 炮:
break;
case 卒:
case 兵:
break;
default:
break;
}
if (canMove)
{
printf("canMove\n");
map[state.endr][state.endc].id = map[state.begr][state.begc].id;
map[state.begr][state.begc].id = NONE;

map[state.endr][state.endc].isRiver = map[state.begr][state.begc].isRiver;
map[state.endr][state.endc].type = map[state.begr][state.begc].type;
}
}
}```

```int main()
{
//创建图形窗口
initgraph(740, 820,EW_SHOWCONSOLE);
//设置背景模式
setbkmode(TRANSPARENT);
//贴棋盘
IMAGE img_board;

init();
//双缓冲绘图，防止闪屏
BeginBatchDraw();
while (true)
{
cleardevice();
putimage(0, 0, &img_board);
draw();
mouseEvent();

FlushBatchDraw();
}
EndBatchDraw();

getchar();
return 0;
}```