C语言——基础版扫雷游戏实现的教程

一:游戏实现的思路:
第一步,首先是需要我们去创建一个菜单界面函数,用于选择退出游戏或者是进入游戏。
第二步,创建用于放置雷的棋盘,并进行棋盘初始化。
第三步,放入雷,并打印出雷的初始化棋盘
第四步,输入排查雷的坐标

第五步,反馈输入坐标的结果,之后循环,直到成功排查或被炸死

在扫雷的过程中,创建棋盘布置雷和排查雷都需要储存信息,所以我们需要一定的数据结构来存储这些信息,在布置雷时,如果是雷就放1,不是雷就放0;

同时为了让游戏具有一定的可玩性,便于修改游戏难度,那么们便在头文件中define行、列和雷的数量

#define number 10//雷的个数
#define ROW 9//棋盘显示的长宽
#define COL 9
#define ROWS ROW+2//设置的存储的棋盘的长宽
#define COLS COL+2
二:模块化代码实现
在这里插入图片描述
game.h//文件中玩游戏所需要的数据类型和函数声明
game.c//文件中玩游戏函数的实现
text.c//文件中玩游戏的测试逻辑
1:创建主函数main()
在主函数中调用函数test在调用函数中我们随机生成一个值同时我们创建一个n值,用于输入判断我们菜单的选择,用do while判断我们输入的选择是否结束,在这里我们需要创建菜单函数,每一次循环我们都调用菜单函数,接着使用switch语句中,来执行输入的结果,如果输入1则提示玩家开始游戏并调用游戏函数game(),输入0则退出游戏,输入其他数值则提示错误,并循环执行switch语句,直至玩家主动退出。
在这里插入图片描述
2:创建菜单函数:
因为只是在屏幕上打印出菜单不需要返回值所以使用void,菜单函数会在test()函数中被调用
在这里插入图片描述
三:创建游戏函数
1:棋盘的设置
假如我们需要创建9x9行的棋盘,当我们排查棋盘的边缘是否有雷时,此时他的搜查范围就是以他为中心的一个九官格,此时最下面的那一行就不在9x9行的棋盘内,这就导致了越界问题,比如这里,我们选择右下角的那一个空格,他就会导致越界。
在这里插入图片描述
所以,我们需要把棋盘的范围设置大一点,我们在9x9的棋盘内玩游戏,但我们需要创建一个11x11行的棋盘,这样才不会导致越界问题的出现。
在这里插入图片描述
假设我们现在已经布置好了雷(雷用1表示,不是雷用0表示),当我们搜查一个坐标的时候,如果这个坐标周围有一个雷,那么我们需要将这个雷的数量信息记录并存储下来,同时打印给玩家,但是我们存放雷的数组里面已经有数据了,如果再存放在里面就会可能产生混淆从而导致棋盘混乱打印困难,所以我们可以设置两个棋盘,一个是雷的棋盘mine,一个是用于放置雷的信息的棋盘show,我们后面会把雷布置到到mine数组里面,再mine数组排查雷之后,将雷的信息存放到show数组里面,然后打印show数组的信息给用户参考排查,这样就不会存在数据混淆了。

