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;
}
由于时间仓促,部分代码没有注释,可以按照最前面的思路去推一遍,对自己的帮助会很大,如有不太懂的代码可以自行百度,或者回复,我会给你解答。
源代码去我上传的资源里面找。