【小游戏】用C++结合EasyX制作扫雷1

开头

这个程序使用了EasyX图形库,简单易用,可以画出丰富的图形和文字。

EasyX官网

可以看这篇文章入门:EasyX基础入门——这一篇就够啦_绿駬的博客-CSDN博客

官网有下载链接和文档,我使用的是VC++编译器,环境是Visual Studio 2022,注意在项目设置中把Unicode字符集改为多字节字符集

6760182ef8c44527b34d374b75d87ec0.png

 da65df3a10124c13bfdcdf0a392cc0a3.png

步骤

  1. 准备好图像文件,不同状态的格子我们就不自己画了(结尾提供)
  2. 引用头文件(graphics.h)
  3. 准备好全局变量(单个格子大小(单位:像素),雷数常量,格子布局长宽(单位:格子),窗口宽度,窗口高度)
  4. 定义一个格子对象
  5. [主函数]加载图像
  6. [主函数]初始化雷盘(layout二维数组)并随机布雷
  7. [主函数]死循环监测鼠标操作
  8. [主函数][死循环]监测点击到的格子,获取周围格子数并显示,判断输赢

代码

main.cpp文件所有代码

#include<graphics.h>
#include<iostream>

using namespace std;
//全局变量
MOUSEMSG msg;//全局鼠标信息变量
IMAGE mine, grid, grid_motion, grid_down, flag, flag_motion , mine_other;//所有图像变量
//单个格子大小(单位:像素),雷数常量,格子布局长宽(单位:格子),窗口宽度,窗口高度
const int grid_size = 40, layout_size=10, width = layout_size * grid_size, height = layout_size * grid_size;

int all_num = 0, grid_x = 0, grid_y = 0, mines_num = 10;

//格子类,边长为40像素的正方形
class Grid {
public:
	bool is_mine, is_click = false, is_flag = false;
	int num = 0;
	IMAGE mine;
	int x1, x2, y1, y2;//格子的四个角顶点的位置
	int i, j;
	int grids[8][2] = { 0 };

