扫雷游戏(已优化版)

简介: 本文详细介绍了如何用C语言实现经典的扫雷游戏。首先通过两个11×11的字符数组(`mine`存放地雷信息,`show`存放排雷信息)来构建游戏棋盘,并通过初始化、布置地雷、打印棋盘等步骤完成基本功能。为解决边界问题,将实际9×9棋盘嵌套在11×11数组中,避免越界操作。接着实现了扫雷逻辑,包括递归展开空白区域、标记和取消标记地雷等功能。此外,还加入了难度选择、颜色设置和提示机会等优化功能,使游戏更具互动性和挑战性。代码结构清晰,功能模块化,适合初学者学习和扩展。


在正文开始之前,先来个简单的介绍扫雷:
1、游戏概述
扫雷游戏想必大家应该都玩过吧,这个游戏的目标呢就是在一个 9x9 的棋盘上找出所有没有地雷的格子,而不踩到地雷。当然这个9×9只是一个初级玩法,棋盘大小和雷的数量是可以随便设置的,有那种电脑满屏的模式,但是我没去尝试过,一般玩的都是初级9×9的模式,而本篇文章也主要说的是9×9扫雷游戏的实现。

棋盘上的某些格子里有地雷,其他格子是空白的。
游戏开始时,棋盘上会有一些数字,这些数字表示周围 8 个格子中地雷的数量。
通过点击格子,如果格子是空白的,则会打开该格子;如果格子中有地雷,则游戏结束。
如果打开的格子周围的地雷数量与数字相符,则该格子周围的其他格子也会被打开。
游戏的目标是在不踩到地雷的情况下,找出所有没有地雷的格子
大致的思路图(菜单部分没有显示)

第一步:准备两个棋盘;
为了统计方便我们统一设定一下用字符数组;

数组一:(存放雷的信息)mine数组

数组二:(存放排雷的信息)show数组

首先在这里解释一下,为什么要用到两个数组,因为扫雷中有这样一个规则 ,如果该处没有雷,那么就会会显示为0个雷(并且周围一圈也无雷)(也就是空白),但如果周围有几个雷那么该处就会显示为几,那么该处就的数组会存放该值,如果使用一个数组,难免就会造成冲突,使得其造成麻烦。

解释一下为什么要设置棋盘大小为11*11

假设我们排查(2,5)这个坐标时,我们访问周围的⼀圈8个⻩⾊位置,统计周围雷的个数是1 假设我们排查(8,6)这个坐标时,我们访问周围的⼀圈8个⻩⾊位置,统计周围雷的个数时,最下⾯的三 个坐标就会越界,为了防⽌越界,我们在设计的时候,给数组扩⼤⼀圈,雷还是布置在中间的99的坐 标上,周围⼀圈不去布置雷就⾏,这样就解决了越界的问题。所以我们将存放数据的数组创建成1111 是⽐较合适

数组设置:

char show[11][11];
//展示的棋盘,存放排雷的信息
char mine[11][11];
//存放雷的信息

我们在设置数组时用数字设置大小,不免显得我们技术不高,我们可以使用宏来定义下

define ROW 9

define COL 9

define ROWS ROW+2

define COLS COL+2

这里要定义ROWS COLS=ROW+2/COL+2是因为要统计周围,为了方便才这样;

第二步:初始化数组:
我们将存放雷的数组全部初始化为0;为了保持神秘,将数组show全部初始化为*;使用函数实现

void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < row+2; i++)
{
int j = 0;
for (j = 0; j < col+2; j++)
{
board[i][j] = set;
}
}
}

Initboard(show,ROWS,COLS,'*');

Initboard(mine,ROWS,COLS,'0');
//0 不是雷 1是雷

第三步:这一步也是最重要的一步,打印棋盘,(主要作用检查前面的代码是否正确):
void Displaymine(char board[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%3d", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 1;
printf("%2d", i);
for (j = 1; j <= col; j++)
{
printf(" %c ", board[i][j]);
}
printf("\n");
}
}//函数部分

