五子棋【基于 EasyX 图像库】

这篇博客介绍了如何使用C++和EasyX图形库实现一个五子棋游戏。游戏包括初始化棋盘、下棋功能以及判断输赢的算法。玩家可以选择黑棋或白棋,当某一方连成五子时,游戏结束并显示胜利者。同时,游戏还提供了和棋选项。
摘要由CSDN通过智能技术生成

首先要安装 EasyX

然后就是代码了(基本都有注释),贴在自己 IDEA 上就能运行

//头文件 five_chess.h
//也可以不用这个类了,全部放在 main.cpp 上也行,为了保持习惯,就分一下吧
//当然每个函数的实现也可以放在不同的 cpp 文件上
class five_chess
{
public:
	void initGame(); 
	void playChess();
	int judge_winlos(int a,int b);
};
//main.cpp

#include<iostream>
#include<graphics.h>	//图形库头文件
#include<math.h>
#include<mmsystem.h>	//播放音乐头文件
#pragma comment(lib, "winmm.lib")	//播放音乐库文件
#include"five_chess.h"
 
using namespace std;
int flag = 0;	//表示下棋次数
int board[20][20] = { 0 };	//0表示棋盘没有棋子的状态


//画出棋盘
void five_chess::initGame() {		//初始化游戏

	//绘图环境的库函数
	//调用系统的窗口

	initgraph(600, 500);	//创建自定义窗口(第三个参数 EW_DBLCLKS 的意思可以双击,下棋子的时候可点双击下棋,如果不是,则只能单击,双击的话,会把第二次击认为是再次下棋)
	//setbkcolor(BLUE);		//设置窗口背景颜色
	//cleardevice();			//刷新

	//贴背景图

	loadimage(NULL, "./src/bird.jpg");   //加载窗口的背景图片
	//背景音乐	mci 多媒体控制接口
	mciSendString("play ./src/skyCity.mp3 repeat", 0, 0, 0); //repeat 是重复播放
	
	//绘制棋盘
	//画网格线: 20条横 20条竖 横线间隔25 竖线间隔25 总体划线 500*500
	for (int i = 0; i <= 500; i += 25) {
		line(0, i, 500, i);  //line("点1的x位置","点1的y位置","点2的x位置","点2的y位置")
		line(i, 0, i, 500);
	}
	//line(501, 0, 501, 500);  //这条列线可以不用

	//1.5 输出相关文本信息
	setbkmode(TRANSPARENT);  //设置下面一句的文本内容背景为透明,参数为 OPAQUE 的话,文本内容将为默认的背景色填充(控制台窗口黑色)
	outtextxy(510, 100, "玩家1:黑棋");   //在x,y位置输出文本内容,这里就是(510,100)
	//setbkmode(TRANSPARENT);
	outtextxy(510, 150, "玩家2:白棋");
	//setbkmode(TRANSPARENT);
	outtextxy(535, 200, "和棋");

}



