扫雷游戏(图形界面)C语言小游戏

摆脱黑窗口,我们用easyX图形库做一个我们小时经常玩的扫雷小游戏。在做出来时你会发现,做一个小游戏原来如此简单,最会还有如何打包的教程,打包之后,可以发给朋友玩玩哦,在炫耀技术的同时可以回味一下童年乐趣。

使用了easyX的图形库进行开发的小游戏,不会的可以去看我的easyX图行库学习的文章,很容易上手的,简单看一下就可以写这个程序的,里面用到的图片我都放到资源里面了,直接私信我要也可以      eaxyX图形库学习https://blog.csdn.net/qq_52661581/article/details/125124212?spm=1001.2014.3001.5502

目录

一、包含头文件

二、全局变量

三、游戏初始化

四、绘图渲染游戏

五、自动解密0周围的格子(使用递归)

六、鼠标消息

七、判断成功/失败

八、主函数

 九、运行成功

 十、打包游戏


一、包含头文件

#include <stdio.h>   
#include <stdlib.h>  //使用随机函数rank()
#include <time.h>    //使用time()
#include <graphics.h>   //使用图行库
#pragma comment(lib,"winmm.lib")   //播放音乐

二、全局变量

#define ROW 12 //行 (可以更改)
#define COL 12 //列 (可以更改)
#define NUM 12 //雷的数量 (可以更改)
#define SIZE 50 //图片大小 (可以自己更改)
#define MAX  1  //容错率(即踩到的雷最多的数量)

bool FLAG; //用来表示是否退出
int map[ROW][COL]; //用来存放所有元素
int count; //用来判断所有格子是否都点完
int count_L ; //踩到雷的个数
IMAGE img[12];  //用来放所有图片

三、游戏初始化

//游戏初始化
void GameInit()
{
	//随机数种子(使每次布雷的位置不同)
	srand((unsigned int)time(NULL));

	//播放音乐
	mciSendString("open ./BGM.mp3 alias BGM", 0, 0, 0);
	mciSendString("play BGM repeat", 0, 0, 0);

	FLAG = TRUE;  //表示开始
	count = 0; //刚开始点了0个格子
	count_L = 0; //点出雷的个数
    //创建窗口
	initgraph(ROW * SIZE, COL * SIZE); 

	/*图片 0:背景
	1-9:数字1-8
	10:标记
	11:雷      */
	loadimage(&img[0], "./tp/back.png", SIZE, SIZE); 
	loadimage(&img[1], "./tp/0.png", SIZE, SIZE); 
	loadimage(&img[2], "./tp/1.png", SIZE, SIZE);
	loadimage(&img[3], "./tp/2.png", SIZE, SIZE);
	loadimage(&img[4], "./tp/3.png", SIZE, SIZE);
	loadimage(&img[5], "./tp/4.png", SIZE, SIZE);
	loadimage(&img[6], "./tp/5.png", SIZE, SIZE);
	loadimage(&img[7], "./tp/6.png", SIZE, SIZE);
	loadimage(&img[8], "./tp/7.png", SIZE, SIZE);
	loadimage(&img[9], "./tp/8.png", SIZE, SIZE);
	loadimage(&img[10], "./tp/a.png", SIZE, SIZE);  
	loadimage(&img[11], "./tp/err.png", SIZE, SIZE);

    //所有元素都赋值为0
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			map[i][j] = 0;
		}
	}

	//布雷用-1表示 NUM个雷
	int n = 0;
	while (n < NUM)
	{
		int r = rand() % ROW;
		int c = rand() % COL;

		if (map[r][c] == 0)
		{
			map[r][c] = -1;
			n++;
		}
	}

	//数字提示(该格周围雷的数量) 如果雷周围的八个格不是雷则加一
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (map[i][j] == -1)
			{
				for (int m = i - 1; m <= i + 1; m++)
				{
					for (int n = j - 1; n <= j + 1; n++)
					{
						if ( m >= 0 && n >= 0 && m<ROW && n<COL && map[m][n] != -1)
						{
							map[m][n]++;
						}
					}
				}
			}
		}
	}

	//刚开始所有全部加密
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			map[i][j] += 20;
		}
	}
}

四、绘图渲染游戏

//使用图片绘制游戏
void GameDraw()
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (map[i][j] == -1) //雷
			{
				putimage(i * SIZE, j * SIZE,  &img[11]);
			}
			else if (map[i][j] >= 0 && map[i][j] <= 8) //数字
			{
				putimage(i * SIZE, j * SIZE, &img[map[i][j] + 1]);
			}
			else if (map[i][j] >= 19 && map[i][j] <= 28)  //背景图片
			{
				putimage(i * SIZE, j * SIZE, &img[0]); 
			}
			else
			{
				putimage(i * SIZE, j * SIZE, &img[10]);  //标记图片
			}
		}

	}
}