//打印棋盘信息
Displaymine(show,ROW,COL);//9*9   ****
Displaymine(mine,ROW,COL);

值得注意的一点形参的名字尽量不要与宏定义的名字重合,避免造成不必要的麻烦;

第四步:布置雷(1是雷,0不是雷)
void Setmine(char board[ROWS][COLS], int row, int col)
{
int count = counts;
//生成十个雷
int x=0;//行
int y=0;//列
while (count)//利用坐标布置雷
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}//使用坐标来实现

Setmine(mine, ROW, COL);

这一步没什么难度,来最后一步;

第五步:扫雷:
第五步来画一个简单的实现图

天冷,写字不易,还请多担待;

代码实现如下:

void Findmine(char board[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while (count 0 && x <= 9 && y > 0 && y <= 9)
{//坐标合理
if (board[x][y] == '0')//第一次查找
{
if(show[x][y]=='')
{
int ret = Countmine(board, x, y);//查看附近有几个雷
show[x][y] = ret + '0';
//再次打印棋盘
Displaymine(show, ROW, COL);
count++;
}
else
{
printf("该坐标已经查找过了,请在次输入新坐标:\n");
}
}
else
{
printf("很遗憾,你被雷炸死了\n");
Displaymine(board, ROW, COL);
break;
}
}
else
{
printf("输入的坐标不合理,请重新输入新的坐标:\n");
}
if (count == row
col - counts)
{
printf("恭喜你,获胜了\n");
Displaymine(board, ROW, COL);
}
}
}

Findmine(mine,show, ROW, COL);//传进去两个数组

在这个代码中有一行是这个,那么展示怎么实现:

int Countmine(char board[ROWS][COLS], int x, int y)
{
int i = 0;
int count = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
count += board[i][j] - '0';
}
}
return count;
}

int Counts(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0';
}

完整的代码:

define _CRT_SECURE_NO_WARNINGS

include"game.h"

void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}

void Displaymine(char board[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%3d", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 1;
printf("%2d", i);
for (j = 1; j <= col; j++)
{
printf(" %c ", board[i][j]);
}
printf("\n");
}
}

void Setmine(char board[ROWS][COLS], int row, int col)
{
int count = counts;
//生成十个雷
int x=0;//行
int y=0;//列
while (count)//利用坐标布置雷
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}

int Countmine(char board[ROWS][COLS], int x, int y)
{
int i = 0;
int count = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
count += board[i][j] - '0';
}
}
return count;
}

void Findmine(char board[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while (count 0 && x <= 9 && y > 0 && y <= 9)
{//坐标合理
if (board[x][y] == '0')//第一次查找
{
if(show[x][y]=='')
{
int ret = Countmine(board, x, y);//查看附近有几个雷
show[x][y] = ret + '0';
//再次打印棋盘
Displaymine(show, ROW, COL);
count++;
}
else
{
printf("该坐标已经查找过了,请在次输入新坐标:\n");
}
}
else
{
printf("很遗憾,你被雷炸死了\n");
Displaymine(board, ROW, COL);
break;
}
}
else
{
printf("输入的坐标不合理,请重新输入新的坐标:\n");
}
if (count == row
col - counts)
{
printf("恭喜你,获胜了\n");
Displaymine(board, ROW, COL);
}
}
}

define _CRT_SECURE_NO_WARNINGS

include"game.h"

void menu()
{
printf("**\n");
printf(" 1 . play \n");
printf(" 0 . exit \n");
printf("**\n");
}
void game()
{

char show[ROWS][COLS];
//展示的棋盘,存放排雷的信息
char mine[ROWS][COLS];
//存放雷的信息

//初始化棋盘 11*11
Initboard(show,ROWS,COLS,'*');

Initboard(mine,ROWS,COLS,'0');
//0 不是雷   1是雷

//打印棋盘信息
//Displaymine(show,ROW,COL);//9*9
//Displaymine(mine,ROW,COL);

//布置雷
Setmine(mine, ROW, COL);
Displaymine(show, ROW, COL);
Displaymine(mine, ROW, COL);

//扫雷
Findmine(mine,show, ROW, COL);//传进去两个数组

}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do {
menu();
scanf("%d", &input);
switch (input)
{
case 1:
printf("---------扫雷---------\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
break;
}
} while (input);
return 0;
}

