摘要:目录前言游戏实现函数的实现游戏相关规则说明的函数棋盘初始化函数的实现随机生成雷的函数的实现打印数组函数的实现修改数组的函数的实现扫雷过程函数的实现修改数组的函数的实现汇总结语前言相信大家小时候都玩过扫雷小游戏吧在网络并
相信大家小时候都玩过扫雷小游戏吧?
在网络并不发达的时代,windows系统自动的扫雷小游戏便成为了不少人童年的回忆。
今天就让我们就用C语言来实现简易版的扫雷小游戏吧!
我们实现的思路如下:
1.程序开始时打印菜单,让玩家选择开始游戏还是退出游戏
2.玩家选择游戏后进入游戏
3.判断输赢后,重新回到菜单
同上一次三子棋小游戏的实现一样,我们先创建三个不同的文件,以便于代码的管理和维护。
test.c 用于游戏整体框架的实现
game.c 用于游戏相关函数的实现
game.h 用于游戏相关函数的声明
如果没有看过三子棋小游戏的同学们,可以点击下方链接跳转哦~
该文件为为main函数的实现,是程序的入口
我们通过菜单选项,可以选择开始游戏还是退出游戏
为了能够在switch语句的case中能够直观的看到不同的选项应该对应哪些函数,我们定义了一个枚举变量来一一对应选项
do-while语句,可以实现程序开始执行就打印一次菜单,让玩家可以选择
while中的条件判断,我们可以放入玩家选择的结果,如果为0就退出循环了,如果为非0就再打印一次菜单
srand函数的调用是用来设置随机数生成的起点,以便于后续调用rand函数来随机设置雷的位置
//test.c//包含头文件,实现game.c中函数的调用#include"game.h"//定义枚举变量,对应菜单的选项enum Choose{ EXIT, PLAY};int main(){ int input = 0; srand((unsigned int)time(NULL));//利用时间戳,设置随机数生成起点 //游戏相关规则的说明 howtoplay(); //程序开始就执行一次,让玩家可以进行选择 do { menu();//调用菜单函数 scanf("%d", &input); switch (input)//对应玩家的选择,并做出判断 { case PLAY: game();//选择了玩游戏后,调用game函数来进行游戏 break; case EXIT: printf("退出游戏/n"); break; default: printf("选择有误,请重新选择/n"); break; } } while (input);//当input为0时,退出循坏,结束程序;当input为非0时,可以重新让玩家选择 return 0;}
该文件用来实现game函数中所调用的所有与游戏有关的函数
大致思路如下:
1.创建两个二维数组,一个(mine)用来记录雷的位置,一个(show)用于打印给玩家看
2.初始化两个二维数组
3.在mine数组中根据事先确定好的难度来设置雷
4.打印show数组与方便玩家看对应着看的坐标轴
5.玩家输入坐标来进行扫雷
6.判断玩家的选择,如果选中了雷就提示玩家:被炸死了;否则,在玩家所选的那一个位置中打印以那一个位置为中心的九宫格的雷的个数
创建数组选择大小时,我们不要直接写大小,免得写死了,后续修改二维数组大小的时候不方便
我们可以在后面的game.h中通过define来定义二维数组行与列的大小
注意!!
这里我们创建的数组大小时11×11,而不是9×9的
这是因为,如果我们选择的是边上的位置,我们在遍历以该位置为中心的九宫格时,会因为数组越界而程序报错
所以我们在二维数组中在扩大一圈,并且全部初始化,避免后续遍历九宫格时候会造成越界
但是我们在打印数组时候,是不会打印外圈的
game函数主要是按照一定的顺序调用各个相关的函数来实现整个游戏过程
void game(){ //创建两个二维数组 //mine数组用于记录雷的位置 //show数组用于打印显示 char mine[ROWS][COLS]; char show[ROWS][COLS]; //初始化二维数组函数 //mine数组传参为‘0’ //show数组传参为‘*’ Initboard(mine, ROWS, COLS,"0"); Initboard(show, ROWS, COLS,"*"); //根据难度,在mine数组中随机设置雷的位置 Setmine1(mine,show,ROWS,COLS); //Setmine(show, ROW, COL); //打印show数组 //Printmine(mine, ROW, COL); Printmine(show, ROW, COL); //扫雷函数 Findmine(mine,show, ROW, COL);}
该函数用于在程序的最开始打印游戏相关规则
//游戏说明void howtoplay(){ printf("-------------------------------------------------------------------------/n"); printf("1.玩家需用键盘输入进行选择 /n"); printf("2.输入坐标时需要输入数字并按回车/n"); printf("3.第一次选择行,第二次选择列/n"); printf("4.左侧和上方的顺序数字是让玩家知道是哪一行那一列的/n"); printf("5.如果选择的位置安全,则会在该位置打印出其周围八个格雷的数目/n"); printf("6.当前版本并不能选择一次就展开一片,只能一个一个选择没有雷的位置/n"); printf("7.当所有安全的位置被玩家找出,就赢得游戏/n"); printf("8.当前难度为简单,一共有9个雷/n"); printf("--------------------------------------------------------------------------/n"); printf("/n");}
为了能够初始化两个数组,我们就在函数内规定初始化的元素了,想要初始化成什么元素就直接传参给该函数即可
//初始化函数//根据传参来初始化二位数组void Initboard(char mine[ROWS][COLS], int rows ,int cols,char ch){ int i = 0; for (i = 0;i < rows;i++) { int j = 0; for (j = 0; j <cols; j++) { mine[i][j] = ch; } }}
我们把mine数组传给该函数,通过随机生成坐标的方式来实现雷的放置
注意!!
这里形参row和col是按照游戏中二维数组的大小来传参的
并不是按照大了一圈的大小来传参
因为我们在放置雷的时候,只需要把雷放在实际大小(该版本为9×9)的二维数组中即可
外围那一圈是不需要放置的
否则在后续遍历九宫格的时候就会出错
这里我设置字符1为雷,原来的字符0为安全
void Setmine1(char mine[ROWS][COLS],int row, int col){ int count = SIMPLE_MODE; while (count) { int i = rand()%9 + 1; int j = rand()%9 + 1; if (mine[i][j] == "0") { mine[i][j] = "1"; count--; } }}
//打印函数//用于打印show数组,并打印行与列的坐标,方便玩家选择void Printmine(char board[ROWS][COLS], int row, int col){ int i = 0; printf("/n"); printf(" ");//让列的坐标数字能够与下面的*对齐 for (i = 1; i <= col; i++) { if (i <= 9) printf("%d ", i);//当坐标数为个位数的时候,多一个空格占位置 else printf("%d ", i);//当坐标数为两位数的时候,少一个空格占位置 } printf("/n"); printf(" ");//让列的坐标数下面的分割线与下面的*对齐 for (i = 1; i <= col; i++) { printf("---");//个位数+两个空格或者两位数+一个空格,所以这里用三个短横线来对齐 } printf("/n"); for (i = 1; i <= row; i++) { int j = 0; if (i <= 9) printf("%d |", i);//个位数的行坐标数用两个空格对齐 else printf("%d |", i);//两位数的行坐标数用一个空格对齐 for (j = 1; j <= col; j++) { printf("%c ", board[i][j]);//用一个字符+两个短横线来对齐上面的三短横线 } printf("/n"); } printf("/n"); printf("/n");}
void Setmine2(char show[ROWS][COLS], int x, int y, int ret){ show[x][y] = ret + "0";}
//扫雷函数void Findmine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col){ int x = 0; int y = 0; int count = 0;//用来记录九宫格雷的个数 int amount = row * col - SIMPLE_MODE;//用来记录没有放雷的安全位置的个数 while (1) { printf("请输入坐标:>/n"); scanf("%d %d", &x, &y); //if语句用于判断玩家输入的坐标是否正确 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x][y] == "1") { printf("/n"); printf("很遗憾,你被炸死了/n"); printf("/n"); return;//被炸死了就直接返回,退出该函数了 } else { //else也要判断该位置是没有选过的‘0’的位置 //还是已经选过的并改为‘#’的位置 if (mine[x][y] == "0") { mine[x][y] = "#";//把字符0改为‘#’,方便后续判断该位置是否重复选择 amount--;//安全位置的个数减一,当减到零的时候,玩家还没有因为被炸死而退出 //则说明玩家已经排雷完成 //定义新坐标,为以玩家选择的坐标为中心的九宫格的左上角, //用于遍历数组来统计九宫格雷的数量 int i = x - 1; int j = y - 1; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++) { if (mine[i][j] == "1") { count++;//用来记录九宫格雷的个数 } } } Setmine2(show, x, y, count);//将返回的九宫格的雷的个数来修改show数组 //让玩家选择的位置可以显示出周围有多少雷 count = 0;//每次修改成功后都要重置为0,否则数量会累加 Printmine(show, ROW, COL);//把修改过的show数组打印出来 if (!amount)//当amount为0时,说明玩家扫雷成功,返回退出函数 { printf("恭喜你扫雷成功!/n"); printf("/n"); return; } } else if (mine[x][y] == "#") { printf("该位置已排查过,请重新选择/n"); } } } else { printf("/n"); printf("输入有误,请重新输入:>/n");//如果玩家输入坐标有误,会让玩家重新选择 printf("/n"); } }}
通过遍历九宫格后返回的数字,来把show函数中对应位置的字符0修改为对应数字的字符形式,以便玩家知道周围的雷的个数,因为打印函数里面用的是%c的字符形式,所以要把数字转变为字符的格式
void Setmine2(char show[ROWS][COLS], int x, int y, int ret){ show[x][y] = ret + "0";}
让我们对上述代码进行汇总吧,想要体验一下的小伙伴们可以直接拷贝下面的代码即可
#include"game.h"//游戏说明void howtoplay(){ printf("-------------------------------------------------------------------------/n"); printf("1.玩家需用键盘输入进行选择 /n"); printf("2.输入坐标时需要输入数字并按回车/n"); printf("3.第一次选择行,第二次选择列/n"); printf("4.左侧和上方的顺序数字是让玩家知道是哪一行那一列的/n"); printf("5.如果选择的位置安全,则会在该位置打印出其周围八个格雷的数目/n"); printf("6.当前版本并不能选择一次就展开一片,只能一个一个选择没有雷的位置/n"); printf("7.当所有安全的位置被玩家找出,就赢得游戏/n"); printf("8.当前难度为简单,一共有9个雷/n"); printf("--------------------------------------------------------------------------/n"); printf("/n");}//菜单函数void menu(){ printf("***************************/n"); printf("******* 1. play *******/n"); printf("******* 0. exit *******/n"); printf("***************************/n"); printf("/n");}//初始化函数//根据传参来初始化二位数组void Initboard(char mine[ROWS][COLS], int rows ,int cols,char ch){ int i = 0; for (i = 0;i < rows;i++) { int j = 0; for (j = 0; j <cols; j++) { mine[i][j] = ch; } }}//设置雷的函数//随机生成雷的坐标,并放置在mine数组中void Setmine1(char mine[ROWS][COLS],int row, int col){ int count = SIMPLE_MODE; while (count) { int i = rand()%9 + 1; int j = rand()%9 + 1; if (mine[i][j] == "0") { mine[i][j] = "1"; count--; } }}void Setmine2(char show[ROWS][COLS], int x, int y, int ret){ show[x][y] = ret + "0";}//打印函数//用于打印show数组,并打印行与列的坐标,方便玩家选择void Printmine(char board[ROWS][COLS], int row, int col){ int i = 0; printf("/n"); printf(" ");//让列的坐标数字能够与下面的*对齐 for (i = 1; i <= col; i++) { if (i <= 9) printf("%d ", i);//当坐标数为个位数的时候,多一个空格占位置 else printf("%d ", i);//当坐标数为两位数的时候,少一个空格占位置 } printf("/n"); printf(" ");//让列的坐标数下面的分割线与下面的*对齐 for (i = 1; i <= col; i++) { printf("---");//个位数+两个空格或者两位数+一个空格,所以这里用三个短横线来对齐 } printf("/n"); for (i = 1; i <= row; i++) { int j = 0; if (i <= 9) printf("%d |", i);//个位数的行坐标数用两个空格对齐 else printf("%d |", i);//两位数的行坐标数用一个空格对齐 for (j = 1; j <= col; j++) { printf("%c ", board[i][j]);//用一个字符+两个短横线来对齐上面的三短横线 } printf("/n"); } printf("/n"); printf("/n");}//扫雷函数void Findmine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col){ int x = 0; int y = 0; int count = 0;//用来记录九宫格雷的
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/121504.html
摘要:每成功排一次雷,我们都要展示雷盘当场上剩下的格子数等于雷数时,游戏胜利,玩家踩雷时,游戏结束,所以我们这是一个判断输赢的函数。 前言:写完三子棋后,慢慢地熟悉了这种...
摘要:展示雷盘和初始化雷盘不一样,展示雷盘只需要用即可,并不需要将都展示出来,只是为了我们更好的计算扫雷的位置周围的雷的数量。 目录 1、需求分析 2、程序架构 3、代码实现(分函数呈现) (1)主函数代码实现 分析: 异常处理: (2)游戏主函数实现 分析: (3)初始化函数的实现 分析: (4...
摘要:新人小白的第一篇博客,有什么不好之处望多提意见。这个扫雷小游戏主要是基于二维数组,循环与基本的函数知识等。请输入坐标提示玩家输入坐标。换行是为了看着好看,要不然打印出来的数组会变形的。用来接收判断输赢的函数的返回值。 新人小白的第一篇博客,有什么不好之处望多提意见。 ...
摘要:设计实现扫雷游戏大致思路创建文件想法实现设计一个函数,实现建议菜单循环和分支选择游戏选项创造一个扫雷版面版面的大小最后是要可控的如何存放雷和版面的信息呢考虑排查雷时候的思路,我们要判断该位置周围个格子里面是否有雷初始化 ...
阅读 2657·2021-11-22 11:56
阅读 3318·2021-11-15 11:39
阅读 3211·2021-09-29 09:34
阅读 724·2021-09-24 09:48
阅读 538·2021-08-17 10:14
阅读 1138·2019-08-30 15:55
阅读 2554·2019-08-30 15:55
阅读 1190·2019-08-30 15:44