五、自动解密0周围的格子(使用递归)

//打开0 使用递归
void openZero(int i, int j)
{
	for (int m = i - 1; m <= i + 1; m++)
	{
		for (int n = j - 1; n <= j + 1; n++)
		{
			if (m >= 0 && n >= 0 && m < ROW && n < COL)
			{
				if (map[m][n] > 19 && map[m][n] <= 28)  //空白的
				{
					if (map[m][n] != 20) //不是0
					{
						map[m][n] -= 20; //解密
						count++;  //每打开一个都要加一
					}
					else    //如果还是0,则再次调用
					{
						map[m][n] -= 20; //解密
						count++;   //每打开一个都要加一
						openZero(m, n);
					}
				}
			}
		}
	}
}

六、鼠标消息

//鼠标消息(在easyX中不会的话可以去看看)
void Mouse()
{
	MOUSEMSG msg; //用来接收鼠标消息

	if (MouseHit()) //当鼠标点击的时候
	{
		msg = GetMouseMsg(); //接受鼠标消息
		if (msg.uMsg == WM_LBUTTONDOWN)  //鼠标左键按下
		{
			if (map[msg.x / SIZE][msg.y / SIZE] >= 19 ) //防止减多次变成雷
			{
				map[msg.x / SIZE][msg.y / SIZE] -= 20;  //解密

				if (map[msg.x / SIZE][msg.y / SIZE] >= -1 
                            && map[msg.x / SIZE][msg.y / SIZE] <= 8)
				{
                    if (map[msg.x / SIZE][msg.y / SIZE] == -1) //雷
			    	{
					    count_L++; //踩雷数量
			    	}
					if (map[msg.x / SIZE][msg.y / SIZE] == 0)
					{
						openZero(msg.x / SIZE, msg.y / SIZE);
					}
					count++;    //每次解密都要+1
				}
			}
		}
		else if (msg.uMsg == WM_RBUTTONDOWN) //鼠标右键按下
		{
			if(map[msg.x / SIZE][msg.y / SIZE] >= 19 
                    && map[msg.x / SIZE][msg.y / SIZE] <30)
			map[msg.x / SIZE ][msg.y / SIZE ] += 20; //标记小红旗
		}
		
	}
}

七、判断成功/失败

//判断是否胜利/失败 (窗口句柄在easyX中有讲不会可以看看)
void isVictory()
{
	HWND hw = GetHWnd();  //获得窗口句柄
	SetWindowText(hw, "如你所愿的扫雷"); //窗口标题
	if (count_L > MAX)  //如果踩雷数大于容错率,游戏失败
	{
		if (MessageBox(hw, "low 你输了", "sao雷", MB_OK) == IDOK) //弹出消息框
		{
			if (MessageBox(hw, "low 还想再来一把吗", "sao雷", MB_YESNO) == IDYES)
			{
				GameInit();  //再次初始化,开始游戏
			}
			else
			{
				count_L = 0;   //踩雷数量
				closegraph(); //关闭窗口
				FLAG = 0;  //退出程序
			}
		}
	}
	if (count == (ROW * COL - NUM + count_L)) //所有格数都解密了
	{
		if (MessageBox(hw, "牛子 胜利了!", "sao雷", MB_OK) == IDOK)  //弹出消息框
		{
			if (MessageBox(hw, "牛子 还想再来一把吗", "sao雷", MB_YESNO) == IDYES)
			{
				GameInit();  //再次初始化,开始游戏
			}
			else
			{
				count = 0;    //解密的格数清零
				closegraph(); //关闭窗口
				FLAG = 0;    //退出程序
			}
		}
	}
}

八、主函数

int main()
{
	GameInit();
	GameDraw();
	while (FLAG)
	{
		Mouse();
		GameDraw();
		isVictory();
	}
	return 0;
}

 九、运行成功

 

 十、打包游戏

1 新建打包项目

 

 下一步  给项目起名  点击创建

因为我把图片素材放在tp文件夹下,所以需要添加一个子目录

 把这个文件夹下的图片添加进来

 我的音乐在当前目录下所以直接在当前目录下添加就行

 之后在右击 项目输出 主输出

 

 在创建快捷方式

 把创建好的快捷方式放到桌面文件夹下

 右击项目 点击生成即可

 查看输出 这里就可以看到生成安装文件的位置 或者直接在刚刚项目创建的地方找

 安装或者给好友发送下面这个即可

tip:我把需要的素材放在资源里面了哦

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小菜菜~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值