C/C++入门项目:五子棋

目录

  • EasyX函数库介绍
  • 预备工作
  • 棋盘
  • 落子
  • 规则
  • 工具

EasyX函数库介绍

EasyX 是针对 C++ 的图形库,可以帮助 C/C++ 初学者快速上手图形和游戏编程。
下载链接:点我
参考文档:https://docs.easyx.cn。

预备工作

  1. 函数库
	#include 
	#include 
  1. 数据结构
	//N 表示棋盘大小,START 表示棋盘起点距离窗口左上角距离,OFFSET 表示方格长度。
	#define N      18
	#define START  45
	#define OFFSET 24
	//记录棋盘状态,0-Null,1-Black,2-White
	int record[N+1][N+1];
	//是否开始游戏
	bool flag = false;
	//记录棋子状态
	struct point {
		//框选坐标
		int x=0;
		int y=0;
		bool show=false;//是否展示
		//棋子坐标
		int row=0;
		int col=0;
		int type=1;
	}p;

  1. 注意事项
  • 对于 VC2008 以及更高版本的编辑器,需要将字符串用 _T() 函数改变编码格式,不然会报错。

棋盘

  1. 设置背景
    初始化棋盘大小为 700*520,并设置棋盘背景为 bg.jpg。
	initgraph(700, 520, EX_SHOWCONSOLE); //EX_SHOWCONSOLE 设置后可以展示控制窗口
	IMAGE bg; //图片对象
	loadimage(&bg, _T(".\\bg.jpg")); //_T()可以将ASCII类型转成unicode类型
	putimage(0, 0, &bg);
  1. 绘制棋盘
  • 设置棋盘边线颜色和格式,并循环绘制 (N+1)*(N+1) 条线段。
	setlinecolor(RGB(0,0,0));
	setlinestyle(PS_SOLID, 1);
	for (int i = 0; i <= N; i++)
	{
		line(START, START + OFFSET * i, START + OFFSET * N, START + OFFSET * i);
		line(START + OFFSET * i, START, START + OFFSET * i, START + OFFSET * N);
	}
  • 绘制边框矩形,使得边框更加明显。
	setlinestyle(PS_SOLID, 2);
	rectangle(START, START, START + OFFSET * N, START + OFFSET * N);
  • 绘制五个圆黑点。
	setfillcolor(RGB(0, 0, 0));
	solidcircle(START + OFFSET * 9, START + OFFSET * 9, 6);
	solidcircle(START + OFFSET * 3, START + OFFSET * 3, 6);
	solidcircle(START + OFFSET * 3, START + OFFSET * 15, 6);
	solidcircle(START + OFFSET * 15, START + OFFSET * 3, 6);
	solidcircle(START + OFFSET * 15, START + OFFSET * 15, 6);

落子

  1. 矫正坐标
  • 捕捉鼠标移动事件,并根据捕捉到的坐标 (x,y),进行矫正,确保选择框在中心点位置。
ExMessage msg; //消息对象
if (flag && peekmessage(&msg, EX_MOUSE) && msg.x>=START-12 && msg.x<=START+18*OFFSET+12 && msg.y>=START-12 && msg.y<=START+18*OFFSET+12)
{
	p.show = false;
	//坐标校准
	for (int i = 0; i <= N; i++)
	{
		for (int j = 0; j <= N; j++)
		{
			//左上角坐标
			int board_x = START + i * OFFSET;
			int board_y = START + j * OFFSET;
			if (abs(msg.x - board_x) <= 12 && abs(msg.y - board_y) <= 12)
			{
				p.x = board_x;
				p.y = board_y;
				p.show = true;
				p.row = i;
				p.col = j;
				break;
			} 
		}
		if (p.show)
		{
			break;
		}
	}
}
  1. 绘制选择框
  • 根据是否展示要求和坐标绘制矩形框,用于选择棋子。
if (p.show)
{
	setlinestyle(PS_SOLID, 2);
	setlinecolor(RGB(255, 0, 0));
	rectangle(p.x - 12, p.y - 12, p.x + 12, p.y + 12);
}
  1. 点击下棋
  • 捕捉鼠标点击事件,判断坐标 (x,y) 是否在棋盘范围内,并记录状态和切换棋手。
if (flag && peekmessage(&msg, EX_MOUSE) && msg.x>=START-12 && msg.x<=START+18*OFFSET+12 && msg.y>=START-12 && msg.y<=START+18*OFFSET+12)
{
	//点击下棋
	if (msg.message == WM_LBUTTONDOWN && !record[p.col][p.row])
	{
		record[p.col][p.row] = p.type;
		
		p.type = (p.type == 1) ? 2 : 1;	
	}
}
  1. 绘制棋子
  • 根据棋盘状态记录,判断每一处格子是否需要绘制。
