效果展示
第一次写应该会有点累赘。下面是最终实现:
20240201-0543-02.3771370
目录
(6)选择难度(我是通过改变game函数的参数再分别放入副菜单啦。谢谢大家了。
20240201-0543-02.3771370
整体思路
首先创建两个字符数组,一个用来存储数据,另一个负责打印显示到控制台。考虑用‘1’表示雷,‘0’表示非雷,因为这样方便后续纪录雷的数量,为了方便同时防止后续记录雷数量时越界,会多加两行两列赋值为’0‘不可修改 作为边界。
1. 头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//简单
#define ROW 9
#define QUEUE 9
#define ROW1 ROW + 2
#define QUEUE1 QUEUE + 2
#define LANDMINE 10
//中等
#define ROWII 16
#define QUEUEII 16
#define ROWII1 ROWII + 2
#define QUEUEII1 QUEUEII + 2
#define LANDMINEII 40
//难
#define ROWIII 16
#define QUEUEIII 30
#define ROWIII1 ROWIII + 2
#define QUEUEIII1 QUEUEIII + 2
#define LANDMINEIII 99
2. 打印菜单
副菜单用来选择难度
int main()
{
do
{
srand(time(NULL)); //用于生成随机值后续埋雷用
menu();
int E = 0;
scanf("%d", &E);
system("cls"); //用来清屏
switch (E)
{
case 1:
game(); //游戏实现
break;
case 2:
return;
case 3:
E = nan_du(); //链接副菜单
default:
if(E != 6) //副菜单调用结束返回6进入主菜单
printf("输入错误,请重试!\n");
}
} while (1);
return 0;
}
//主菜单
void menu()
{
printf("\n");
printf(" ____________________________扫雷小游戏______________________________\n ");
printf("| 1. PLAY(默认简单) || 2. EXIT || 3. 选择难度 || 请选>>: ");
}
//副菜单
int nan_du()
{
while (1)
{
printf("\n");
printf(" _____________________________难度选择___________________________\n ");
printf("| 1. 中等 || 2. 难 || 3. 返回 || 请选>>:");
int i = 0;
scanf("%d", &i);
system("cls");
switch (i)
{
case 1:
//把传参数据改一下
gameII();
return 6;
case 2:
gameIII();
return 6;
case 3:
return 6;
default:
printf("输入错误,请重试!\n");
}
}
}
3. game函数--游戏实现(核心)
(1)game函数整体
void game()
{
printf("\n");
//负责存雷否
char base[ROW1][QUEUE1];
//负责控制台显示
char show[ROW1][QUEUE1];
// 初始化数组
initialize(base, ROW1, QUEUE1, '0');
initialize(show, ROW1, QUEUE1, '*');
// 埋雷
landmine(base, LANDMINE, ROW, QUEUE);
// 打印
print(show, ROW, QUEUE);
print(base, ROW, QUEUE);
// 玩家操作
realy(base, show, 1);
}
(2)初始化函数,双循环赋值。
// 初始化
void initialize(char diagram[ROW1][QUEUE1], int row, int queue, char ch)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < queue; j++)
diagram[i][j] = ch;
}
}
(3)打印函数,以下是初始化控制台显示
void print(char diagram[ROW1][QUEUE1], int row, int queue)
{
int i = 0;
printf(" ");
for (i = 1; i <= queue; i++)
printf("%-3d", i);
printf("\n");
// 打印行数
printf(" ");
for (i = 1; i <= queue; i++)
printf("---");
printf("-");
printf("\n");
//打印的核心
for (i = 1; i <= row; i++)
{
int j = 0;
printf(" %-2d| ",i); // 打印列数
for (j = 1; j <= queue; j++)
printf("%c ", diagram[i][j]);
printf("|\n");
}
printf(" ");
for (i = 1; i <= queue; i++)
printf("---");
printf("-");
printf("\n");
}
(4)埋雷函数
void landmine(char diagram[ROW1][QUEUE1],int land, int row, int queue)
{
int i = land; //传10个雷
while(i)
{
int r = rand() % row + 1; //负责随机生成 不越界的 横坐标
int q = rand() % queue + 1; //负责随机生成 不越界的 纵坐标
if (diagram[r][q] != '1') //避免重复在同一位置埋雷
{
diagram[r][q] = '1';
i--;
}
}
}
’1‘ 表示雷
(5)玩家操作
//玩家操作
void realy(char diagram[ROW1][QUEUE1], char show[ROW1][QUEUE1],int i)
{
int X = 0, Y = 0, Z = 0;
switch (i) // 这里用来选择难度
{
case 1:
X = ROW; Y = QUEUE; Z = LANDMINE;
break;
case 2:
X = ROWII; Y = QUEUEII; Z = LANDMINEII;
break;
case 3:
X = ROWIII; Y = QUEUEIII; Z = LANDMINEIII;
break;
}
int Count = X * Y - Z; //总格子数减去雷数
while (Count) //当空白格子全部被展开时,循环停止
{
printf("请选择坐标>>;");
int x = 0, y = 0;
scanf("%d,%d", &x, &y);
system("cls");
//判断是否触雷
if (diagram[x][y] == '1') //游戏结束用'!'显示所有的雷
{
for(int i = 1; i <= X; i++)
{
for (int j = 1; j <= Y; j++)
{
if (diagram[i][j] == '1')
show[i][j] = '!';
}
}
print(show, X, Y);
printf("你已被炸死,失败,游戏结束。\n");
return;
}
else
{
Kai(diagram, show, x, y, X, Y); //用于自动展开一片空白格子
print(show, X, Y);
Count--;
}
}
printf("恭喜你通关!\n");
}
这里把雷放慢进行检查
Kai函数用递归实现:
//计雷数
char num(char diagram[ROW1][QUEUE1],int x, int y)
{
char h = (diagram[x - 1][y]
+ diagram[x - 1][y + 1]
+ diagram[x][y + 1]
+ diagram[x + 1][y + 1]
+ diagram[x + 1][y]
+ diagram[x + 1][y - 1]
+ diagram[x][y - 1]
+ diagram[x - 1][y - 1]) - 7 * '0';
if (h != '0')
{
return h;
}
else return ' ';
}
//开图
void Kai(char diagram[ROW1][QUEUE1], char show[ROW1][QUEUE1], int x, int y, int row, int queue)
{
if ((x >= 1 && x <= row) && (y >= 1 && y <= queue)) //防止越界访问
{
char count = num(diagram, x, y); //调用num判断此坐标周围有没有雷。
if (' ' == count)
{
show[x][y] = ' ';
// 双循环递归判断8个方向
for (int i = x - 1; i <= x + 1; i++)
{
for (int j = y - 1; j <= y + 1; j++)
{
if ('*' == show[i][j]) //避免重复
{
Kai(diagram,show, i, j, row, queue);
}
}
}
}
else
{
show[x][y] = count;
}
}
}
然后就可以自动展开啦!
(6)选择难度(我是通过改变game函数的参数再分别放入副菜单啦。谢谢大家了。
void game()
{
printf("\n");
//负责存雷否
char base[ROW1][QUEUE1];
//负责控制台显示
char show[ROW1][QUEUE1];
// 初始化数组
initialize(base, ROW1, QUEUE1, '0');
initialize(show, ROW1, QUEUE1, '*');
// 埋雷
landmine(base, LANDMINE, ROW, QUEUE);
print(show, ROW, QUEUE);
print(base, ROW, QUEUE);
realy(base, show, 1);
}
void gameII()
{
printf("\n");
char base[ROWII1][QUEUEII1];
char show[ROWII1][QUEUEII1];
initialize(base, ROWII1, QUEUEII1, '0');
initialize(show, ROWII1, QUEUEII1, '*');
landmine(base, LANDMINEII, ROWII, QUEUEII);
print(show, ROWII, QUEUEII);
print(base, ROWII, QUEUEII);
realy(base, show, 2);
}
void gameIII()
{
printf("\n");
char base[ROWIII1][QUEUEIII1];
char show[ROWIII1][QUEUEIII1];
initialize(base, ROWIII1, QUEUEIII1, '0');
initialize(show, ROWIII1, QUEUEIII1, '*');
landmine(base, LANDMINEIII, ROWIII, QUEUEIII);
print(show, ROWIII, QUEUEIII);
print(base, ROWIII, QUEUEIII);
realy(base, show, 3);
}