define _CRT_SECURE_NO_WARNINGS

define ROW 9

define COL 9

define ROWS ROW+2

define COLS COL+2

define counts 10

include

include

include

void Initboard(char board[ROWS][COLS], int rows, int cols, char set);

void Displaymine(char board[ROWS][COLS],int row,int col);//要避免与宏的名字重

void Setmine(char board[ROWS][COLS], int row, int col);

void Findmine(char board[ROWS][COLS], char show[ROWS][COLS], int row, int col);

首先实现难度选择
难度的设置:

因为我们是使用的宏,所以改起来非常方便,首先尝试我们把宏定义的ROW与COLS改为18

运行结果:

除了对不齐大致正确,

我思考后,我感觉可以这样修改代码实现难度选择:

但是这样写起来会有警告:

乍一看这样貌似也是对的,毕竟可以打印出来难度最高的情况,但是对于#define我们在编译的时候,代码是从上往下依次执行,所以在执行到第一个#define ROW 9的时候确实会把所有的ROW换为9 ,但是往下执行代码的时候同样也会以相同的道理执行代码将ROW换为16,最后换为30

所以这样来写是有问题的;那么我们要怎么样子去写这个代码呢?

上面那个a的代码其实已经给出了我们思路,我们不妨抛弃不去使用#define,转而使用extern然后运用switch去改变row跟col的值

代码如下:

int input = 0;
do
{
    menu2();
    scanf("%d", &input);

    switch (input)
    {
    case 1:
        row = 9, col = 9, mine_num = 10;
        break;
    case 2:
        row = 16, col = 16, mine_num = 40;
        break;
    case 3:
        row = 30, col = 16, mine_num = 99;
        break;
    default:
        printf("选择错误,请重新选择\n");
        break;
    }
} while (input != 1 && input != 2 && input != 3);

在.h文件中我们需要运用extern

extern int row;//行数
extern int col;//列数
extern int mine_num;//类的个数
需要注意的是,我们在.h文件里面运用了extern如果要想在别的.c文件可以使用,那么需要在.c文件的头几行加上

那么行与列的控制搞定,只需要搞定数组了,因为数组大小会随着难度不同,而改变其行与列的大小,所以我们需要运用到动态内存分配,开辟二维数组:

//创建棋盘
char** mine = (char**)malloc(sizeof(char*) * (row + 2));//存放每一行都首元素
char** show = (char**)malloc(sizeof(char*) * (row + 2));
int i = 0;
for (i = 0; i < row + 2; i++)
{
    //存放雷的信息
    mine[i] = (char*)malloc(sizeof(char) * (col + 2));
    //展示的棋盘,存放排雷的信息
    show[i] = (char*)malloc(sizeof(char) * (col + 2));
}

相应的我们传的就是二维数组指针,那么对应的也就不需要再进行传行与列的大小了(进行优化,不该按理说没问题);

递归展开一片
这一部分还是好实现的

大致思路就是先写出来正规的扫雷,然后再在里面加入递归函数,大致位置如下

改函数内部的实现思路就是:我们先检查他周围一格内是否为雷的代码写出来 ,如果四周里面有的地方为四周全无雷,那么在进行递归他这个位置的情况,

相比于汉诺他还是比较好理解的

代码如下:

void digui(char board, char show, int x, int y, int count)
{
if (x >= 1 && x <= col && y >= 1 && y <= row)
{
int ret = Countmine(board, x, y);
(
count)++;
if (ret > 0)
{
show[x][y] = ret + '0';
return;
}
else //四周没雷,进入递归展开
{
show[x][y] = ' ';//四周没雷的改为 空格 ' '
int i = 0;
// 向四周共8个位置递归
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{

                //只对 '*' 进行展开,防止死循环
                if (show[i][j] == '*')
                {
                    digui(board, show, i, j, count);
                }

            }
        }
    }
}

}