	void init(bool is_mine, int x, int y, int i, int j) {
		//初始化
		this->is_mine = is_mine;
		x1 = x; x2 = x + grid_size;
		y1 = y; y2 = y + grid_size;
		this->i = i; this->j = j;
		//绘制
		change(grid);
		//判断自己的位置(grids二维数组记录周围8个格子的行和列)
		if (i == 0 && j == 0)
		{
			//左上角
			int grids[3][2] = { {0,1},{1,0},{1,1}};
			for (int a = 0; a < 3; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}

		else if (i == layout_size - 1 && j == layout_size - 1)
		{
			//右下角
			int grids[3][2] = { {layout_size - 1,layout_size - 2},{layout_size - 2,layout_size - 1},{layout_size - 2,layout_size - 2}};
			for (int a = 0; a < 3; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}

		else if (i == 0 && j == layout_size - 1)
		{
			//右上角
			int grids[3][2] = { {0,layout_size - 2},{1,layout_size - 1},{1,layout_size - 2}};
			for (int a = 0; a < 3; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}

		else if (i == layout_size - 1 && j == 0){
			//左下角
			int grids[3][2] = { {layout_size - 1,layout_size - 2},{layout_size - 2,layout_size - 2},{layout_size-2,layout_size-1} };
			for (int a = 0; a < 3; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}
			
		else if (i == 0 && j > 0 && j < layout_size - 1) 
		{
			//上-边
			int grids[8][2] = { {0,j - 1},{0,j + 1},{1,j - 1},{1,j},{1,j + 1},{2,j - 1},{2,j},{2,j + 1} };
			for (int a = 0; a < 8; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}

		else if (i == layout_size - 1 && j > 0 && j < layout_size - 1) 
		{
			//下-边
			int grids[8][2] = { {layout_size - 1,j - 1},{layout_size - 1,j + 1} ,{layout_size - 2,j - 1} ,{layout_size - 2,j} ,{layout_size - 2,j + 1} ,{layout_size - 3,j - 1} ,{layout_size - 3,j} ,{layout_size - 3,j + 1} };
			for (int a = 0; a < 8; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}
			
		else if (j == 0 && i > 0 && i < layout_size - 1) 
		{
			//左-边
			int grids[8][2] = { {i - 1,0} ,{i - 1,1} ,{i - 1,2} ,{i,1} ,{i,2} ,{i + 1,0} ,{i + 1,1} ,{i + 1,2} };
			for (int a = 0; a < 8; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}

		else if (j == layout_size - 1 && i > 0 && i < layout_size - 1) 
		{
			//右-边
			int grids[8][2] = { {i - 1,layout_size - 1} ,{i - 1,layout_size - 2} ,{i - 1,layout_size - 3} ,{i,layout_size - 2} ,{i,layout_size - 3} ,{i + 1,layout_size - 1} ,{i + 1,layout_size - 2} ,{i + 1,layout_size - 3} };
			for (int a = 0; a < 8; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}

		else
		{
			//以此格子为中心
			int grids[8][2] = { {i - 1,j - 1} ,{i - 1,j} ,{i - 1,j + 1} ,{i,j - 1} ,{i,j + 1} ,{i + 1,j - 1} ,{i + 1,j} ,{i + 1,j + 1} };
			for (int a = 0; a < 8; a++) {
				this->grids[a][0] = grids[a][0];
				this->grids[a][1] = grids[a][1];
			}
		}
	}

	void change(IMAGE image) {
		putimage(x1, y1, &image);
	}

	void show_num() {
		if (num == 0)
			return;
		else if (num == 1)
			settextcolor(BLUE);
		else if (num == 2)
			settextcolor(GREEN);
		else if (num == 3)
			settextcolor(YELLOW);
		else if (num == 4)
			settextcolor(RGB(255, 135, 35));
		else
			settextcolor(RED);
		setbkmode(TRANSPARENT);
		settextstyle(45, 0, _T("Consolas"));
		char info = num + 48;
		outtextxy(x1 + 6, y1 - 3, _T(info));
	}

	void find_0(Grid(&layout)[layout_size][layout_size]) {
		for (int a = 0; a < 8; a++) {//遍历grids(周围格子)
			int i = grids[a][0], j = grids[a][1];
			if (layout[i][j].num == 0 && layout[i][j].is_click == false && layout[i][j].is_mine == false) {
				//模拟点击操作
				layout[i][j].is_flag = false;
				layout[i][j].change(grid_down);
				layout[i][j].is_click = true;
				all_num++;
				layout[i][j].find_0(layout);
			}
		}
	}
};

int main() {
	//程序初始化
	initgraph(width, height);
	setbkcolor(WHITE);
	cleardevice();
	//加载图像
	loadimage(&mine, "images/mine.png", grid_size, grid_size);
	loadimage(&grid, "images/grid.png", grid_size, grid_size);
	loadimage(&grid_motion, "images/grid_motion.png", grid_size, grid_size);
	loadimage(&grid_down, "images/grid_down.png", grid_size, grid_size);
	loadimage(&flag, "images/flag.png", grid_size, grid_size);
	loadimage(&flag_motion, "images/flag_motion.png", grid_size, grid_size);
	loadimage(&mine_other, "images/mine_other.png", grid_size, grid_size);
	//布雷
	Grid layout[width / grid_size][height / grid_size];//布局,用二维数组,如果是1就有雷,0则没有

	srand(time(nullptr));
	//初始化
	for (int i = 0; i < layout_size; i++) {
		for (int j = 0; j < layout_size; j++) {
			layout[i][j].init(false, grid_x, grid_y, i, j);
			grid_x += 40;
		}
		grid_y += 40;
		grid_x = 0;
	}
	//随机布雷实现
	int x = 0, y = 0, count = 0;
	for (count = 0; count < mines_num;){
		x = 1 + rand() % layout_size-1;
		y = 1 + rand() % layout_size-1;
		if (layout[x][y].is_mine == false){
			layout[x][y].is_mine = true;
			count++;//每次布置好一个雷之后,才会计数
		}
	}

	for (int i = 0; i < layout_size; i++) {
		for (int j = 0; j < layout_size; j++) {
			//每个格子获取周围格子的雷数
			for (int a = 0; a < 8; a++) {
				if (layout[layout[i][j].grids[a][0]][layout[i][j].grids[a][1]].is_mine) {
					layout[i][j].num++;
				}
			}
		}
	}
	/*调试输出布局*/
	for (int i = 0; i < layout_size; i++) {
		for (int j = 0; j < layout_size; j++) {
			cout << layout[i][j].is_mine << ' ';
		}
		cout << endl;
	}
	//轮询监测鼠标事件
	while (true) {
		//监测鼠标操作
		ExMessage msg = getmessage(EX_MOUSE);

		if (msg.message == WM_LBUTTONDOWN) {
			for (int i = 0; i < layout_size; i++) {
				for (int j = 0; j < layout_size; j++) {
					//通过点击坐标判断是哪个格子
					if (msg.x >= layout[i][j].x1 && msg.x <= layout[i][j].x2 && msg.y >= layout[i][j].y1 && msg.y <= layout[i][j].y2) {
						if (layout[i][j].is_click == false) {//判断是否被点击过
							layout[i][j].is_flag = false;
							//如果这个格子是雷
							if (layout[i][j].is_mine) {
								layout[i][j].change(mine);
								//显示提示信息
								for (int x = 0; x < layout_size; x++) {
									for (int y = 0; y < layout_size; y++) {
										if (layout[x][y].is_mine && x != i && y != j)
											layout[x][y].change(mine_other);
									}
								}
								cout << "踩雷!即将退出";
								Sleep(2500); //停顿两秒半
								//退出程序
								return 0;
							}

							else {
								layout[i][j].change(grid_down);
								//显示格子周围的雷数
								layout[i][j].show_num();
								//如果是数量是0
								if (layout[i][j].num == 0)
									layout[i][j].find_0(layout);
							}
							layout[i][j].is_click = true;
							all_num++;
						}
						//判断未点开的格子数,从而判断输赢
						if (all_num == layout_size * layout_size - mines_num) {
							//显示提示信息
							for (int x = 0; x < layout_size; x++) {
								for (int y = 0; y < layout_size; y++) {
									if (layout[x][y].is_mine && x != i && y != j)
										layout[x][y].change(flag);
								}
							}
							cout<<"获胜!即将退出";
							Sleep(2500); //停顿两秒半
							//退出
							return 0;
						}
					}
				}
			}
		}

		if (msg.message == WM_MOUSEMOVE) {
			for (int i = 0; i < layout_size; i++) {
				for (int j = 0; j < layout_size; j++) {
					//通过坐标判断是哪个格子
					if (msg.x >= layout[i][j].x1 && msg.x <= layout[i][j].x2 && msg.y >= layout[i][j].y1 && msg.y <= layout[i][j].y2) {
						if (layout[i][j].is_click) {
							layout[i][j].change(grid_down);
							layout[i][j].show_num();
						}
						else if (layout[i][j].is_click == false && layout[i][j].is_flag == false)
							layout[i][j].change(grid_motion);
						else if (layout[i][j].is_click == false && layout[i][j].is_flag == true)
							layout[i][j].change(flag_motion);
					}

					else {
						if (layout[i][j].is_click) {
							layout[i][j].change(grid_down);
							layout[i][j].show_num();
						}
						else if (layout[i][j].is_click == false && layout[i][j].is_flag == false)
							layout[i][j].change(grid);
						else if (layout[i][j].is_click == false && layout[i][j].is_flag)
							layout[i][j].change(flag);
					}

				}
			}
		}

		else if (msg.message == WM_RBUTTONDOWN) {
			for (int i = 0; i < layout_size; i++) {
				for (int j = 0; j < layout_size; j++) {
					//通过点击坐标判断是哪个格子
					if (msg.x >= layout[i][j].x1 && msg.x <= layout[i][j].x2 && msg.y >= layout[i][j].y1 && msg.y <= layout[i][j].y2) {
						//如果已经被标记就取消标记
						if (layout[i][j].is_flag) {
							layout[i][j].is_flag = false;
							layout[i][j].change(grid);
						}
						//如果没有被标记就标记上
						else if (layout[i][j].is_flag == false && layout[i][j].is_click == false) {
							layout[i][j].is_flag = true;
							layout[i][j].change(flag);
						}
					}
				}
			}
		}
	}

	closegraph();
	return 0;
}

结尾

已开源到了GitHub(包含图片文件):LightByteCode/MineSweeper (github.com)

扫描二维码关注公众号,回复: 16521261 查看本文章

猜你喜欢

转载自blog.csdn.net/m0_61316509/article/details/128730461