//下棋
void five_chess::playChess() {
	//鼠标
	MOUSEMSG mouse;	//保存鼠标消息
	int x = 0, y = 0;	//坐标
	int a = 0, b = 0;	//行列

	//持续下棋
	while (1)
	{
		
		//获取一个鼠标消息
		mouse = GetMouseMsg();
		//文本"和棋"的大概位置,且要有 uMsg 属性来接收鼠标信号,不然鼠标一移到该位置,就弹出提示框了
		if (mouse.x >= 535 && mouse.x <= 555 && mouse.y >= 200 && mouse.y <= 215&&mouse.uMsg==WM_LBUTTONDOWN)  
		{
			
			int ret_mouse = MessageBox(NULL, "若选择和棋、则游戏结束", "提示",MB_YESNO);
			if (ret_mouse == IDYES)
			{
				exit(0);
			}
			if (ret_mouse == IDNO)
			{
				int ret_m = MessageBox(NULL, "请继续游戏", "提示", MB_OK);
				if (ret_m == IDOK)
				{
					continue;
				}
			}
			

		}
		//获取离鼠标最近的点的坐标信息
		for (int i = 1; i < 20; i++) {  //19行
			for (int j = 1; j < 20; j++) { //19列
				if (abs(mouse.x - i * 25) < 12 && abs(mouse.y - j * 25) < 12) {    //小于12的原因是,25要取半的原因
					x = i * 25;
					y = j * 25;
					a = i;
					b = j;
					break;     //判断出一个坐标位置,就不用再去判断坐标的位置了
				}
			}
		}

		/*
		鼠标对象 m 是一个 MOUSEMSG 结构体对象,m对象(实例)下的 uMsg 成员是接收当前的
		鼠标信息,uMsg 是一个 unsigned int 型的(逐步去查看定义), WM_LBUTTONDOWN 是鼠标按下左键的消息
		*/
		if (mouse.uMsg == WM_LBUTTONDOWN) {
			//棋子重复下在一个位置上
			if (board[a][b] != 0) {  //初始化时0表示为没棋子,所以这是判断有无棋子在当前的坐标位置
				//MessageBox("此参数表示消息框拥有的窗口","消息框的内容","消息框的标题","消息框的“下一步”例如是和否按钮")
				//如过
				//MessageBox(NULL, "这里已经有棋子了哦,请重新选择呢。", "温馨提示",MB_YESNO);	//弹出一个提示框
				MessageBox(NULL, "此处已有棋子", "温馨提示", MB_OK | MB_ICONERROR);	//弹出一个提示框


				continue;	//进入下一循环 ,(再去接收鼠标的点击消息,再重新判断)
			}

			//判断黑白子
			if (flag % 2 == 0) {	//	偶数次为黑棋,因为 flag 初始值为0,所以黑棋先起步
				setfillcolor(BLACK);    //画圆填充颜色
				solidcircle(x, y, 10);  //出现黑图形
				board[a][b] = 1;
			}
			else {	//奇数次为白棋
				setfillcolor(WHITE);
				solidcircle(x, y, 10);
				board[a][b] = 2;
			}
			flag++;
		}

		if (judge_winlos(a, b)) {
			if (flag % 2 == 0) {
				MessageBox(NULL, "玩家2胜利。", "游戏结束", MB_OK);	//弹出一个提示框
				exit(0);

			}
			else {
				MessageBox(NULL, "玩家1胜利。", "游戏结束", MB_OK);	//弹出一个提示框 
				exit(0);
			}
		}
	}
}

//判断输赢
int five_chess::judge_winlos(int a, int b) {
	int i, j;
	int t = 2 - flag % 2;	//1 判断黑子是否赢	2 判断白子是否赢

	//横向判断同色棋子      //在 if 语句的判断中,为什么只向右判断?例如你在 (10,10)坐标中下了棋,然后判断,没有五个同色棋子,你又在(10,9)中下了棋,向右判断就行,这样你应该就懂了
	for (i = a - 4, j = b; i <= a; i++) {
		//i > 0 && i < 16 : 是因为行列都只有18个坐标,i到15时,左边最好情况还能加4个,跟15位置刚好五个同色棋子
		if (i > 0 && i < 16 && t == board[i][j] && t == board[i + 1][j] && t == board[i + 2][j] && t == board[i + 3][j] && t == board[i + 4][j]) {
			return 1;
		}
	}

	//纵向判断同色棋子
	for (i = a, j = b - 4; j <= b; j++) {
		if (j > 0 && j < 16 && t == board[i][j] && t == board[i][j + 1] && t == board[i][j + 2] && t == board[i][j + 3] && t == board[i][j + 4]) {
			return 1;
		}
	}

	//向右下判断同色棋子
	for (i = a - 4, j = b - 4; i <= a, j <= b; i++, j++) {
		if (i > 0 && i < 16 && j > 0 && j < 16 && t == board[i][j] && t == board[i + 1][j + 1] && t == board[i + 2][j + 2] && t == board[i + 3][j + 3] && t == board[i + 4][j + 4]) {
			return 1;
		}
	}

	//向左下判断同色棋子
	for (i = a - 4, j = b + 4; i <= a, j >= b; i++, j--) {
		if (i > 0 && i < 16 && j > 0 && j < 16 && t == board[i][j] && t == board[i + 1][j - 1] && t == board[i + 2][j - 2] && t == board[i + 3][j - 3] && t == board[i + 4][j - 4]) {
			return 1;
		}
	}

	return 0;
}
int main() {
	five_chess chess;
	chess.initGame();
	chess.playChess();
	system("pause");
	return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值