标记雷
在玩网页版的扫雷的时候都会有标记雷,就是用小红旗标记这个位置是雷,以方便我们获胜。

需要注意的是p是指针,传的是一个数的地址,可以改变函数外的值

void set_flag(char* show, int p)
{
//设计被标记的地方设为’@‘
int x = 0;
int y = 0;
//if (p == mine_num)
printf("%d \n",
p);
if (p == 1)
{
printf("已经达到标记最大值\n");
return;//达到最大标记量
}
while (1)
{
printf("请输入需要标记的坐标\n");
scanf("%d%d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '
')//没有被排查过而且也没有被标记过
{
show[x][y] = '@';
(p)++;
break;
}
else if (show[x][y] != '@' && show[x][y] != '
')
{
printf("抱歉,该坐标已扫查过,不是雷,请从新输入坐标n");
continue;
}
else
{
printf("抱歉,该坐标已经被标记过,请从新输入坐标\n");
continue;
}
}
else {
printf("坐标非法,请从新输入新的坐标\n");
continue;
}
}
}

有标记雷,哪么就一定有取消标记,取消标记就是标记的逆思路实现

void cancle_flag(char* show, int p)
{
int x = 0;
int y = 0;
if ((p) == 0)
{
printf("目前没有标记,无法进行取消标记\n");
return;
}
while (1)
{
printf("请输入需要取消标记的坐标\n");
scanf("%d%d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '@')
{
show[x][y] = '
';
(*p)--;
break;
}
else if (show[x][y] != '@')
{
printf("该坐标不为标记坐标,请重新输入新的坐标,\n请输入正确的标记坐标\n");
continue;
}
}
else
{
printf("坐标非法,请重新输入\n");
continue;
}
}
}

颜色设置
实现代码就是如上,但是我们一直使用一个颜色来去打印,并且打印提示信息,这样就会让玩家看起并不是很方便,那么一般来说,我们一般是把重要的信息进行标红,来让我们一看就可以看出来哪里是重点。

这里运用到一个别的函数,该函数需要使用API来实现

函数为:

void color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //颜色设置
//注:SetConsoleTextAttribute是一个API(应用程序编程接口)
}
还需要引用头文件

颜色设置函数的作用是,将此后输出的内容颜色都更为所指定的颜色,接收的参数c是颜色代码,十进制颜色代码表如下:

只需要在需要提示信息前面调用该函数即可,比如

color(6);//设置米黄色
print("sss");
这样打印出来的就不只是默认的白色,而是我们设置的颜色,米黄色,

但是使用完后还要记得该回去

我们还可以进行一点的小优化,比如给五次机会,选择提示标记的地方是不是雷

代码实现如下:

void help_flag(char* board, int x, int y,int n)
{
color(6);
if ((n) == 0)
{
printf("很遗憾,你已经没有提示机会了\n");
}
(
n)--;
if (board[x][y] == '1')
{
printf("恭喜你标记对了,该坐标就为雷\n");
printf("你还剩余%d次提示机会\n",n);
}
else
{
printf("很遗憾,该坐标不为雷,你还剩余%d次提示机会\n",
n);
}
color(7);
}

需要改变的是标记雷的代码区域,需要添加两个参数

最后在进行最后的优化,进行适当的清屏,让代码运行起来后打印屏幕看起来更高级点;

待优化:排行榜
game.c

define _CRT_SECURE_NO_WARNINGS

include"game.h"

void color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //颜色设置
//注:SetConsoleTextAttribute是一个API(应用程序编程接口)
}
void Initboard(char** board, char set)
{
int i = 0;
for (i = 0; i < row + 2; i++)
{
int j = 0;
for (j = 0; j < col + 2; j++)
{
board[i][j] = set;
}
}
}