在这里插入图片描述:2:初始化棋盘
棋盘设置好之后呢,我们就该对棋盘进行初始化,让用于雷的棋盘数组mine中先全是无雷信息,全部初始化为字符‘0’;显示给用户看的棋盘数组show初始化字符全部为‘’,这样可以让用户不知道下面的信息,从而保持游戏的可玩性。同时,为了报证两个数组类型的一致,我们使用同一套函数对这两个数组进行初始化处理。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3:打印棋盘
那么我们该如何打印呢,首先要传给函数的参数是mine数组、行和列,在进入函数之后我们为了让在棋盘的周围显示行与列,首先从零开始循环打印小于等于列号的数,打印完之后开始打印棋盘,在打印每一行开始之前呢,还是先打印行号再接着打印mine数组的每一行,那么最终代码的实现就如下所示
在这里插入图片描述
4:现在就是步雷了:
现在我们棋盘初始化完成了,但是mine里面全是‘0’,没有雷的信息,所以现在我们需要往数组mine里面放入雷的信息,那么我们该如何放置呢?现在让我们来理一下思路,我们要在一个9×9的棋盘范围大小,一共81个坐标里面放置10个雷,为了保证游戏的可玩性,所以我们放置的这十个雷应该是随机的,是随机布置在这81个坐标中的任意10个。所以我们要使用srand函数
在这里插入图片描述
随机数生成之后,它的范围是无法固定的,但是我们布置雷只需要在9×9棋盘上布置,那么我们就可以将这个生成的数%棋盘的长宽然后+1,比如当前棋盘长宽为9,那么用生成的随机数%9得到的数字就是0-8,在+1就是1-9,而一到九就是我们所需要布置棋盘雷的坐标,代码如下
在这里插入图片描述
现在雷的坐标范围已经确定了。接下来就是布置雷了,假设我们要步10个雷,我们首先int count = number;而number已经在头文件game.h中声明过了然后使用while循环,以count为条件,每次成功布置好一个雷之后,count–,当雷全部布置完成后count==0,while循环结束。在while循环里面我们使用if语句来判断当前位置是否为雷,不是则布置雷,布置好count自减,如此循环,雷就布置好啦!下面是布置好的例子与代码。
在这里插入图片描述
在这里插入图片描述
5:排查雷:
雷布置好之后我们就需要玩家输入坐标排查雷并将排查后的棋盘显示给玩家,那么当输入一个坐标之后该如何排查呢,首先就是创建一个排雷函数,用于接收有雷的棋盘和用于显示的棋盘,开始我们先定义x,y作为排查坐标,此处的count是可排查的次数,当我们如果将无雷区域全部排查出来之后我们该如何结束呢,所以我们使用while循环,条件是add < rowcol - mine即count<行列-雷的数量,每次成功排雷后,add++,当count < row*col - mine不成立时while循环结束,执行if语句,如果add == row * col - mine,即排雷成功。当然,前提是我们查找的坐标在棋盘内。
在这里插入图片描述
这里,如果我们查找的坐标不是雷的话,我们想知道该坐标附近有多少个雷,此时就需要调用函数实现功能
在这里插入图片描述
因为棋盘内为字符1的就是雷,字符0的就不是雷,而字符1比字符0的ascll码只多了1,所以如果此坐标显示2的话,就表示周边有2个雷。
完整代码如下:
game.h内的代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE 10
void intiboard(char arr[ROWS][COLS], int rows, int cols, char set);
void setmine(char arr[ROWS][COLS], int row, int col);
void displayboard(char arr[ROWS][COLS], int row, int col);
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c内的代码
#include"game.h"
void intiboard(char arr[ROWS][COLS], int rows, int cols, char set)
{
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
//打印棋盘
void displayboard(char arr[ROWS][COLS],int row, int col)
{
printf(“扫雷游戏\n”);
int i;
for (i = 0; i <= row; i++)
{
printf(“%d “, i);
}
printf(”\n”);
for (i = 1; i <= row; i++)
{
printf(“%d “, i);
int j;
for (j = 1; j <= col; j++)
{
printf(”%c “, arr[i][j]);
}
printf(”\n”);
}
}
void setmine(char arr[ROWS][COLS], int row, int col)
{
int count = MINE;
while (count)
{
int x = rand() % 9 + 1;//棋盘x的坐标,生成的随机数%9后0-8,加一后为0-9
int y = rand() % 9 + 1;//棋盘y的坐标,生成的随机数%9后0-8,加一后为0-9
if (arr[x][y] = ‘0’)
{
arr[x][y] = ‘1’;
count–;
}
}
}
int getminecount(char mine[ROWS][COLS], int x, int y)
{

 return mine[x - 1][y] + mine[x + 1][y] + mine[x - 1][y - 1] +
		 mine[x][y - 1] + mine[x + 1][y - 1] +
		 mine[x - 1][y + 1] + mine[x][y + 1] +
		 mine[x + 1][y + 1] - 8 * '0';

}
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x, y;
int add = 0;
while (add <= row * col - MINE)
{
printf(“请输入一个坐标”);
scanf(“%d%d”, &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == ‘1’)
{
printf(“很遗憾,你踩到雷了\n”);
displayboard(mine, ROW, COL);
break;
}
else
{
int count = getminecount(mine, x, y);//找出该坐标附件有多少个雷
show[x][y] = count + ‘0’;
displayboard(show, ROW, COL);
add++;
}
}
else
{
printf(“该坐标非法,不在范围内\n”);
break;
}
if (add == row * col - MINE)
{
printf(“成功通关”);
displayboard(mine, ROW, COL);
}
}
}
test.c内的代码
#include"game.h"
void menu()
{
printf(“* * * * * * * * * * * * \n");
printf("
* * 1:play * * \n");
printf("
* * 0:exit * * \n");
printf("
* * 其他数字:选择错误 * * \n");
printf("
* * * * * * * * * * \n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
intiboard(mine, ROWS, COLS, ‘0’);
//intiboard(show, ROWS, COLS, '
');
setmine(mine, ROW, COL);
displayboard(mine, ROW, COL);
displayboard(show, ROW, COL);
findmine(mine, show, ROW, COL);
}
void test()
{
int n;
srand((unsigned int)time(NULL));//生成一个随机数,time函数无参返回,返回类型强制转为unsigned int
do {
menu();
scanf(”%d", &n);
switch (n)
{
case 1:
game();
break;
case 0:
printf(“退出游戏”);
break;
default:
printf(“请重新选择”);
break;
}
} while (n);
}
int main()
{
test();
return 0;
}
这里,我们所有的头文件都在game.h里面,所以我们在game.c和text.c里引用头文件时只要引用#include"game.h",就可以引用game.c里的所有头文件了。
这里只是基础版的扫雷,说明过程中可能有一些问题,或者遗落的地方,请大家多多海涵,大家也可以利用我上述的代码自己实现一遍,这样比较好理解。感谢大家支持哦!!!

  • 49
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值