for (int i = 0; i <= N; i++)
{
	for (int j = 0; j <= N; j++)
	{
		switch (record[i][j])
		{
			case 1:
				setfillcolor(RGB(0, 0, 0));
				solidcircle(START + OFFSET * j, START + OFFSET * i, 11);
				break;
			case 2:
				setfillcolor(RGB(255, 255, 255));
				solidcircle(START + OFFSET * j, START + OFFSET * i, 11);
				break;
			default:
				break;
		}
	}
}

规则

  1. 判断逻辑
  • 对于每一次落子,以其为原点,自4个方向循环判断5次是否有连续类型棋子。
  • 因此需要在落子后进行判断。
if (judge_game(p.col, p.row))
{
	draw_board();
	FlushBatchDraw();
	MessageBox(GetHWnd(), _T("You Win!"), p.type==1?_T("Black"):_T("White"), MB_OK); 
	flag = false;
}
  1. 横向
for (int i = row - 4; i <= row; i++)
{
	int num = 0;
	for (int j = 0; j < 5; j++)
	{
		if (i >= 0 && record[col][i+j] == record[col][row])
		{
			num++;
		}
	}
	if (num == 5)
	{
		return true;
	}
}
  1. 竖向
for (int i = col - 4; i <= col; i++)
{
	int num = 0;
	for (int j = 0; j < 5; j++)
	{
		if (i >= 0 && record[i+j][row] == record[col][row])
		{
			num++;
		}
	}
	if (num == 5)
	{
		return true;
	}
}
  1. 左斜向
for (int i = row - 4, j = col - 4; i <= row; i++, j++)
	{
int num = 0;
	for (int k = 0; k < 5; k++)
	{
		if (i >= 0 && j >= 0 && record[j + k][i + k] == record[col][row])
		{
			num++;
		}
	}
	if (num == 5)
	{
		return true;
	}
}
  1. 右斜向
for (int i = row - 4, j = col + 4; i <= row; i++, j--)
{
	int num = 0;
	for (int k = 0; k < 5; k++)
	{
		if (i >= 0 && j <= N && record[j - k][i + k] == record[col][row])
		{
			num++;
		}
	}
	if (num == 5)
	{
		return true;
	}
}

工具

  1. 标题栏
  • 在棋盘右侧绘制 “五子棋” 标题。
	TCHAR title[] = _T("经典五子棋");
	settextcolor(RGB(255,255,255));
	settextstyle(35,0, _T("Consolas"));
	outtextxy(21*OFFSET,50,title);
  1. 开始按钮
  • 绘制矩形模拟 “开始” 按钮。
	setlinestyle(PS_SOLID, 1);
	setlinecolor(RGB(93, 107, 153));
	setfillcolor(RGB(93, 107, 153));
	fillroundrect(START+20*OFFSET,140,START+25*OFFSET,190,15,15);
	TCHAR button[] = _T("开始");
	settextcolor(RGB(198, 220, 184));
	settextstyle(40, 0, _T("Courier"));
	outtextxy(10+22 * OFFSET, 145, button);
  1. 点击开始
  • 点击开始按钮后,初始化棋盘状态,并弹出 “开始” 提示框。
ExMessage msg;
if (!flag && peekmessage(&msg, EX_MOUSE))
{
	if (msg.message == WM_LBUTTONDOWN && msg.x > START + 20 * OFFSET && msg.x < START + 25 * OFFSET && msg.y>140 && msg.y < 190)
	{
		for (int i = 0; i <= N; i++)
		{
			for (int j = 0; j <= N; j++)
			{
				record[i][j] = 0;
			}
		}
		flag = true;
		MessageBox(GetHWnd(), _T("Game Start!"), _T("五子棋"), MB_OK);
	}
}
  1. 执子方
  • 根据当前执子方绘制不同颜色棋子。
	TCHAR name[] = _T("当前棋手");
	settextcolor(RGB(255, 255, 255));
	settextstyle(30, 0, _T("Consolas"));
	outtextxy(22 * OFFSET, 250, name);
	if (p.type == 1)
	{
		setfillcolor(RGB(0, 0, 0));
		solidcircle(12+24 * OFFSET, 330, 12);
	}
	else
	{
		setfillcolor(RGB(255, 255, 255));
		solidcircle(12+24 * OFFSET, 330, 12);
	}

完整项目代码链接:点我
C/C++入门项目:五子棋_第1张图片

你可能感兴趣的:(项目实践,c++,c语言,visual,studio,游戏程序)