关于c++小游戏扫雷

c++小游戏扫雷

菜鸡献丑~
从数学的思想来看:
扫雷可以划分为几个阶段:
①、建立一个N×N的矩阵bool型矩阵W,其中W(m,n)=1代表(m,n)处有雷。随机在N²个位置中选取M个位置将W置1(M为雷的数量)。
②、定义一个N×N的矩阵bool型矩阵O,其中O(m,n)=1代表(m,n)还没有被翻开
③、计算周围雷的数目,将得到的数据存储在矩阵A中(矩阵A为int型,A的值为0-8)。
④、选取(m,n)点为所开始点。如果O(m,n)=0,表示已经翻开了,不能重复翻开如果O(m,n)=1,若(m,n)处W(m,n)=1,则选中了雷,游戏结束,直接到步骤⑥。如果O(m,n)=1且A(m,n)!=0,则把O(m,n)置为0,同时把W(m,n)在该处显示出来。如果O(m,n)=1且A(m,n)=0,表明此处是空白,周围没有雷,则要通过遍历周围的坐标处是否有数字,通过遍历实现点击一下有一大片空白的生成,同时把已经翻开的位置处的O矩阵置为0。
⑤、循环步骤④,直到游戏结束。游戏结束的条件为以下任一:选取的(m,n)处有雷把所有的没有雷的位置都翻开(矩阵O求和==M);
⑥、游戏结束。
以下为程序实现的某些截图。

在这里插入图片描述
在这里插入图片描述
此外还针对于图像化的显示做了部分优化,同时加入了开始场景和背景音乐以及特殊场景的音效控制等适配。
附上头文件代码

#include <time.h>
#include <string>
#ifndef MATRIX_H
#define MATRIX_H

#define NUM 10//定义N×N个格子
#define numBOOM 12//定义numBOOM为雷的总数
template<typename T>
class matrix
{
public:
	matrix(int num);
	void init(T w);
	void _rand();
	void show();
	T get(int x, int y)
	{
		return mat[x][y];
	}
	void set(int x, int y, T z)
	{
		mat[x][y] = z;
	}
private:
	int _num;
	T mat[NUM][NUM];
};

template<typename T>
matrix<typename T>::matrix(int num)
{
	_num = num;
}
template<typename T>
void matrix<typename T>::init(T w)
{
	for (int i1 = 0; i1 < NUM; i1++)
	{
		for (int i2 = 0; i2 < NUM; i2++)
		{
			mat[i1][i2] = w;
		}
	}
}
template<typename T>
void matrix<typename T>::_rand()
{
	int m, n;
	srand(int(time(0)));
	for (int i = 0; i < numBOOM;)//雷的总数为numBOOM;
	{
		m = rand() % NUM;
		n = rand() % NUM;
		if (!mat[m][n])
		{
			mat[m][n] = 1;
			i++;
		}
	}
}

template<typename T>
void matrix<typename T>::show()
{
	for (int i = 0; i < NUM; i++)
	{
		for (int j = 0; j < NUM; j++)
		{
		}
	}
}

#endif

附上主程序代码

#include <iostream>
#include <stdlib.h>
#include <cstdlib>
#include "matrix.h"
#include <graphics.h>
#include "stdio.h"
#include <windows.h>
#include <mmsystem.h>
#pragma comment (lib, "winmm.lib")  
#define SIZE 40//定义单张图片的大小
using namespace std;
IMAGE image[16];
MOUSEMSG msg;

//void init();
//void show(bool S[NUM][NUM]);
//void INIT();
int sum(matrix<bool> &mat_O);
int loop(int m, int n, matrix<bool> &mat_W, matrix<bool> &mat_O, matrix<int> &mat_A, matrix<char> &mat_S);
void loop2(int m, int n, matrix<bool> &mat_W, matrix<bool> &mat_O, matrix<int> &mat_A, matrix<char> &mat_S);
//void boom();

