目录
思路:
main函数内容:
创建“双子”数组:
初始化数组:
打印棋盘:
布置雷:
排查雷:
初阶:
大致过程:
如何统计周围雷的个数:
判断是否赢得游戏:
进阶:(可扩散可标记)
1.排雷:
2.标记:
标记要更改的时show数组,呈现给玩家标记信息;
3.取消标记:
整体代码呈现:
所有代码呈现:
game.h
game.c
test.c
总结:
这期内容我们来讲讲怎么用C语言实现扫雷游戏:
思路:
首先,还是和上一篇写的N子棋游戏一样,分为三个文件:
game.h -- 函数的声明、宏的定义、头文件的引用
game.c -- 函数的编写
test.c -- 函数的定义、整体逻辑的组织
创建一个棋盘,布置雷,雷的分布当然不能直接展现在玩家的面前,
因此,我们要创建两个数组,一个数组记录雷的分布信息,另一个数组记录玩家排雷的信息;
当所有没有雷的地方都被排干净之后,玩家胜利!
当玩家排到有雷的地方时,就会被炸死;
main函数内容:
首先打印一个目录供玩家选择是否进行游戏:
void menu()
{
printf(" 1.play \n");
printf(" 0.exit \n");
}
这是就需要创建一个变量input来接受玩家的选择,从而给出相应的反应:
当玩家选择1,开始游戏;
当玩家选择0,退出游戏,即退出程序;
每次游戏结束都判断一下玩家是否要再来一局游戏,打印目录供玩家选择;
因此,就形成了一种循环结构:
do...while循环
先打印一次目录,供玩家选择,若选择1,则进入游戏;若选择0,则退出循环;
而玩家的选择又是一种选择结构:
switch语句
结合二者:
将switch语句嵌入到do...while语句中:
int main()
{
int input = 0;
srand((unsigned int)time(NULL)); //用于布置雷的随机性,后面会详细讲解
do
{
menu(); //打印棋盘函数
printf("请选择:>");
scanf("%d", &input); //玩家选择
switch (input)
{
case 1:
game(); //进入游戏
break;
case 0: //退出游戏
printf("退出游戏\n");
break;
default: //若玩家不小心选择错误,就会提示玩家,让玩家重新选择。
printf("选择错误,请重新选择:>\n");
break;
}
} while (input); //while语句使用input作为判断条件,看似随意,实则十分巧妙
return 0; //input不仅可以当作switch语句的选择条件,当玩家选择0,即退出游戏时
} //input为0,条件为假,跳出循环;玩家不选择0,无论是选择1,还是选择
//错误,都为非0,条件为真,继续循环。
不太了解switch语句的可以看看我之前写的文章
switch语句--超详解
main函数完成了,剩下的大头就是game函数了:
创建“双子”数组:
上面提到过我们要创建两个二维数组,
一个用来存放布置雷的信息
一个用来存放排查雷的信息
char mine[ROWS][COLS] = { 0 }; //布置雷信息的数组
char show[ROWS][COLS] = { 0 }; //玩家排雷的数组
数组中的 ROWS 与 COLS 为宏常量,
为了方便控制棋盘的大小以及游戏的难度,我们就可以定义宏常量来代替数组的大小,当想要增加或降低游戏难度时,就可以只修改宏,便将整个程序所用到的该常量修改。
ps:宏常量的定义要在game.h头文件中定义
#define ROW 9 //行数
#define COL 9 //列数
#define ROWS ROW+2
#define COLS COL+2
#define MINE_NUM 10 //控制雷的数量,后面会讲解
这时,肯定会有细心的朋友发现,我定义了两类宏:ROW COL 与 ROWS COLS ,而且后者永远比前者多2。
这就要考虑到我们排雷时统计周围雷个数的问题了:
当我们排查雷时,要看这个格子周围的8个格子有没有雷,但是处于边界的格子周围总是不足8个格子,这时我们就需要将数组扩大一圈,这样边界的格子周围也有8个格子了,便于统计周围雷的个数。
由此,我们无论是布置雷,还是排查雷 都只使用中间的ROW行、COL列。
初始化数组:
mine数组初始化为'0'
show数组初始化为'*'
创建一个初始化数组的函数:
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
void init_board(char board[ROWS][COLS], int rows, int cols, char ch)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = ch;
}
}
}
由于我们要初始化两个数组,而且初始化内容也不一样,
所以,我们直接将初始化的字符也传参过去,这样就可以想初始化为什么就初始化为什么了。
打印棋盘:
上面我们已经说过了,布置雷和排查雷我们只需用到中间的ROW行 与 COL列的数组,
所以打印棋盘时,也只需打印中间这些部分:
为了方便玩家排雷输入坐标的准确性,我们也可以在棋盘的外围打印出行数与列数。
另一方面,玩家输入的坐标可以直接作为二维数组的下标,因为真正的棋盘行列的下标都是从1开始的。
display_board(mine, ROW, COL); //注意:这里传参传ROW与COL
display_board(show, ROW, COL);
void display_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//打印列数
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++) //第一行已经打印了一个0,所以这里i从1开始。
{
//打印行数
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]); //i与j都从1开始,正好符合玩家坐标的输入
}
printf("\n");
}
}
布置雷:
要在mine数组中存放雷的信息,mine数组原本全是'0',布置雷的地方就被改成'1'。
其次,我们想到的就是雷分布的随机性,
这里我们还是使用rand-srand函数:
定义两个变量n、m,用来存放布置的雷的坐标。
int n = rand() % ROW + 1;
int m = rand() % COL + 1;
(rand的取值范围为 0 ~ 32767 ,% ROW 后 ,即rand() % ROW 的取值范围为 0~ROW-1
再加上1 之后,n的取值范围就为1~ROW,符合棋盘的大小;
同理,m的取值范围也为1~COL)
srand要在主函数起始位置定义,同时通过time库函数,运用时间戳来确保随机性,
因为时间是 无时无刻都在变化的。
srand函数要包含头文件<stdlib.h>
time函数要包含头文件<time.h>
#include <stdlib.h>
#include <time.h>
还要定义一个变量k存储雷的数量:
int k = MINE_NUM;
用循环的结构将MINE_NUM个雷全部布置下来,
每布置一个雷,k就减1;
当然,还有一个非常重要的细节,布置过雷的地方不能再布置雷了,
因此,我们需要先判断一下该位置有没有雷,没有雷时,我们再布置雷。
void set_mine(char board[ROWS][COLS], int row, int col)
{
int k = MINE_NUM;
int n = 0;
int m = 0;
while (k) //循环布置雷,当要布置的雷的数量为0,即全部的雷已经布置完成
{ //k=0时,跳出循环。
n = rand() % ROW + 1;
m = rand() % COL + 1;
if (board[n][m] == '0')//判断该位置是否有雷,为'0'则没有雷
{
board[n][m] = '1'; //布置雷
k--; //雷的数量减1
}
}
}
排查雷:
初阶:
大致过程:
输入一个坐标,判断该位置有没有雷,
有雷,玩家被炸死,游戏结束;
没有类,则显示该坐标的周围8个格子一共有几个雷;
排查雷是一个循环的过程,要一直进行下去,除非玩家被炸死,或者玩家赢得游戏才会结束。
每次排完雷之后判断一下玩家是否赢得游戏,当棋盘上只剩下雷的时候,玩家赢得游戏。
如何统计周围雷的个数:
这就要联系到我们初始化mine二维数组时,将它初始化为'0'了。
布置雷时,我们将'0'改为'1',
统计周围雷的个数时,我们只需将周围的数加起来就好,
都是我们发现,这里的'0'与'1'都是字符啊,怎么能加起来呢?
这里就有一个知识点:
字符相加时,加的都是ASCII值,字符'0' 的ASCII值为48,字符'1'的ASCII值为49
'0' - '0' = 0(字符'0'减字符'0'等于数字0),'1' - '0' = 1(字符'1'减字符'0'等于数字1);
因此,我们只需将周围8个字符加起来,再减去8个'0',就可以得到周围雷的个数了。
讲到这里,肯定有人会问,那直接创建int 类型数组,放数字在里面不就好了,
但是,我们不仅要统计周围雷的个数,还要将这个数放到show数组里,呈现给玩家;
还是统一两个数组的类型比较好。
(若是你实在要用int 类型也是可以的)
得到周围雷的个数后,此时的类型为整形(减去8个'0'后),我们要再加上一个'0'后,变为字符类型,放到show数组里。
(直接加起来减去7个'0'也是可以的)
判断是否赢得游戏:
在循环外定义一个int类型变量win,每当排除一个坐标后win就加一
在循环部分的最后判断win的大小,
当win=ROW*COL-MINE_NUM时,就代表棋盘上只剩下雷,此时就赢游戏了。
break跳出循环。
函数定义:
find_mine(mine, show, ROW, COL);
函数内容:
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int n = 0;
int m = 0;
int win = 0;
while (1)
{
printf("请输入您要排查的坐标:>");
scanf("%d%d", &n, &m); //输入要排查的坐标
if (n >= 1 && n <= row && m >= 1 && m <= col) //判断坐标是否合法,即是否再棋盘上
{
if (mine[n][m] == '1') //判断该坐标是否为雷
{
printf("很遗憾,您被炸死了\n"); //为雷则被炸死,游戏结束
display_board(mine, ROW, COL); //打印一下雷的分布,让玩家瞑目
break; //被炸死,游戏结束,跳出循环
}
else
{
int num = get_mine_num(mine, n, m); //统计周围雷个数的函数
show[n][m] = num + '0'; //加'0',变为字符
display_board(show, ROW, COL); //打印棋盘,让玩家获得排查雷的信息
win++;
if (win == row * col - MINE_NUM) //判断是否获胜
{
printf("恭喜你,赢得游戏!\n");
break; //赢得游戏,游戏结束,跳出循环
}
}
}
else //坐标非法,进入下一次循环,重新输入排查坐标
printf("该坐标非法,");
}
}
//统计周围雷个数的函数
int get_mine_num(char mine[ROWS][COLS], int n, int m)
{
return (mine[n - 1][m]
+ mine[n - 1][m - 1]
+ mine[n][m - 1]
+ mine[n + 1][m - 1]
+ mine[n + 1][m]
+ mine[n + 1][m + 1]
+ mine[n][m + 1]
+ mine[n - 1][m + 1]) - 8 * '0'; //将周围8个格子的字符加起来,减去8个'0'
}
进阶:(可扩散可标记)
进阶版本与初阶版本相比,无非就是多了扩散与标记功能,其他功能都是一样的:
因为多了标记功能,所以在玩家操作的时候就不止排雷一种操作了,要让玩家选择操作。
有了标记功能,当然也要有取消标记的功能,这两个功能是共存的。
所有的操作都要在循环中进行,除非被雷炸死,或者赢得游戏游戏结束,才能退出循环,结束游戏。
在循环刚开始我们就要打印一个目录,让玩家选择操作:
void menu_word()
{
printf(" 1.排雷 \n");
printf(" 2.标记 \n");
printf(" 3.取消标记 \n");
}
涉及到选择,当然就离不开switch选择结构:
1.排雷:
其实排雷的过程和初阶版本的差不多,只不过排雷的函数变了,其余功能都一样:
case 1:
{
int n = 0;
int m = 0;
printf("请输入您要排查的坐标:>");
scanf("%d%d", &n, &m);
if (n<1 || n > ROW || m < 1 || m > COL) //判断坐标的合法性
{
printf("输入坐标有误\n"); //不合法,就提示玩家坐标有误
continue; //continue进入下一次循环
}
if (show[n][m] != '*' && show[n][m] != '#')//判断该坐标是否已经被排查过了
{ //#为标记字符
printf("该坐标已被占用\n"); //被排查过了,就提示玩家坐标已被占用
continue; //continue进入下一次循环
}
else if (mine[n][m] == '1') //判断该坐标是否有雷
{
system("cls"); //清理界面,使界面显得整洁
printf("您被炸死了\n"); //有雷,则玩家被炸死
display_board(mine, ROW, COL); //打印雷的分布,让玩家死的瞑目
flag = '0';
break; //break跳出switch语句
} //(注意:这里跳出的是switch语句,而不是循环,因为switch语句
else //对break语句有反应,只是跳出switch语句,而switch语句对continue语
{ //句没有反应,所以continue时就是直接进入下一次循环)
find_mine(mine, show, ROW, COL, n, m, pw);//排查雷的函数
system("cls"); //清理界面,使界面显得整洁
display_board(show, ROW, COL); //打印棋盘,让玩家获得排雷的信息
if (win == ROW * COL - MINE_NUM) //判断是否赢得游戏
{
system("cls"); //清理界面,使界面显得整洁
printf("恭喜你,赢得游戏!\n");
display_board(mine, ROW, COL); //打印雷的分布
flag = '0';
break;
}
}
break;
}
上面的代码段里说过了,在switch语句中的break只能跳出switch语句,
因此,我们在循环外定义了一个字符变量flag,当要退出循环时,在break之前,将flag赋值为'0'
在循环的最后部分,判断flag是否为'0',若是,则再来一个break跳出循环;若不是,则继续循环。
排雷的函数:
其实扩散就是利用函数递归来实现的
当该坐标周围没有雷时,就将周围8个坐标也点开,
直到点开的那个坐标周围有雷时,就不再扩散了,递归终止。
find_mine(mine, show, ROW, COL, n, m, pw);
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int n, int m, int* pw)
{ //n,m为玩家要排查的坐标;pw为win变量的地址,传递至可以通过形参来改变实参
if (n >= 1 && n <= row && m >= 1 && m <= col) //判断坐标是否合法
{
if (show[n][m] == '*' || show[n][m] == '#')//判断坐标是否被占用(#为标记字符)
{
int num = get_mine_num(mine, n, m); //计算该坐标周围的雷数
char ch = num + '0';
show[n][m] = ch; //放到show数组里
(*pw)++; //win++ (每排查一个,就加一)
if (ch == '0') //判断该坐标周围是否有雷,
{ //没有雷,则进入递归;有雷,则跳过,不递归
find_mine(mine, show, ROW, COL, n - 1, m, pw); //周围8个格子统统来一遍
find_mine(mine, show, ROW, COL, n - 1, m - 1, pw);
find_mine(mine, show, ROW, COL, n, m - 1, pw);
find_mine(mine, show, ROW, COL, n + 1, m - 1, pw);
find_mine(mine, show, ROW, COL, n + 1, m, pw);
find_mine(mine, show, ROW, COL, n + 1, m + 1, pw);
find_mine(mine, show, ROW, COL, n, m + 1, pw);
find_mine(mine, show, ROW, COL, n - 1, m + 1, pw);
}
}
}
}
//计算周围雷数量的函数
int get_mine_num(char mine[ROWS][COLS], int n, int m)
{
return (mine[n - 1][m]
+ mine[n - 1][m - 1]
+ mine[n][m - 1]
+ mine[n + 1][m - 1]
+ mine[n + 1][m]
+ mine[n + 1][m + 1]
+ mine[n][m + 1]
+ mine[n - 1][m + 1]) - 8 * '0';
}
2.标记:
标记要更改的时show数组,呈现给玩家标记信息;
将要标记的地方改为'#';
要注意的是:已经被排查过的地方不能被标记;
case 2:
sign_mine(show, ROW, COL);
break;
void sign_mine(char show[ROWS][COLS], int row, int col)
{
int n = 0;
int m = 0;
printf("请输入要标记的坐标:>");
scanf("%d%d", &n, &m);
if (show[n][m] == '*') //只有当该坐标上的字符为'*'时,才可以被标记
{
show[n][m] = '#'; //将'*'改为'#',即为标记
system("cls"); //清空界面,使界面整洁
display_board(show, ROW, COL); //打印棋盘,呈现给玩家信息
}
else //若不能被标记,则提醒玩家,让玩家重新选择操作
{
printf("该坐标不可标记\n");
}
}
3.取消标记:
就是将标记的地方重新改为'*';
注意:只有'#'可以被更改。
case 3:
c_sign(show, ROW, COL);
break;
void c_sign(char show[ROWS][COLS], int row, int col)
{
int n = 0;
int m = 0;
printf("请输入要取消标记的坐标:>");
scanf("%d%d", &n, &m);
if (show[n][m] == '#') //判断是否可以取消标记
{
show[n][m] = '*'; //更改为'*'
system("cls"); //清理界面,使界面整洁
display_board(show, ROW, COL); //打印棋盘,给玩家信息
}
else //若该坐标上的字符不为'#',则不可取消标记,
{ //提醒玩家该位置未被标记,让玩家重新选择操作
printf("该坐标未被标记\n");
}
}
整体代码呈现:
int win = 0; //win变量,用于判断是否赢得游戏
int* pw = &win; //取地址,用于传参,通过形参来改变实参
char flag = '?'; //由于判断游戏的状态
while (1) //进入循环,开始操作,一直循环,除非break跳出循环
{
menu_word(); //打印目录,让玩家选择操作内容
int input = 0;
printf("请选择您的操作:>");
scanf("%d", &input);
switch (input) //根据玩家的选择,执行程序
{
case 1: //排雷
{
int n = 0;
int m = 0;
printf("请输入您要排查的坐标:>");
scanf("%d%d", &n, &m); //输入排雷的坐标
if (n<1 || n > ROW || m < 1 || m > COL) //判断坐标是否合法
{
printf("输入坐标有误\n");
continue; //若坐标非法,则continue进入下一次循环
}
if (show[n][m] != '*' && show[n][m] != '#') //判断坐标是否被占用
{
printf("该坐标已被占用\n");
continue; //若坐标被占用,则continue进入下一次循环
}
else if (mine[n][m] == '1') //判断该坐标是否有雷
{
system("cls");
printf("您被炸死了\n"); //若有雷,则被炸死,游戏结束
display_board(mine, ROW, COL); //打印雷的分布,让玩家死的瞑目
flag = '0'; //将flag赋值为'0',用于后面的判断,表示游戏结束
break; //break跳出switch语句
}
else //若该坐标不为雷,则进行排雷
{
find_mine(mine, show, ROW, COL, n, m, pw); //排雷的函数
system("cls");
display_board(show, ROW, COL); //打印棋盘,提供玩家排雷信息
if (win == ROW * COL - MINE_NUM) //判断是否赢得游戏
{
system("cls");
printf("恭喜你,赢得游戏!\n");
display_board(mine, ROW, COL); //打印雷的分布
flag = '0'; //将flag赋值为'0',用于后面的判断,表示游戏结束
break; //break跳出switch语句
}
}
break;
}
case 2:
sign_mine(show, ROW, COL); //进行标记的函数
break;
case 3:
c_sign(show, ROW, COL); //取消标记的函数
break;
default:
printf("选择错误\n"); //若玩家选择错误,则提醒玩家,让玩家重新选择
break;
}
if (flag == '0') //判断flag的值,若为'0',则代表游戏结束,break跳出循环
{ //否则,进行下一次循环
break;
}
}
所有代码呈现:
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 MINE_NUM 10
//初始化棋盘的声明
void init_board(char board[ROWS][COLS], int rows, int cols, char ch);
//打印棋盘的声明
void display_board(char board[ROWS][COLS], int row, int col);
//布置雷的声明
void set_mine(char board[ROWS][COLS], int row, int col);
//排查雷的声明
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//标记雷的声明
void sign_mine(char show[ROWS][COLS], int row, int col);
//取消标记的声明
void c_sign(char show[ROWS][COLS], int row, int col);
game.c
#include "game.h"
//初始化棋盘的函数
void init_board(char board[ROWS][COLS], int rows, int cols, char ch)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = ch;
}
}
}
//打印棋盘的函数
void display_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//打印列数
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
//打印行数
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//布置雷的函数
void set_mine(char board[ROWS][COLS], int row, int col)
{
int k = MINE_NUM;
int n = 0;
int m = 0;
while (k)
{
n = rand() % ROW + 1;
m = rand() % COL + 1;
if (board[n][m] == '0')
{
board[n][m] = '1';
k--;
}
}
}
//排查雷的函数
//void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
//{
// int n = 0;
// int m = 0;
// int win = 0;
// while (1)
// {
// printf("请输入您要排查的坐标:>");
// scanf("%d%d", &n, &m);
// if (n >= 1 && n <= row && m >= 1 && m <= col)
// {
// if (mine[n][m] == '1')
// {
// printf("很遗憾,您被炸死了\n");
// display_board(mine, ROW, COL);
// break;
// }
// else
// {
// int num = get_mine_num(mine, n, m);
// show[n][m] = num + '0';
// display_board(show, ROW, COL);
// win++;
// if (win == row * col - MINE_NUM)
// {
// printf("恭喜你,赢得游戏!\n");
// break;
// }
// }
// }
// else
// printf("该坐标非法,");
// }
//}
int get_mine_num(char mine[ROWS][COLS], int n, int m)
{
return (mine[n - 1][m]
+ mine[n - 1][m - 1]
+ mine[n][m - 1]
+ mine[n + 1][m - 1]
+ mine[n + 1][m]
+ mine[n + 1][m + 1]
+ mine[n][m + 1]
+ mine[n - 1][m + 1]) - 8 * '0';
}
//排查雷的函数 (可以扩散排查)!!!
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int n, int m, int* pw)
{
if (n >= 1 && n <= row && m >= 1 && m <= col)
{
if (show[n][m] == '*' || show[n][m] == '#')
{
int num = get_mine_num(mine, n, m);
char ch = num + '0';
show[n][m] = ch;
(*pw)++;
if (ch == '0')
{
find_mine(mine, show, ROW, COL, n - 1, m, pw);
find_mine(mine, show, ROW, COL, n - 1, m - 1, pw);
find_mine(mine, show, ROW, COL, n, m - 1, pw);
find_mine(mine, show, ROW, COL, n + 1, m - 1, pw);
find_mine(mine, show, ROW, COL, n + 1, m, pw);
find_mine(mine, show, ROW, COL, n + 1, m + 1, pw);
find_mine(mine, show, ROW, COL, n, m + 1, pw);
find_mine(mine, show, ROW, COL, n - 1, m + 1, pw);
}
}
}
}
//标记雷的函数
void sign_mine(char show[ROWS][COLS], int row, int col)
{
int n = 0;
int m = 0;
printf("请输入要标记的坐标:>");
scanf("%d%d", &n, &m);
if (show[n][m] == '*')
{
show[n][m] = '#';
system("cls");
display_board(show, ROW, COL);
}
else
{
printf("该坐标不可标记\n");
}
}
//取消标记的函数
void c_sign(char show[ROWS][COLS], int row, int col)
{
int n = 0;
int m = 0;
printf("请输入要取消标记的坐标:>");
scanf("%d%d", &n, &m);
if (show[n][m] == '#')
{
show[n][m] = '*';
system("cls");
display_board(show, ROW, COL);
}
else
{
printf("该坐标未被标记\n");
}
}
test.c
#include "game.h"
void menu()
{
printf(" 1.play \n");
printf(" 0.exit \n");
}
void menu_word()
{
printf(" 1.排雷 \n");
printf(" 2.标记 \n");
printf(" 3.取消标记 \n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
//mine数组初始化为'0'
//show数组初始化为'*'
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
//打印棋盘
//display_board(mine, ROW, COL);
display_board(show, ROW, COL);
//布置雷
set_mine(mine, ROW, COL);
//display_board(mine, ROW, COL);
//排查雷
//find_mine(mine, show, ROW, COL);
int win = 0;
int* pw = &win;
char flag = '?';
while (1)
{
menu_word();
int input = 0;
printf("请选择您的操作:>");
scanf("%d", &input);
switch (input)
{
case 1:
{
int n = 0;
int m = 0;
printf("请输入您要排查的坐标:>");
scanf("%d%d", &n, &m);
if (n<1 || n > ROW || m < 1 || m > COL)
{
printf("输入坐标有误\n");
continue;
}
if (show[n][m] != '*' && show[n][m] != '#')
{
printf("该坐标已被占用\n");
continue;
}
else if (mine[n][m] == '1')
{
system("cls");
printf("您被炸死了\n");
display_board(mine, ROW, COL);
flag = '0';
break;
}
else
{
find_mine(mine, show, ROW, COL, n, m, pw);
system("cls");
display_board(show, ROW, COL);
if (win == ROW * COL - MINE_NUM)
{
system("cls");
printf("恭喜你,赢得游戏!\n");
display_board(mine, ROW, COL);
flag = '0';
break;
}
}
break;
}
case 2:
sign_mine(show, ROW, COL);
break;
case 3:
c_sign(show, ROW, COL);
break;
default:
printf("选择错误\n");
break;
}
if (flag == '0')
{
break;
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择:>\n");
break;
}
} while (input);
return 0;
}
总结:
其实每个语句都不难,但是整体组合在一起就显得比较复杂,我们只需要一点点分析,用逻辑将他们联合起来就成功了!
最后,希望这篇文章可以帮助到大家,喜欢的话记得三连哦~
关注博主,后续会持续推迟优质内容~
感谢大家的支持~