void Displaymine(char** board)
{
color(7); //颜色设置为白色
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%-3d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 1;
printf("%-3d ", i);
for (j = 1; j <= col; j++)
{
printf("%-3c ", board[i][j]);
}
printf("\n");
}
}

void Setmine(char** board)
{
int count = mine_num;
//生成十个雷
int x = 0;//行
int y = 0;//列
while (count)//利用坐标布置雷
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}

int Countmine(char** board, int x, int y)
{
int i = 0;
int count = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
count += board[i][j] - '0';
}
}
return count;
}

void digui(char board, char show, int x, int y, int count)
{
if (x >= 1 && x <= col && y >= 1 && y <= row)
{
int ret = Countmine(board, x, y);
(
count)++;
if (ret > 0)
{
show[x][y] = ret + '0';
return;
}
else //四周没雷,进入递归展开
{
show[x][y] = ' ';//四周没雷的改为 空格 ' '
int i = 0;
// 向四周共8个位置递归
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{

                //只对 '*' 进行展开,防止死循环
                if (show[i][j] == '*')
                {
                    digui(board, show, i, j, count);
                }

            }
        }
    }
}

}

void help_flag(char* board, int x, int y,int n)
{
color(9);//深蓝色
if ((n) == 0)
{
printf("很遗憾,你已经没有提示机会了\n");
}
(
n)--;
if (board[x][y] == '1')
{
printf("恭喜你标记对了,该坐标就为雷\n");
printf("你还剩余%d次提示机会\n",n);
}
else
{
printf("很遗憾,该坐标不为雷,你还剩余%d次提示机会\n",
n);
}
color(7);
}

void set_flag(char show, char board, int p, int p1, int p2)
{
color(6);
//设计被标记的地方设为’@‘
int x;
int y;
//if (
p == mine_num)
printf("%d \n", p);
if (
p == mine_num)
{
printf("已经达到标记最大值\n");
return;//达到最大标记量
}
while (1)
{
printf("请输入需要标记的坐标\n");
scanf("%d%d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '')//没有被排查过而且也没有被标记过
{
p1 = x;
p2 = y;
show[x][y] = '@';
(
p)++;
break;
}
else if (show[x][y] != '@' && show[x][y] != '*')
{
printf("抱歉,该坐标已扫查过,不是雷,请从新输入坐标n");
continue;
}
else
{
printf("抱歉,该坐标已经被标记过,请从新输入坐标\n");
continue;
}
}
else {
printf("坐标非法,请从新输入新的坐标\n");
continue;
}
}
color(7);
}

void cancle_flag(char* show, int p)
{
color(6);
int x = 0;
int y = 0;
if ((p) == 0)
{
printf("目前没有标记,无法进行取消标记\n");
return;
}
while (1)
{
printf("请输入需要取消标记的坐标\n");
scanf("%d%d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '@')
{
show[x][y] = '
';
(*p)--;
break;
}
else if (show[x][y] != '@')
{
printf("该坐标不为标记坐标,请重新输入新的坐标,\n请输入正确的标记坐标\n");
continue;
}
}
else
{
printf("坐标非法,请重新输入\n");
continue;
}
}
color(7);
}

