纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

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

MAX在码字   2021-11-19 我要评论
想了解C++ 中国象棋的实现流程详解的相关内容吗MAX在码字在本文为您仔细讲解C++ 中国象棋的相关知识和一些Code实例欢迎阅读和指正我们先划重点:C++,中国象棋,C++,象棋下面大家一起来学习吧。

中国象棋的中国棋文化也是中华民族的文化瑰宝它源远流长趣味浓厚基本规则简明易懂。中国象棋在中国的群众中基础远远超过围棋是普及最广的棋类项目中国象棋已流传到十几个国家和地区。 中国象棋使用方形格状棋盘圆形棋子共有32个红黑二色各有16个棋子摆放和活动在交叉点上。双方交替行棋先把对方的将(帅)“将死”的一方获胜。

我们今天就来看看我们自己能不能写出这样一个游戏呢?

今天就不话不多说了先说一下今天我们做的是一个简易版的单机中国象棋希望大家理解联网对弈的话需要用到的知识过多数据库以及网络协议这些大部分同学都没有学所以我们今天就简单的实现《中国象棋》的简单对弈主要是希望同学们可以理解其中的逻辑关系之后就可以更好的去完善

行吧我们现在就开始吧!!!

今天先出场的就不是我们的老朋友结构体了而是我们的新朋友枚举类型

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;
	loadimage(&img_board, "./res/ChessBoard.png");
	
 
	init();
	//双缓冲绘图防止闪屏
	BeginBatchDraw();
	while (true)
	{
		cleardevice();
		putimage(0, 0, &img_board);
		draw();
		mouseEvent();
 
		FlushBatchDraw();
	}
	EndBatchDraw();
 
 
	getchar();
	return 0;
}

这样一个简易版的《中国象棋》游戏项目就解决啦重点就是逻辑一定要想清楚想要实现联网的同学就要更加的去想清楚以及去提高自己的能力好啦希望可以让大家从中感受到编程的快乐吧也希望大家可以给UP主一个关注非常感谢大家了!!!


相关文章

猜您喜欢

网友评论

Copyright 2020 www.tdogsoftware.com 【零度软件园】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式