//bool W[NUM][NUM] = { 0 };//=1表示(m,n)处有雷;=0表示(m,n)处无雷;
//bool O[NUM][NUM] = { 1 };//=1表示(m,n)处未翻开;=0表示(m,n)处已经翻开;
//int A[NUM][NUM];//(m,n)周围雷的个数(0-8);
//bool _W[NUM + 2][NUM + 2];//W[][]周围加上一圈的0;
//int _A[NUM + 2][NUM + 2];//_W[][]的周围雷的个数;
//char S[NUM][NUM];//显示,用“*”或者A(m,n)显示;

void main()
{
	//PlaySound(L"music.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
	//mciSendString(L"open qiyueshang.wav alias aa", NULL, 0, NULL);//alias后面为设备名称,
	//mciSendString(L"play aa wait", NULL, 0, NULL);//wait表示播放完毕之后才返回,最好加上去{该语句会一直执行,不会执行后面的代码,故不用}
	//mciSendString(L"close aa", NULL, 0, NULL);
	//system("mode con cols=34 lines=20");//改变窗口宽高
	//system("color 5E");//改变窗口文字颜色
	initgraph(NUM*SIZE, (NUM+1)*SIZE);
	loadimage(&image[0], L"image\\0.jpg", SIZE, SIZE);//此处用来读取文件所在的位置时候只能用\\,不能用其他的;
	loadimage(&image[1], L"image\\1.jpg", SIZE, SIZE);
	loadimage(&image[2], L"image\\2.jpg", SIZE, SIZE);
	loadimage(&image[3], L"image\\3.jpg", SIZE, SIZE);
	loadimage(&image[4], L"image\\4.jpg", SIZE, SIZE);
	loadimage(&image[5], L"image\\5.jpg", SIZE, SIZE);
	loadimage(&image[6], L"image\\6.jpg", SIZE, SIZE);
	loadimage(&image[7], L"image\\7.jpg", SIZE, SIZE);
	loadimage(&image[8], L"image\\8.jpg", SIZE, SIZE);
	loadimage(&image[9], L"image\\init.jpg", SIZE, SIZE);
	loadimage(&image[10], L"image\\lei.jpg", SIZE, SIZE);
	loadimage(&image[11], L"image\\tag.jpg", SIZE, SIZE);
	loadimage(&image[12], L"image\\success2.jpg", SIZE*NUM*5/5, SIZE*NUM*5/5);//牛逼图片
	loadimage(&image[13], L"image\\failure.jpg", SIZE*NUM*5/5, SIZE*NUM*5/5);//垃圾图片
	loadimage(&image[14], L"image\\start.jpg", SIZE*NUM, SIZE*(NUM+1));//开始图片
	loadimage(&image[15], L"image\\head.jpg", SIZE*NUM, SIZE);//head文件,用以展示
	
	putimage(0, 0,&image[14]);
	int flag_start = 1;
	while (flag_start)
	{
		int X, Y;
		msg = GetMouseMsg();
		X = msg.x / SIZE;
		Y = msg.y / SIZE;
		switch (msg.uMsg)
		{
			case WM_LBUTTONDOWN:
				if (X >= (NUM *4/ 10) && X <= (NUM *6/ 10) && Y >= NUM* 8 / 10 && Y <= NUM*9 / 10)
				{   
						flag_start = 0;
				}
		}
	}
	PlaySound(L"music.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//进入开始界面后开始播放音乐
	putimage(0, 0, &image[15]);
	for (int i = 0; i < NUM; i++)//初始化界面
	{
		for (int j = 1; j < NUM+1; j++)
		{
			putimage(SIZE * i, SIZE * j, &image[9]);
		}
	}
	//_getch();
	//return 0;
	//Sleep(5000);
	matrix<bool> mat_F(NUM);//Flag矩阵
	mat_F.init(0);
	matrix<bool> mat_W(NUM);//W[][]矩阵
	mat_W.init(0);
	mat_W._rand();
	//mat_W.show();//输出炸弹矩阵();
	matrix<bool> mat_O(NUM);//O[][]矩阵
	mat_O.init(1);
	//mat_O.show();
	matrix<char> mat_S(NUM);//S[][]矩阵
	mat_S.init('*');
	//mat_S.show();
	matrix<int> mat_A(NUM);//A[][]矩阵
	//mat_O.show();
	int _W[NUM + 2][NUM + 2];//扩展后的W[12][12]
	int _A[NUM + 2][NUM + 2];
	for (int i1 = 0; i1 < NUM + 2; i1++)
	{
		for (int i2 = 0; i2 < NUM + 2; i2++)
		{
			_W[i1][i2] = 0;
		}
	}
	for (int i1 = 1; i1 < NUM + 1; i1++)
	{
		for (int i2 = 1; i2 < NUM + 1; i2++)
		{
			_W[i1][i2] = mat_W.get(i1 - 1, i2 - 1);
		}
	}
	for (int i1 = 1; i1 < NUM + 1; i1++)
	{
		for (int i2 = 1; i2 < NUM + 1; i2++)
		{
			_A[i1][i2] = _W[i1 - 1][i2 - 1] + _W[i1 - 1][i2] + _W[i1 - 1][i2 + 1] + _W[i1][i2 - 1] + _W[i1][i2 + 1] + _W[i1 + 1][i2 - 1] + _W[i1 + 1][i2] + _W[i1 + 1][i2 + 1];
			mat_A.set(i1 - 1, i2 - 1, _A[i1][i2]);
		}
	}
	//int m, n;
	int X = 0, Y = 0;
	int sum = 100;
	while (sum != numBOOM)
	{
		while (MouseHit())
		{
			msg = GetMouseMsg();
			X = msg.x / SIZE;
			Y = msg.y / SIZE - 1;
			if (X >= 0 && Y >= 0)
			{
				switch (msg.uMsg)
				{
				case WM_LBUTTONDOWN:
					//X = msg.x / 50;
					//Y = msg.y / 50;
					sum = loop(X, Y, mat_W, mat_O, mat_A, mat_S);
					if (sum == -1)
					{
						//cout << "完蛋玩意儿,BOOM!!!" << endl;

						for (int i1 = 0; i1 < NUM; i1++)//循环输出雷的位置
						{
							for (int i2 = 0; i2 < NUM; i2++)
							{
								if (mat_W.get(i1, i2))
								{
									putimage(i1 * SIZE, (i2+1) * SIZE, &image[10]);
								}
							}
						}
						PlaySound(L"boom.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//播放炸弹被翻开的音效
						Sleep(2000);//2000ms时间展示雷的位置
						PlaySound(NULL, NULL, SND_FILENAME);//停止播放背景音乐
						putimage(NUM*SIZE * 0 / 10, SIZE, &image[13]);//输出垃圾图片
						PlaySound(L"heihei.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//输出白痴笑声
						Sleep(3000);//延时3000ms关闭
						PlaySound(NULL, NULL, SND_FILENAME);
						system("pause");
					}
					continue;
				case WM_RBUTTONDOWN:
					if (mat_O.get(X, Y))
					{
						if (!mat_F.get(X, Y))
						{
							putimage(X * SIZE, (Y+1) * SIZE, &image[11]);
							mat_F.set(X, Y, 1);
						}
						else
						{
							putimage(X * SIZE, (Y+1) * SIZE, &image[9]);
							mat_F.set(X, Y, 0);
						}
					}
				}
			}
		}
	}
	if (sum == numBOOM)
	{
		Sleep(1000);
		putimage(NUM*SIZE*0/10,SIZE,&image[12]);//牛逼,输出牛逼图片
		PlaySound(L"applause.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
		Sleep(4000);
		PlaySound(NULL, NULL, SND_FILENAME);
		system("pause");
	}
}

int loop(int m, int n, matrix<bool> &mat_W, matrix<bool> &mat_O, matrix<int> &mat_A, matrix<char> &mat_S)
{
	int flag = 0;//作为选中炸弹的标志;
	if (!mat_O.get(m, n))//如果翻开的话重新选择,没翻开的话进入判断
	{
		//cout << "请重新选择:" << endl;
		return 0;
	}
	else
	{
		if (mat_W.get(m, n))//有雷的话就爆炸
		{
			//boom();
			//cout << "恭喜您,您选中了炸弹!!" << endl;
			putimage(SIZE*m, SIZE*(n + 1), &image[10]);
			return -1;

		}
		else if (mat_A.get(m, n))//如果(m,n)处有数字,周围有雷
		{
			mat_O.set(m, n, 0);
			int temp = mat_A.get(m, n);
			putimage(SIZE * m, SIZE * (n + 1), &image[temp]);
			//mat_S.set(m, n, temp + '0');
			//mat_S.show();
		}
		else//(m,n)处为空白,即mat_A(m,n)=0;
		{
			putimage(SIZE*m, SIZE * (n + 1), &image[0]);
			loop2(m, n, mat_W, mat_O, mat_A, mat_S);
			//mat_S.show();
		}
	}
	//cout << "-------------------------------" << endl;
	//cout << "①②③④⑤⑥⑦⑧⑨⑩" << endl;
	//cout << "end" << endl;
	//mat_S.show();
	return sum(mat_O);
}
void loop2(int m, int n, matrix<bool> &mat_W, matrix<bool> &mat_O, matrix<int> &mat_A, matrix<char> &mat_S)
{
	int temp = mat_A.get(m, n);
	//mat_S.set(m, n, temp + '0');
	mat_O.set(m, n, 0);
	if (m > 0 && mat_O.get(m - 1, n))
	{
		if (mat_A.get(m - 1, n))
		{
			putimage(SIZE * (m - 1), SIZE * (n + 1), &image[mat_A.get(m - 1, n)]);
			mat_S.set(m - 1, n, mat_A.get(m - 1, n) + '0');
			mat_O.set(m - 1, n, 0);
		}
		else
		{
			putimage(SIZE * (m - 1), SIZE * (n + 1), &image[0]);
			loop2(m - 1, n, mat_W, mat_O, mat_A, mat_S);
		}
	}
	if (m < (NUM -1) && mat_O.get(m + 1, n))
	{
		if (mat_A.get(m + 1, n))
		{
			putimage(SIZE * (m + 1), SIZE * (n + 1), &image[mat_A.get(m + 1, n)]);
			mat_S.set(m + 1, n, mat_A.get(m + 1, n) + '0');
			mat_O.set(m + 1, n, 0);
		}
		else
		{
			putimage(SIZE * (m + 1), SIZE * (n + 1), &image[0]);
			loop2(m + 1, n, mat_W, mat_O, mat_A, mat_S);
		} 
	}
	if (n > 0 && mat_O.get(m, n - 1))
	{
		if (mat_A.get(m, n - 1))
		{
			putimage(SIZE * m, SIZE * n, &image[mat_A.get(m, n - 1)]);
			mat_S.set(m, n - 1, mat_A.get(m, n - 1) + '0');
			mat_O.set(m, n - 1, 0);
		}
		else
		{
			putimage(SIZE * m, SIZE * n , &image[0]);
			loop2(m, n - 1, mat_W, mat_O, mat_A, mat_S);
		}
	}
	if (n < (NUM - 1) && mat_O.get(m, n + 1))
	{
		if (mat_A.get(m, n + 1))
		{
			putimage(SIZE * m, SIZE * (n + 2), &image[mat_A.get(m, n + 1)]);
			mat_S.set(m, n + 1, mat_A.get(m, n + 1) + '0');
			mat_O.set(m, n + 1, 0);
		}
		else
		{
			putimage(SIZE * m, SIZE * (n + 2), &image[0]);
			loop2(m, n + 1, mat_W, mat_O, mat_A, mat_S);
		}
	}
}
int sum(matrix<bool> &mat_O)
{
	int sum = 0;
	for (int i = 0; i < NUM; i++)
	{
		for (int j = 0; j < NUM; j++)
		{
			sum += mat_O.get(i, j);
		}
	}
	return sum;
}

由于时间仓促,部分代码没有注释,可以按照最前面的思路去推一遍,对自己的帮助会很大,如有不太懂的代码可以自行百度,或者回复,我会给你解答。

源代码去我上传的资源里面找。

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值