文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

c语言怎么实现含递归清场版扫雷游戏

2023-06-25 17:06

关注

这篇文章主要介绍“c语言怎么实现含递归清场版扫雷游戏”,在日常操作中,相信很多人在c语言怎么实现含递归清场版扫雷游戏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”c语言怎么实现含递归清场版扫雷游戏”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一,设计思路

想必大家都玩过扫雷

c语言怎么实现含递归清场版扫雷游戏

 这便是一个标准的扫雷,换做代码实现,我们需要考虑以下几点:

棋盘的设计与初始化

在棋盘中放入雷

统计雷数

如何实现“一片”的效果

输赢的判断

接下来我们进行具体操作。

二.实现方式

1.菜单的打印

对任意一个游戏,菜单是必不可少的,也是最简单的部分,直接上代码

void menu(){printf("------------------扫雷------------------\n");printf("---------------1.开始游戏---------------\n");printf("---------------0.退出游戏---------------\n");}int main(){srand((unsigned int)time(NULL));int a = 0;do{menu();scanf("%d", &a);if (a == 0){break;}game();} while (a);return 0;}

其中srand是为了求随机值,用来布置雷

2.game函数

主菜单完后进入game函数,在game函数里我们就要开始主要的游戏部分,如棋盘初始化与打印等,当然这些步骤都依靠函数完成,game函数只相当于集合了一系列的游戏模块

