首先我们整理一下扫雷的思路:
1.创建菜单
2.构造初始雷区
3.埋雷
4.找雷
5.game函数整合
创建菜单
构造雷区
雷区内容由两个二维数组存储,show数组展现的是雷区表面,而mine数组则是雷的具体位置。
我们要实现的是9*9的雷区,但是为了防止在接下来的查看周边雷数时导致越界,我们我们行列都要+2。
我们需要初始化两个数组,show数组内容初始化为*,而mine数组则初始化为0,表示无雷。
初始化函数:
因为两个数组初始化内容不同,所以用形参x表示要初始化的内容。
下面则要将雷区打印,也就是打印show数组的内容:
下面展示一下效果:
至此,构造雷区结束。
埋雷
如何埋雷呢?这里我们采用随机数方式埋雷。
找雷
我们在进行找雷的过程中,会遇到以下几种情况:
1.找到雷,被雷炸死。
2.没找到雷,要显示你当前位置周边雷数,这里又要分情况:
当前位置周边没有雷,那么就要展开周边位置。
当前位置周边有雷,只展开当前位置。
首先我们要实现查找周边雷数:
接着实现递归展开:
这里要小心数组越界,还有递归无止境!这是因为考虑导致的。
越界,要终止递归。雷的存储位置是1-9!
元素被递归过就不要递归!
周围有雷要停止递归展开。周边无雷向周围展开。
接着我们开始找雷:
找到的是雷,被炸死,终止游戏。死了展现雷区内容,死而瞑目。
找到的不是雷,展开位置,继续找雷。
game函数整合:
完整代码
扫雷.h
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define mines 10//雷数
void menu();//菜单
void Init(char a[ROWS][COLS], int row,int col,char x);//初始化
void Display(char a[ROWS][COLS], int row, int col);//打印
void _mine(char a[ROWS][COLS], int row, int col);//埋雷
int getminesize(char a[ROWS][COLS], int row, int col);//周边雷数
void findmine(char a[ROWS][COLS], char show[ROWS][COLS], int row, int col);//找雷
void game();//游戏
void boom_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* count);
扫雷.c
#include"扫雷.h"
void menu()//菜单
{
printf("----------------------------------------\n");
printf("---------1.play 0.exit--------\n");
printf("----------------------------------------\n");
}
//初始化
void Init(char a[ROWS][COLS], int rows, int cols, char x)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
a[i][j] = x;//将数组所有内容初始化为字符x
}
}
}
void Display(char a[ROWS][COLS], int row, int col) //打印雷区
{
for (int i = 0; i <= col; i++)
{
printf("---");
}
printf("\n");
for (int i = 0; i <= row; i++)
{
printf("%2d|", i);
}
printf("\n");
for (int i = 0; i <= col; i++)
{
printf("---");
}
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%2d|", i);
for (int j = 1; j <= col; j++)
{
printf("%2c|", a[i][j]);
}
printf("\n");
for (int i = 0; i <= col; i++)
{
printf("---");
}
printf("\n");
}
}
void _mine(char a[ROWS][COLS], int row, int col)
{
srand((size_t)time(0));
int x = 0, y = 0;
int count = mines;//mines表示雷数
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (a[x][y] == '0')
{
a[x][y] = '1';
count--;
}
}
}
int getminesize(char mine[ROWS][COLS], int x, int y)//周围雷数
{
return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] +
mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] +
mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0');
}
//无雷区成片展开
void boom_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* count)
{
if (x == 0 || x == ROW + 1 || y == 0 || y == COL + 1)//越界
{
return;
}
if (show[x][y] != '*')//元素递归过
{
return;
}
int minesize = getminesize(mine, x, y);
if (minesize)//有雷
{
show[x][y] = minesize + '0';
(*count)--;
return;
}
else//无雷
{
show[x][y] = ' ';
(*count)--;
boom_mine(mine, show, x, y-1, count);
boom_mine(mine, show, x, y+1, count);
boom_mine(mine, show, x-1, y, count);
boom_mine(mine, show, x-1, y+1, count);
boom_mine(mine, show, x-1, y-1, count);
boom_mine(mine, show, x+1, y, count);
boom_mine(mine, show, x+1, y-1, count);
boom_mine(mine, show, x+1, y+1, count);
}
}
void findmine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
int x = 0, y = 0;
int counts = row * col;
while (counts>mines)
{
printf("请输入坐标:");
scanf_s("%d %d", &x, &y);
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
Display(mine, row, col);//死而瞑目
break;
}
else
{
if (show[x][y] == '*')
{
boom_mine(mine, show, x, y, &counts);//递归展开
Display(show, row, col);
}
else
{
printf("请重新输入:\n");
}
}
}
if (counts == mines)
{
printf("你赢了");
}
}
void game()
{
char show[ROWS][COLS] = { 0 };
char mine[ROWS][COLS] = { 0 };
Init(mine, ROWS, COLS, '0');
Init(show, ROWS, COLS, '*');
_mine(mine, ROW, COL);
Display(show,ROW,COL);
findmine(mine, show, ROW, COL);
}
test.c
#include"扫雷.h"
int main()
{
int input = 0;
do
{
menu();
printf("请输入:");
scanf_s("%d", &input);
switch (input)
{case 1:
game();
break;
case 0:
printf("退出游戏");
break;
default:printf("请重新输入:");
break;
}
} while (input);
return 0;
}
希望本篇文章对你有一些帮助。