void nume3()
{
color(6);
printf("--------是否需要标记---------\n");
printf("** 1. 标记 **\n");
printf("** 2.取消标记信息**\n");
printf("** else. ext **\n");
printf("** 共五次验证标记机会 \n");
printf("**
\n");
color(7);
}

void Findmine(char board, char show)
{
int x = 0;
int y = 0;
int count = 0;

int help_count = 5;
int count_check = 0;
int* p = &count_check;
int choice = 0;
while (count < row * col - mine_num)
{
again:
    nume3();
    scanf("%d", &choice);
    if (choice != 1 || choice != 2)
    {
        if (choice == 1)
        {
            int x = 0;
            int y = 0;
            set_flag(show, board, p, &x, &y);
            //system("cls");
            Displaymine(show);
            getchar();
            char ch;
            printf("是否需要提示该坐标是否为雷?Y/N\n");
            scanf("%c", &ch);
            if (ch == 'y' || ch == 'Y')
            {
                help_flag(board, x, y, &help_count);
            }
        }
        else if (choice == 2)
        {
            system("cls");
            Displaymine(show);
            cancle_flag(show, p);
            //system("cls");
            Displaymine(show);
        }
        getchar();
        char ch;
        printf("是否还要进行标记?Y/N\n");
        scanf("%c", &ch);
        if (ch == 'Y' || ch == 'y')
        {
            system("cls");
            goto again;
        }
    }
    //system("cls");
    Displaymine(show);
    printf("--------扫雷---------\n");
    printf("请输入要查找的坐标:\n");
    scanf("%d %d", &x, &y);
    if (x > 0 && x <= row && y > 0 && y <= col)//坐标合理
    {
        if (board[x][y] == '0')//第一次查找
        {
            if (show[x][y] == '*' || show[x][y] == '@')
            {
                if (show[x][y] == '@')
                {
                    (*p)--;
                }
                digui(board, show, x, y, &count);
                system("cls");
                Displaymine(show);
            }
            else
            {
                color(6);
                printf("该坐标已经查找过了,请在次输入新坐标:\n");
                color(7);
            }
        }
        else
        {
            system("cls");
            color(6);
            printf("很遗憾,你被雷炸死了\n");
            color(7);
            Displaymine(board);
            break;
        }
    }
    else
    {
        color(6);
        printf("输入的坐标不合理,请重新输入新的坐标:\n");
        color(7);
    }
    if (count == row * col - mine_num)
    {
        system("cls");
        color(6);
        printf("恭喜你,获胜了\n");
        color(7);
        Displaymine(board);
    }
}

}

test.c

define _CRT_SECURE_NO_WARNINGS

include"game.h"

int row = 0;//行
int col = 0;//列
int mine_num = 0;//雷的个数
void menu1()
{
printf("**\n");
printf(" 1 . play \n");
printf(" 0 . exit \n");
printf("**\n");
}
void menu2()
{
printf("*\n");
printf(" 1. esay \n");
printf(" 2. medium \n");
printf(" 3. difficulty \n");
printf(" easy-10个雷 \n");
printf(" medium-40个雷 \n");
printf(" difficulty-99个雷 \n");
printf("*\n");
}
void menu3()
{
printf("*\n");
printf(" 1. 扫雷 \n");
printf(" 2. 排查雷 \n");
printf("*\n");
}
void game()
{
int input = 0;
do
{
menu2();
scanf("%d", &input);

    switch (input)
    {
    case 1:
        row = 9, col = 9, mine_num = 10;
        break;
    case 2:
        row = 16, col = 16, mine_num = 40;
        break;
    case 3:
        row = 30, col = 16, mine_num = 99;
        break;
    default:
        printf("选择错误,请重新选择\n");
        break;
    }
} while (input != 1 && input != 2 && input != 3);
//创建棋盘
char** mine = (char**)malloc(sizeof(char*) * (row + 2));//存放每一行都首元素
char** show = (char**)malloc(sizeof(char*) * (row + 2));
int i = 0;
for (i = 0; i < row + 2; i++)
{
    //存放雷的信息
    mine[i] = (char*)malloc(sizeof(char) * (col + 2));
    //展示的棋盘,存放排雷的信息
    show[i] = (char*)malloc(sizeof(char) * (col + 2));
}

//初始化棋盘 11*11
Initboard(show, '*');

Initboard(mine, '0');
//0 不是雷   1是雷

//打印棋盘信息
//Displaymine(show);//9*9
//Displaymine(mine,ROW,COL);

//布置雷
Setmine(mine);
Displaymine(show);
//Displaymine(mine);
//Displaymine(mine, ROW, COL);
//扫雷
Findmine(mine, show);//传进去两个数组

}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do {
menu1();
scanf("%d", &input);
switch (input)
{
case 1:
printf("---------扫雷---------\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
break;
}
} while (input);
return 0;
}

game.h

define _CRT_SECURE_NO_WARNINGS

extern int row;//行数
extern int col;//列数
extern int mine_num;//类的个数

include

include

include

include

include

void Initboard(char** board, char set);

void Displaymine(char** board);//要避免与宏的名字重

void Setmine(char** board);

void Findmine(char board, char show);

void digui(char board, char show, int x, int y, int* count);

void set_flag(char show, char board, int p, int p1, int* p2);

void cancle_flag(char* show, int p);

void help_flag(char* board, int x,int y,int n);

那么就直接拜拜

目录
相关文章
|
存储 算法 语音技术
振南技术干货集:znFAT 硬刚日本的 FATFS 历险记(3)
振南技术干货集:znFAT 硬刚日本的 FATFS 历险记(3)
|
机器学习/深度学习 固态存储 安全
表情识别-情感分析-人脸识别(代码+教程)
表情识别-情感分析-人脸识别(代码+教程)
|
移动开发 前端开发 小程序
分享118个HTML公司企业模板,总有一款适合您
分享118个HTML公司企业模板,总有一款适合您
354 2
|
5月前
|
供应链 Python
如何开发ERP系统中的采购管理板块(附架构图+流程图+代码参考)
本文介绍如何在ERP系统中开发高效采购管理模块,涵盖采购申请、订单处理、入库与退货等关键流程,解析核心功能与业务逻辑,并提供代码参考及开发技巧,助力企业优化采购管理效率。
|
6月前
|
并行计算 PyTorch 算法框架/工具
OpenFold2.0 基于NPU的推理适配与测试
本教程详细介绍了 OpenFold 的环境搭建、代码部署、依赖安装、数据集准备及推理测试全流程。首先通过 Anaconda 创建 Python3.9 环境并配置相关库,接着克隆 OpenFold 代码仓库并安装必要依赖(如 PyTorch、dllogger、hhsuite 等)。随后准备 PDB 数据集与模型参数,调整脚本路径以适配运行环境。最后执行推理脚本完成测试,并针对常见报错提供了解决方案,例如更新 NumPy、SciPy 或调整 GPU 配置等,确保流程顺利运行。
|
7月前
|
开发框架 API 开发工具
HarmonyOS NEXT~鸿蒙系统与Uniapp跨平台开发实践指南
本书《HarmonyOS NEXT~鸿蒙系统与Uniapp跨平台开发实践指南》深入探讨了华为鸿蒙系统(HarmonyOS)与Uniapp框架的融合应用。书中首先介绍了鸿蒙系统的分布式架构特点及其原子化服务理念,随后详细讲解了Uniapp在鸿蒙环境下的适配方案,包括开发环境配置、特有配置项设置以及条件编译调用鸿蒙原生能力的方法。此外,还提供了界面适配策略、性能优化建议及调试发布流程,帮助开发者高效构建多端协同应用。最后展望了鸿蒙生态未来的发展方向,如ArkUI-X的深度集成和全新API能力的应用前景。
685 0
|
缓存 监控 Ubuntu
在Linux中,如何使用top、htop、vmstat等命令监控系统性能?
在Linux中,如何使用top、htop、vmstat等命令监控系统性能?
|
Android开发 iOS开发 UED
安卓与iOS的较量:谁才是智能手机市场的王者?
本文将深入探讨安卓和iOS两大智能手机操作系统之间的竞争关系,分析它们各自的优势和劣势。通过对比两者在市场份额、用户体验、应用生态等方面的表现,我们将揭示出谁才是真正的市场领导者。无论你是安卓粉丝还是iOS忠实用户,这篇文章都将为你提供一些有趣的观点和见解。
|
弹性计算 监控 网络协议
短连接服务部署
【9月更文挑战第20天】
246 2
|
Shell iOS开发 MacOS
入职必会-开发环境搭建04-IDEA激活
本方法是市面上最简单、方便的JetBrains全家桶激活方法,包含IDEA、PyCharm、CLion、DataGrip、GoLand、PhpStorm、WebStorm均可激活并且支持最新的2023版本。
321 0
入职必会-开发环境搭建04-IDEA激活