void game(){char mine[ROWS][COLS];char show[ROWS][COLS];initeboard(mine, ROWS, COLS, '0');initeboard(show, ROWS, COLS, '*');//初始棋盘displayboard(show, ROW, COL);//打印棋盘mine_make(mine, ROW, COL);//设置雷//displayboard(mine, ROW, COL);find_mine(mine, show, ROWS, COLS);//排查雷 }

3.棋盘的初始化与打印

可以看到,我在game函数里初始了两个棋盘,为什么要两个呢?

其实,一个是为了放置了雷,一个为了展示给玩家,为什么不用一个呢,我们要在放雷处用'1',表示不放雷处用‘0',这样计算一个坐标周围雷的数量就会更简单,接下来看一段代码:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <time.h>#define ROW 10#define COL 10#define ROWS ROW+2#define COLS COL+2

这里我们看到定义了一个ROWS和COLS这又是为何呢?

 扫雷时当你确认一个点时,它会对此点周围的八个点进行排查看是否有泪,当坐标位于红线处时没有无法判断八个,因此有了ROWS与COLS,这时,有人就会问了:那埋雷的地方用ROW COL就可以了,还不用担心雷跑到外边我们加的框,想法很好,但我们有两个棋盘,必须对应,而且也不存在跑出雷的情况,往下分析你就会知道

void initeboard(char board[ROWS][COLS], int cols, int rows,char s)//棋盘初始化,此处用了个节省步骤的方法,不用两个棋盘依次初始化{int i = 0;int j = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){board[i][j] = s;}}}void displayboard(char board[ROWS][COLS], int row, int col)//棋盘打印{int i = 0;int j = 0;printf(" ");//与行中打印的0%d对应for (j = 0; j <=col; j++){printf(" %d  ", j);}printf("\n");printf("-");for (j = 1; j <= col + 1; j++){printf("---");printf("|");}printf("\n");//列对应打印完成for (i = 1; i <= row; i++){if (i <= 9){printf(" 0%d ", i);}elseprintf(" %d ", i);printf("|");for (j = 1; j <= col; j++){printf(" %c ", board[i][j]);printf("|");}printf("\n");printf("-");for (j = 1; j <= col+1; j++){printf("---");printf("|");}printf("\n");//行对应嵌套在内部 打印的数前加0是为了让当行数大于9时能够对应 如09与10}}

棋盘的打印做了行列对应,所以可能有点不明显

 4.雷的放置,雷的个数

雷的放置很简单,在棋盘‘0',处放置就行,因为我们对随机数的算式使随机数只会出现在0-9没有跑出的情况

mine_make(char mine[ROWS][COLS], int row, int col)//设置雷{int count = 10;while (count){int x = rand() % 10;int y = rand() % 10;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}}

雷的个数就需要一定考虑了:

首先,我们需要把周围八个位置是否有雷,有多少个雷判断出来,这时我们设计‘0' ‘1'类型就排上用场了,但是注意,这是字符,不是数字

当然返回的数字记得转成字符类型

int get_mine(char mine[ROWS][COLS], int i, int j)//得到一个坐标附近雷的个数{return mine[i - 1][j - 1] + mine[i - 1][j] + mine[i - 1][j + 1] +mine[i][j - 1] + mine[i][j + 1] +mine[i + 1][j - 1] + mine[i +1 ][j] + mine[i + 1][j + 1] - 8 * '0';//此处我们的数字其实是字符,用此方法可以转为数字整形}

5.递归实现一片效果

当不为雷是会展开附近一片不为雷,提高游戏效率

void spread(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)//递归方法实现一大片{show[x][y] = ' ';//先让输入金的坐标处变为空格,因为已经判定过雷所以可以直接转空格int i = 0;int j = 0;int ret = 0;for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++)//嵌套for循环表示输入坐标包括自生及周围八个{if (i > 0 && i <= ROW && j > 0 && j <= COL && mine[i][j] != '1' && show[i][j] == '*')//防止出现负坐标,避免有雷,避免输入重复{ret = get_mine(mine, i, j);//判断ret是0或非0,并得出周围雷数if (!ret)//如果ret=0,!ret便是非0;为真{spread(show, mine, i, j);//递归}if (ret)//ret!=0时为真,便打印数{show[i][j] = ret + '0';//使数字转成对应字符}} }}}

 6.排查雷

负责判断是否被炸死及游戏胜利

void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷{printf("请输入坐标\n");int i = 0;int j = 0;int win = 0;while (row*col-10)//因为是十个雷,所以是—10,因为下总数减10就赢了,所以可以以此跳出循环,当然要是雷部位10,定一个变量就行,此处就不改了{scanf("%d %d", &i, &j);if (mine[i][j] == '1'){printf("你挂了\n");displayboard(mine, ROW, COL);break;}else{show[i][j] = get_mine(mine, i, j)+'0';spread(show,mine, i, j);displayboard(show, ROW, COL);win++;}}if (win ==row * col - 10){printf("恭喜你,成功了\n");displayboard(mine, ROW, COL);}}

具体注释都在代码里了

正常情况把打印雷盘注释就行,就可以正常游戏了

 三.完整代码

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <time.h>#define ROW 10#define COL 10#define ROWS ROW+2#define COLS COL+2void menu(){printf("------------------扫雷------------------\n");printf("---------------1.开始游戏---------------\n");printf("---------------0.退出游戏---------------\n");}void initeboard(char board[ROWS][COLS], int cols, int rows,char s)//棋盘初始化,此处用了个节省步骤的方法,不用两个棋盘依次初始化{int i = 0;int j = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){board[i][j] = s;}}}void displayboard(char board[ROWS][COLS], int row, int col)//棋盘打印{int i = 0;int j = 0;printf(" ");//与行中打印的0%d对应for (j = 0; j <=col; j++){printf(" %d  ", j);}printf("\n");printf("-");for (j = 1; j <= col + 1; j++){printf("---");printf("|");}printf("\n");//列对应打印完成for (i = 1; i <= row; i++){if (i <= 9){printf(" 0%d ", i);}elseprintf(" %d ", i);printf("|");for (j = 1; j <= col; j++){printf(" %c ", board[i][j]);printf("|");}printf("\n");printf("-");for (j = 1; j <= col+1; j++){printf("---");printf("|");}printf("\n");//行对应嵌套在内部 打印的数前加0是为了让当行数大于9时能够对应 如09与10}}mine_make(char mine[ROWS][COLS], int row, int col)//设置雷{int count = 10;while (count){int x = rand() % 10;int y = rand() % 10;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}}int get_mine(char mine[ROWS][COLS], int i, int j)//得到一个坐标附近雷的个数{return mine[i - 1][j - 1] + mine[i - 1][j] + mine[i - 1][j + 1] +mine[i][j - 1] + mine[i][j + 1] +mine[i + 1][j - 1] + mine[i +1 ][j] + mine[i + 1][j + 1] - 8 * '0';//此处我们的数字其实是字符,用此方法可以转为数字整形}void spread(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)//递归方法实现一大片{show[x][y] = ' ';//先让输入金的坐标处变为空格,因为已经判定过雷所以可以直接转空格int i = 0;int j = 0;int ret = 0;for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++)//嵌套for循环表示输入坐标包括自生及周围八个{if (i > 0 && i <= ROW && j > 0 && j <= COL && mine[i][j] != '1' && show[i][j] == '*')//防止出现负坐标,避免有雷,避免输入重复{ret = get_mine(mine, i, j);//判断ret是0或非0,并得出周围雷数if (!ret)//如果ret=0,!ret便是非0;为真{spread(show, mine, i, j);//递归}if (ret)//ret!=0时为真,便打印数{show[i][j] = ret + '0';//使数字转成对应字符}} }}}void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷{printf("请输入坐标\n");int i = 0;int j = 0;int win = 0;while (row*col-10)//因为是十个雷,所以是—10,因为下总数减10就赢了,所以可以以此跳出循环,当然要是雷部位10,定一个变量就行,此处就不改了{scanf("%d %d", &i, &j);if (mine[i][j] == '1'){printf("你挂了\n");displayboard(mine, ROW, COL);break;}else{show[i][j] = get_mine(mine, i, j)+'0';spread(show,mine, i, j);displayboard(show, ROW, COL);win++;}}if (win ==row * col - 10){printf("恭喜你,成功了\n");displayboard(mine, ROW, COL);}}void game(){char mine[ROWS][COLS];char show[ROWS][COLS];initeboard(mine, ROWS, COLS, '0');initeboard(show, ROWS, COLS, '*');//初始棋盘displayboard(show, ROW, COL);//打印棋盘mine_make(mine, ROW, COL);//设置雷displayboard(mine, ROW, COL);find_mine(mine, show, ROWS, COLS);//排查雷 }int main(){srand((unsigned int)time(NULL));int a = 0;do{menu();scanf("%d", &a);if (a == 0){break;}game();} while (a);return 0;}

到此,关于“c语言怎么实现含递归清场版扫雷游戏”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