前言
扫雷是一款经典的小游戏,那么如何使用C语言来写一个简单的扫雷呢?
先说思路
1.获取一个游戏版数组,之后进行初始化。
2.写一个打印游戏板的函数,在之后的游戏中都会用到
3.有了游戏板,接下来只需要放置雷。
4.排查雷,游戏过程中都是需要持续的排查出非雷的空格区域。
好了既然有了思路,接下来只需要将思路用代码的方式运行起来。
零.游戏本体的制作
无论是什么游戏,都需要主页,这个主页决定了一个游戏是否开始,所以也是必不可少的。
那么在c语言中如何制作一个简单的游戏主页呢?
其实之前发的猜数字就讲过。那还是用那种方法来吧。
int main ()
{
int n = 0;
do
{
menu();
printf(" 输入数字后按回车选择: ");
scanf_s("%d", &n);
if (n == 1)
{
printf("\a游戏开始\n");
game();
}
else if (n == 0)
{
printf("\a正在退出游戏....");
}
} while (n);
return 0;
}
这里用了一个do while 循环,使这个游戏能够有一个循环开始的功能,可以多次游玩体验。
其中的menu函数是主页了,其中的game函数就是待会讲的游戏本体了。
1.创建函数主页
void menu() {
printf("|-----------------------------|\n");
printf("| |\n");
printf("| 1.开始 |\n");
printf("| |\n");
printf("| 0.退出 |\n");
printf("| |\n");
printf("|_____________________________|\n");
}
Menu是一个表示可选项列表的用户界面,通常由一组垂直或水平排列的选项组成。用户可以通过选择菜单中的选项来执行相关的操作或导航到其他部分或页面。菜单通常与按钮、链接或其他用户交互元素相结合,可以在应用程序、网站或操作系统中找到。菜单也可以是文本或图形形式的,具体取决于使用场景和设计需求
利用这个自定义的函数,可以写一个主页出来。记得不要少了什么符号,以及这个函数一定要写在main函数的上面,编译时,数据从上向下读取,先读取上面的代码,一条一条向下读取,如果写在下面,那么在读取main函数主体时,就无法识别这个menu函数了,编译器自然就会报错了。
2.创建游戏主体
game()
{
/*初始化棋盘*/
/*打印棋盘*/
//布置雷
//排查雷
}
这里利用之前的构思,可以先写出这样一个构思,一步一步来。
一.获取一个游戏板数组,之后进行初始化
在创建游戏板之前先声明一下
#include<stdio.h>
#include<stdlib.h>
#define HANG 9
#define LIE 9
#define HANGS HANG+2
#define LIES LIE+2
这里先是声明好要使用的库函数。
库函数是什么?
库函数,也称为函数库或库例程,是一组已编写好的可重复使用的程序代码,它们为程序员提供了一组预构建的功能,以便在编写程序时使用。库函数能够大大提升程序员的工作效率,因为它们能够让程序员避免编写重复的代码,而是直接使用已经编写好的功能。
然后再定义一下游戏中经常用到的棋盘大小的数据行HANG和列LIE
因为还要进行判定旁边雷的个数,所以就要在旁边一圈进行判断,为了防止越界访问,所以在创建数组时多创建一格子
![](https://i-blog.csdnimg.cn/blog_migrate/f41acb9089b40b08db254e8820aaf427.png)
在C语言中,可以使用以下语法定义数组:
<数据类型> <数组名>[<数组大小>];
其中,数据类型是数组中元素的数据类型,数组名是数组的标识符,数组大小是数组元素的数量。
例如,要定义一个包含5个整数的数组,可以使用以下语句:
int arr[5];
这将定义一个名称为arr的整数数组,它包含5个元素。可以使用如下语句访问数组中的元素:
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
接下来,就可以创建二维数组了
game()
{
char zhupan[HANGS][LIES];
char fupan[HANGS][LIES];
/*初始化棋盘*/
/*打印棋盘*/
//布置雷
//排查雷
}
这里创建了两个数组进行存放后面游戏板的内容。
void Qipan(char qipan[HANGS][LIES], int lies, int hangs, char set)
{
int i = 0;
for (int i = 0; i < hangs; i++)
{
int j = 0;
for (int j = 0; j < lies; j++)
{
qipan[i][j] = set;
}
}
这里是先对函数进行了一个创建利用循环来初始化棋盘,而使用set来调用这个函数时就可以选择是空白还是雷。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define HANG 9
#define LIE 9
#define HANGS HANG+2
#define LIES LIE+2
void Qipan(char qipan[HANGS][LIES], int lies, int hangs, char set)
{
int i = 0;
for (int i = 0; i < hangs; i++)
{
int j = 0;
for (int j = 0; j < lies; j++)
{
qipan[i][j] = set;
}
}
void menu() {
printf("|-----------------------------|\n");
printf("| |\n");
printf("| 1.开始 |\n");
printf("| |\n");
printf("| 0.退出 |\n");
printf("| |\n");
printf("|_____________________________|\n");
}
game()
{
char zhupan[HANGS][LIES];
char fupan[HANGS][LIES];
/*初始化棋盘*/
Qipan(zhupan, HANGS, LIES, '0');
Qipan(fupan, HANGS, LIES, '*');
/*打印棋盘*/
//布置雷
//排查雷
}
int main()
{
int n = 0;
do
{
menu();
printf(" 输入数字后按回车选择: ");
scanf_s("%d", &n);
if (n == 1)
{
printf("\a游戏开始\n");
game();
}
else if (n == 0)
{
printf("\a正在退出游戏....");
}
} while (n);
return 0;
}
这里放出现在的全代码
二.打印棋盘
现在有了棋盘的数组接下来,将这个数组打印出来
game()
{
char zhupan[HANGS][LIES];
char fupan[HANGS][LIES];
/*初始化棋盘*/
Qipan(zhupan, HANGS, LIES, '0');
Qipan(fupan, HANGS, LIES, '*');
/*打印棋盘*/
Dayinqipan(fupan, HANG, LIE);
//布置雷
//排查雷
}
void Dayinqipan(char qipan[HANGS][LIES], int hang, int lie)
{
int i = 0;
printf("------------------------------\n");
for (i = 0; i <= hang; i++)
{
printf(" %d ", i);
}
printf("\n");
for (int i = 1; i <= hang; i++)
{
printf(" %d ", i);
int j = 0;
for (j = 1; j <= lie; j++)
printf(" %c ", qipan[i][j]);
printf("\n");
}
printf("-------------------------------\n");
}
创建一个函数
使用这个函数可以进行调用时就打印棋盘,并结合后面的函数实时更新棋盘。
这段代码是一个打印棋盘的函数Dayinqipan,它接受两个参数:二维字符数组qipan表示棋盘,int类型的hang和lie表示棋盘的行数和列数。该函数会在屏幕上打印出整个棋盘的状态。
具体来说,该函数首先打印出一行数字,从0到hang,表示列号。然后对于每一行i(从1到hang),先打印出行号i,然后依次打印出该行每一个位置上的字符。最后再打印一行数字,表示列号。
三.布置雷
这里新定义一个函数用于布置雷
雷的位置需要是随机的
首先我们就要做到每次都是随机的数,那么如何在c语言做到随机数呢?
int a=rand();
在C语言中,rand函数获取的随机数范围是0到RAND_MAX之间的整数,其中RAND_MAX是一个常量,它通常定义在stdlib.h头文件中,它代表了rand函数能够生成的最大随机数。具体数值可以通过调用srand函数来设置随机数种子,从而影响rand函数返回的随机数序列。
如果需要在指定范围内生成随机数,可以通过取余和加法等方式实现。
我们都知道,时间是不断在变化的,那么可以利用这一点,将函数time使用到我们的代码中,time函数在使用中需要 #include<time.h> 头文件
int random_num = rand() % 100 + 1;
// 获取1到100之间的随机整数
将这个写在开头的主函数里就可以了
这里需要定义雷的数量,为了方便以后看,就宏定义一个在开头处了#define JIANDAN 10
void Buzhilei(char zhupan[HANGS][LIES], int hang, int lie)
{
int jiandan = JIANDAN;
while (jiandan)
{
int x = rand() % hang + 1;
int y = rand() % lie + 1;
if (zhupan[x][y] == '0')
{
zhupan[x][y] = '1';
jiandan--;
}
}
}
这段代码是一个随机生成雷的函数Buzhilei,它接受三个参数:二维字符数组zhupan表示雷区,int类型的hang和lie表示雷区的行数和列数。
函数中使用了一个while循环,条件为jiandan为10,即还有需要生成的雷。在循环内部,使用rand()函数生成两个随机数x和y,分别表示雷的位置。然后判断zhupan[x][y]是否为\'0\',即该位置是否已经有雷。如果没有,则将该位置标记为\'1\'表示有雷,并将jiandan减一。如果已经有雷,则重新生成随机数直到找到一个空位。
四.排查雷
定义一个函数用于排查雷
static int Xianshileishu(char zhupan[HANGS][LIES], int x, int y)
{
return (zhupan[x - 1][y] +
zhupan[x - 1][y - 1] +
zhupan
[x][y - 1] +
zhupan[x + 1][y - 1] +
zhupan[x + 1][y] +
zhupan[x + 1][y + 1] +
zhupan[x][y + 1] +
zhupan[x - 1][y + 1] - 8 * '0');
}
void Paichalei(char zhupan[HANGS][LIES], char fupan[HANGS][LIES], int hang, int lie)
{
int x = 0;
int y = 0;
int win = 0;
while (win < hang * lie - JIANDAN)
{
printf("请输入要排查的坐标: ");
scanf_s("%d %d", &x, &y);
if (x >= 1 && x <= hang && y >= 1 && y <= lie)
{
if (zhupan[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
Dayinqipan(zhupan, HANG, LIE);
break;
}
else
{
int count = Xianshileishu(zhupan, x, y);
fupan[x][y] = count + '0';
Dayinqipan(fupan, HANG, LIE);
win++;
}
}
else
{
printf("坐标非法,重新输入\n");
}
}
if (win == hang * lie - JIANDAN)
{
printf("恭喜你,排雷成功\n");
Dayinqipan(zhupan, HANG, LIE);
}
}
函数计算给定坐标周围的雷数。该函数接收一个二维字符数组作为参数,表示雷盘的状态。函数中通过将字符转换为整数来计算雷数,是为了减去字符转换为整数的偏移量。Xianshileishu
(x, y)
zhupan
-8 * '0'
函数是排雷函数,用于进行扫雷操作。它接收两个二维字符数组和作为参数,分别表示雷盘和覆盖雷盘的状态。和表示雷盘的行数和列数。变量用于记录成功排除的雷数。Paichalei
zhupan
fupan
hang
lie
win
函数通过一个循环,从用户获取输入的坐标,并进行合法性检查。如果输入的坐标非法,会打印错误提示信息。如果输入的坐标合法,会根据雷盘状态进行判断。(x, y)
如果坐标上是雷(值为字符),则游戏失败,会打印失败信息,并将完整的雷盘状态通过函数打印出来。然后跳出循环。(x, y)
'1'
Dayinqipan
如果坐标上不是雷,通过调用函数计算出周围的雷数,并更新覆盖雷盘状态。然后打印覆盖雷盘状态,并将成功排除的雷数加一。(x, y)
Xianshileishu
fupan
最后,判断成功排除的雷数是否等于雷盘上的雷数减去一个预设的常量。如果相等,则说明所有雷都已排除,打印成功信息,并将完整的雷盘状态通过函数打印出来。
五.源码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define HANG 9
#define LIE 9
#define HANGS HANG+2
#define LIES LIE+2
#define JIANDAN 10
void Qipan(char qipan[HANGS][LIES], int lies, int hangs, char set);
void Dayinqipan(char qipan[HANGS][LIES], int hangs, int lies);
void Buzhilei(char zhupan[HANGS][LIES], int hang, int lie);
void Paichalei(char zhupan[HANGS][LIES], char fupan[HANGS][LIES], int hang, int lie);
void menu() {
printf("|-----------------------------|\n");
printf("| |\n");
printf("| 1.开始 |\n");
printf("| |\n");
printf("| 0.退出 |\n");
printf("| |\n");
printf("|_____________________________|\n");
}
game()
{
char zhupan[HANGS][LIES];
char fupan[HANGS][LIES];
/*初始化棋盘*/
Qipan(zhupan, HANGS, LIES, '0');
Qipan(fupan, HANGS, LIES, '*');
/*打印棋盘*/
Dayinqipan(fupan, HANG, LIE);
/*Dayinqipan(fupan, HANG, LIE);*/
//布置雷
Buzhilei(zhupan, HANG, LIE);
//排查雷
Paichalei(zhupan, fupan, HANG, LIE);
}
int main()
{
srand((unsigned int)time(NULL));
int n = 0;
do
{
menu();
printf(" 输入数字后按回车选择: ");
scanf_s("%d", &n);
if (n == 1)
{
Sleep(500);
printf("\a游戏开始\n");
system("cls");
game();
}
else if (n == 0)
{
Sleep(500);
printf("\a正在退出游戏....");
}
} while (n);
return 0;
}
void Qipan(char qipan[HANGS][LIES], int hangs, int lies, char set)
{
int i = 0;
for (int i = 0; i < hangs; i++)
{
int j = 0;
for (int j = 0; j < lies; j++)
{
qipan[i][j] = set;
}
}
}
void daojishi()
{
int timedaojishi = 5000;
while (timedaojishi > 0)
{
timedaojishi -= 1000;
printf("\r%2d", timedaojishi / 1000);
Sleep(1000);
}
printf("\n");
}
void Dayinqipan(char qipan[HANGS][LIES], int hang, int lie)
{
system("cls");
int i = 0;
printf("------------------------------\n");
for (i = 0; i <= hang; i++)
{
printf(" %d ", i);
}
printf("\n");
for (int i = 1; i <= hang; i++)
{
printf(" %d ", i);
int j = 0;
for (j = 1; j <= lie; j++)
printf(" %c ", qipan[i][j]);
printf("\n");
}
printf("-------------------------------\n");
printf("5秒");
daojishi();
}
void Buzhilei(char zhupan[HANGS][LIES], int hang, int lie)
{
int jiandan = JIANDAN;
while (jiandan)
{
int x = rand() % hang + 1;
int y = rand() % lie + 1;
if (zhupan[x][y] == '0')
{
zhupan[x][y] = '1';
jiandan--;
}
}
}
static int Xianshileishu(char zhupan[HANGS][LIES], int x, int y)
{
return (zhupan[x - 1][y] +
zhupan[x - 1][y - 1] +
zhupan
[x][y - 1] +
zhupan[x + 1][y - 1] +
zhupan[x + 1][y] +
zhupan[x + 1][y + 1] +
zhupan[x][y + 1] +
zhupan[x - 1][y + 1] - 8 * '0');
}
void Paichalei(char zhupan[HANGS][LIES], char fupan[HANGS][LIES], int hang, int lie)
{
int x = 0;
int y = 0;
int win = 0;
while (win < hang * lie - JIANDAN)
{
printf("请输入要排查的坐标: ");
scanf_s("%d %d", &x, &y);
if (x >= 1 && x <= hang && y >= 1 && y <= lie)
{
if (fupan[x][y] != '*')
{
printf("已经排查过了,请重新输入!\n");
}
else if (zhupan[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
Dayinqipan(zhupan, HANG, LIE);
break;
}
else
{
int count = Xianshileishu(zhupan, x, y);
fupan[x][y] = count + '0';
Dayinqipan(fupan, HANG, LIE);
win++;
}
}
else
{
printf("坐标非法,重新输入\n");
}
}
if (win == hang * lie - JIANDAN)
{
printf("恭喜你,排雷成功\n");
Dayinqipan(zhupan, HANG, LIE);
}
}
这是一个完整的实现了扫雷游戏逻辑的代码。你可以在主函数 main 中运行该程序,并通过菜单选择开始游戏或退出游戏。开始游戏后,将开始一个无限循环,在循环中处理用户的输入并进行游戏过程。游戏板使用二维字符数组表示,包括主游戏板 zhupan 和隐藏板 fupan。Qipan 函数用于初始化游戏板,Buzhilei 函数在游戏板上随机放置地雷,Paichalei 函数用于揭开方块并判断游戏胜负。Dayinqipan 函数用于在控制台上显示游戏板状态。menu 函数用于显示游戏菜单并处理用户输入的选择。daojishi 函数实现了一个倒计时计时器。
同样你也可以自己添加功能
这样一个简单的扫雷就完成了,制作不易,求个赞!!