前言
大家好,今天我们来进行一个经典的游戏的代码实现——扫雷游戏的代码实现,Let's go !(感觉之前写的代码废话太多所以我就不说废话了直接进入正题)
目录
一.使用工具
二.扫雷游戏的简易介绍以及游戏设计思路
三.扫雷游戏的逻辑实现
3.1.菜单的打印
3.2.对于棋盘的实现
3.3.雷的布置
3.4.如何排查雷
四.扫雷游戏的高级版(对于这部分不感兴趣的可以跳过)
4.1如何对棋盘进行增加的实现
五.完整的代码实现
1.头文件展示
2.源文件展示
正文
一.使用工具
VS2022 |
二.扫雷游戏的简易介绍以及游戏设计思路
《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。 所以这个游戏想要实现就必须包含这几个步骤:
1.菜单的打印 2.棋盘的打印 3.对于雷的布置 4。如何进行雷的排查
对于没玩过此类游戏的读者朋友,目前大多数系统是不自带扫雷游戏了,所以我这里放个链接供各位读者进行试玩:扫雷游戏网页版 - Minesweeper
对于此类游戏的设计思路,首先我们可以用1来代表雷,0代表的是不是雷并且用二位数组来模拟实现,不过这里也出现了一个状况,我们知道扫完一个地方后会显示周围雷的个数,如果恰好是1那么我们就不知道是雷还是周围的个数了,所以针对这个情况,我们可以设计两个棋盘,其中一个棋盘仅仅代表的是展示出来让别人选的棋盘,可以用“*”来进行实现,所以说,我们在设置数组的时候会选择字符数组来进行实现,并且我们在筛选雷的时候一般是筛选周围九个的,以9 * 9棋盘为例,如果选择的是第一行的可能会出现越界现象,所以针对于这种情况,我们可以多加两行两列,从而避免出现指针越界这种情况,我们在之后打印的时候选择打印9 * 9就好了,当然雷的布置也会在9 * 9里面的,下面我们就进入主体部分喽
三.扫雷游戏的逻辑实现
3.1.菜单的打印
这个算是扫雷游戏最好实现的部分了,仅仅通过printf仅可实现,下面是代码的实现:
#include"game.h" //这个在后面会说什么会说是什么
void menu()
{
printf("**********扫雷游戏开始喽*********\n");
printf("*********************************\n");
printf("*******1.游玩********************\n");
printf("*******0.退出********************\n");
printf("*********************************\n");
printf("*********************************\n");
}
int main()
{
int i = 0;
srand((unsigned int)time(NULL)); //先设置雷的随机数
do
{
menu();
printf("请输入您想要进行的数字 :");
scanf("%d", &i);
switch (i)
{
case 1:
game();
break;
case 0:
printf("\n期待您的下次游玩");
break;
default:
printf("请您重新在进行选择:");
break;
}
} while (i);
}
为了不让一个主函数看起来很长,所以我们可以选择写一个函数来代表着菜单,从而减小主函数的负担,对于为什么头文件是game.h,我说一下,我为了让代码变得更容易可读,于是我把很多的内容放到了头文件里面,从而让代码变得不繁琐。
3.2.对于棋盘的实现
对于棋盘我们可以用二维字符数组来进行实现,为了让代码更灵活一点,我们可以采用define关键字来进行行和列的设置(这为后面高级版打下了基础):
这是设置行(ROW)和列(COL)数,这里可以让他们进行灵活的变换,下面来展示棋盘如何进行打印(这部分是关于数组的知识,我相信读者朋友们已经学过了):
我把代码分成了三份分成写,所以我就不用代码分别展示了不然显的不好看,第一个是代码的主题内容,第二个是主函数内对函数的调用,第三个是头文件对函数的声明,为了让棋盘代码写的数量减少,我在函数不仅仅有数组和行列,还加上了想把棋盘变成的内容,就比如我们因为还没设置雷,所以先用‘0’代替,棋盘的主体用‘*’表示,这样可以让代码的可读性和灵活性上升,减少代码量与文件的大小,下面来看看棋盘的效果 ,对了我缺少了打印的部分,下面附上
从图中可以清晰的看出棋盘打印出来的效果,对于旁边数字,是为了后续方便写坐标打印出来的,也可以不打印不过效果看着不会很好应该,下面我们继续深入,开始进行雷的布置
3.3.雷的布置
对于雷的布置,这时候我们就需要用到两个不算新的朋友,rand函数(生成随机数),srand(生成种子,搭配time可以实现随机种子),简易介绍一下,rand函数虽说生成的是随机数,不过把它可以认定为伪随机数,因为它生成随机数后就会固定下来,它会和srand函数搭配来进行使用,这个是生成种子来改变随机数,不过种子也是固定的,这时候可以用time(时间戳)来进行种子的随机,从而三者搭配到一起来进行真正的随机数,下面来展示它生成随机数以及雷布置完后的情况:
因为是9 * 9的棋盘,所以我们设置10个雷,同样也是用到了用define关键字,方便后续的操控,通过随机数组的坐标来放置雷,注意这个是字符型数组,所以是字符‘1’而不是单纯的1,直到count变为0雷就放完了,所以采用循环的过程,雷也放置完了,现在进入最后的部分,如何找雷
3.4.如何排查雷
对于雷的寻找,我们可以采用通过坐标的方式来进行排查类,这个时候就用到了循环的知识了,通过一直循环来进行排查雷,直到雷找到或者找完了才停止循环,具体的代码就放到了下面:
以上便是排查雷代码的具体实现,值得一提的是,我将字符与数字进行了转换,因为我们这个代码的整体是字符,所以要进行二者的转换,以上便是此代码的总实现逻辑,下面来说明一下高级版的实现逻辑(代码就不展现了太大了)
四.扫雷游戏的高级版
4.1.如何对棋盘进行增加的实现
小编之前就展示了define的灵活运用,我们可以通过对于define里面的数值进行更改从而可以做到棋盘的增加,并且有空闲时间的读者朋友可以尝试一下做一个可以选择版本的代码实现,具体内容我就不展开说了如果想要理解更多的我把资源放到文章开头了,我看到很多优秀的作者还想到了更多的优化(就比如如果周围都没有雷的话继续展开,这里用到了递归的思想,我递归还不太熟悉),所以读者朋友们也可以关注一下别人的代码如何进行书写,小编能力有限,我会将我会的尽全力教给你们!!!
五.完整的代码展示
1.头文件的展示(game.h)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define ROW 9
#define COL 9 //用define的时候不用加上分号
#define ROWS ROW+2
#define COLS COL+2
//先对函数进行实名
void my_qifanfuzhi(char arr[ROWS][COLS], int rows, int cols, char a); //形参与实参名字不要相同
void my_printqipai(char arr[ROWS][COLS], int row, int col);
#include<time.h>
#include<stdlib.h>
#define my_count 10
void my_fangzhilei(char arr[ROWS][COLS], int row, int col);
void my_zhaolei(char arr[ROWS][COLS],char show[ROWS][COLS], int row, int col);
2.源文件的展示(game.c,test.c)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"game.h"
void my_qifanfuzhi(char arr[ROWS][COLS], int rows, int cols, char a)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
arr[i][j] = a;
}
}
}
void my_printqipai(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
printf("-------扫雷--------\n");
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
int j = 0;
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
void my_fangzhilei(char arr[ROWS][COLS], int row, int col)
{
int count = my_count;
int i = 0;
int x = 0;
int y = 0;
while (count)
{
x = rand() % row +1; //先设置好1到9的随机数
y = rand() % col +1;
if (arr[x][y] != '1')
{
arr[x][y] = '1'; //因为是字符数组,所以在这里1也应该用字符表示
count--;
}
}
}
int geichutishi(char arr[ROWS][COLS], int x, int y)
{
int i = 0;
int count = 0;
for (i = -1; i <= 1; i++)
{
int j = 0;
for (j = -1; j <= 1; j++)
{
count = count + arr[x + i][y + j] - '0';
}
}
return count;
}
void my_zhaolei(char arr[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while (1) //因为一直找雷所以死循环就好了
{
printf("请输入您想要的坐标(温馨提示,输入的要用逗号隔开):");
scanf("%d ,%d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if (arr[x][y] == '1')
{
printf("很好,你成功找到了雷,在来一次吧");
my_printqipai(arr, ROW, COL);
break;
}
else
{
int c = geichutishi(arr, x, y);
show[x][y] = c + '0'; //转换成数字
my_printqipai(show, ROW, COL);
count++;
}
}
else
{
printf("您输错了请重新选择x,y(x在1到9,y在1到9)");
}
if (count == ROW * COL - my_count)
{
printf("恭喜你,成功排查出了所以的雷,真棒!");
break;
}
}
}
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
printf("**********扫雷游戏开始喽*********\n");
printf("*********************************\n");
printf("*******1.游玩********************\n");
printf("*******0.退出********************\n");
printf("*********************************\n");
printf("*********************************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//先对这个棋盘赋值
my_qifanfuzhi(mine, ROWS, COLS, '0');
my_qifanfuzhi(show, ROWS, COLS, '*');
//打印棋盘
//my_printqipai(mine, ROW, COL);
my_printqipai(show, ROW, COL);
//该要放置雷了
my_fangzhilei(mine,ROW,COL);
//my_printqipai(mine, ROW, COL);
//开始寻找雷
my_zhaolei(mine,show, ROW, COL);
}
int main()
{
int i = 0;
srand((unsigned int)time(NULL)); //先设置雷的随机数
do
{
menu();
printf("请输入您想要进行的数字 :");
scanf("%d", &i);
switch (i)
{
case 1:
game();
break;
case 0:
printf("\n期待您的下次游玩");
break;
default:
printf("请您重新在进行选择:");
break;
}
} while (i);
}
以上便是扫雷游戏的详细讲解,如果有写的不好的可以在评论区点出来,我会诚恳听取并且进行更正,如果觉着我写的好的话,希望可以收到您的点赞,您的点赞就是我写动力,那么,我们下一篇文章见咯~~~