C语言实现递归版扫雷游戏实例
思路
清晰的逻辑
为方便将其分为三个文件:text.c(测试) game.c(函数实现) game.h(头文件声明)
在排雷的时候为了方便,我们需要将每一行每一列对应的行数,列数打印出来。
#define LEI 10 #define ROW 10 #define LOW 10 #define ROWS ROW+2 #define LOWS LOW+2 //在定义棋盘的长宽时,特意加上2,便于标记行数列数。
菜单
打印的菜单只需要有开始游戏、退出游戏的选项即可
void menu() { printf("*************************************\n"); printf("************1.开始游戏***************\n"); printf("************0.退出游戏***************\n"); printf("*************************************\n"); }
棋盘
1.雷盘
2.棋盘
扫雷需要先记录雷的信息再进行排雷,如果使用一个棋盘太过于复杂,所以我们使用两个棋盘,一个用于布置雷,一个用于玩家排雷。
两个棋盘初始化
布置雷的棋盘初始化,将字符‘0’作为非雷,字符‘1’作为雷。
玩家盘将字符‘*’作为还没有扫的地方
board(arr1, ROWS, LOWS, '0');//雷盘 board(arr2, ROWS, LOWS, '*');//玩家盘
因为两个的初始化方式不同,所以我们采用传参ret初始化
//初始化棋盘 void board(char arr1[ROWS][LOWS], int rows, int lows, char ret) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < lows; j++) { arr1[i][j] = ret; } }
布置雷
布置的雷放置需要随机,所以采用两个随机数来定位坐标。
//布置雷 void Get_lei(char arr1[ROWS][LOWS], int row, int low) { int count = LEI; while (count) { int x = rand() % row + 1; int y = rand() % low + 1; if (arr1[x][y] == '0') { arr1[x][y] = '1'; count--; } } //displayboard(arr1, ROW, LOW);//用于测试 }
排雷
当我们输入一个坐标时,我们需要知道这个坐标周围雷的个数,定义一个Get_num函数来获取雷个数。但此时只能获取一个坐标的信息,我们知道一般的扫雷,如果当前坐标雷的个数为0,就会展开,这个过程较为复杂,所以我们使用递归来实现
//玩家盘 static int Get_num(char arr1[ROWS][LOWS],int x, int y)//获得当前坐标周围雷的个数 { int count = 0; int i = 0; for (i = x - 1; i <= x + 1; i++) { int j = 0; for (j = y - 1; j <= y + 1; j++) { if (arr1[i][j] == '1') { count++; } } } return count; } //判断是否展开,实现函数 static void Judge(char arr2[ROWS][LOWS], char arr1[ROWS][LOWS], int x, int y) { if (x > 0 && x <= ROW && y > 0 && y <= LOW) { int ret = Get_num(arr1, x, y); if (ret != 0) arr2[x][y] = ret + '0';//记录雷的个数 //递归散开 else if (arr1[x][y] != ' ') { arr2[x][y] = '0'; arr1[x][y] = ' '; int i = 0; for (i = x - 1; i <= x + 1; i++) { int j = 0; for (j = y - 1; j <= y + 1; j++) { Judge(arr2, arr1, i, j); } } } else { return; } } }
判断输赢
输:即每排一次雷,检查一下雷盘对应的信息,如果是雷,就被炸死,如果不是,就继续排雷。
赢:当玩家将所有的非雷的区域都排查出来时,判断为赢。(这里采用一个计数器,没排一次雷计数器就++一下,当计数器与总的非雷的区域数目相同时,判断为赢)
void Out_lei(char arr2[ROWS][LOWS], int row, int low, char arr1[ROWS][LOWS]) { int x = 0; int y = 0; while (1) { printf("请输入坐标:>"); scanf("%d,%d", &x, &y); if (x >= 1 && x <= ROW && y >= 1 && y <= LOW) { if (arr1[x][y] == '1') { arr2[x][y] = '#'; displayboard(arr2, ROW, LOW);//排雷 printf("遗憾你输了\n"); break; } else { Judge(arr2, arr1, x, y); displayboard(arr2, ROW, LOW);//排雷 } } else { printf("输入错误!\n"); } //判断扫雷是否赢 int i = 0, flag = 0; for (i = 1; i <= ROW; i++) { int j = 0; for (j = 1; j <= LOW; j++) { if (arr2[i][j] != '*') { flag++; } } } if (flag == ROW*LOW - LEI) { printf("你赢了!\n"); break; } } }
text.c实现
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" //菜单 void menu() { printf("*************************************\n"); printf("************1.开始游戏***************\n"); printf("************0.退出游戏***************\n"); printf("*************************************\n"); } void game() { //初始化棋盘 char arr1[ROWS][LOWS] = { 0 };//雷盘 char arr2[ROWS][LOWS] = { 0 };//玩家盘 board(arr1, ROWS, LOWS, '0'); board(arr2, ROWS, LOWS, '*'); //打印棋盘 //displayboard(arr1, ROW, LOW);//布置雷 displayboard(arr2, ROW, LOW);//排雷 //布置雷 Get_lei(arr1,ROW,LOW); //排雷 Out_lei(arr2,ROW,LOW, arr1); } int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择:>"); scanf("%d",&input); switch (input) { case 1: { printf("扫雷\n"); game(); break; } case 0: { printf("退出游戏\n"); break; } default: { printf("选择错误\n"); break; } } } while (input); return 0; }
game.c实现
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" //初始化棋盘 void board(char arr1[ROWS][LOWS], int rows, int lows, char ret) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < lows; j++) { arr1[i][j] = ret; } } } //打印棋盘 void displayboard(char arr1[ROWS][LOWS], int row, int low) { printf("<———扫雷游戏———>\n"); int i = 0; for (i = 1; i <= row; i++) { int j = 0; if (i == 1) { for (j = 0; j <= low; j++) { printf("%2d ", j); } printf("\n"); } for (j = 1; j <= low; j++) { if (j == 1) { printf("%2d ", i); } printf("%2c ", arr1[i][j]); } printf("\n"); } printf("<———扫雷游戏———>\n"); } //布置雷 void Get_lei(char arr1[ROWS][LOWS], int row, int low) { int count = LEI; while (count) { int x = rand() % row + 1; int y = rand() % low + 1; if (arr1[x][y] == '0') { arr1[x][y] = '1'; count--; } } //displayboard(arr1, ROW, LOW); } //玩家盘 static int Get_num(char arr1[ROWS][LOWS],int x, int y) { int count = 0; int i = 0; for (i = x - 1; i <= x + 1; i++) { int j = 0; for (j = y - 1; j <= y + 1; j++) { if (arr1[i][j] == '1') { count++; } } } return count; } //判断是否展开,实现函数 static void Judge(char arr2[ROWS][LOWS], char arr1[ROWS][LOWS], int x, int y) { if (x > 0 && x <= ROW && y > 0 && y <= LOW) { int ret = Get_num(arr1, x, y); if (ret != 0) arr2[x][y] = ret + '0'; //递归散开 else if (arr1[x][y] != ' ') { arr2[x][y] = '0'; arr1[x][y] = ' '; int i = 0; for (i = x - 1; i <= x + 1; i++) { int j = 0; for (j = y - 1; j <= y + 1; j++) { Judge(arr2, arr1, i, j); } } } else { return; } } } void Out_lei(char arr2[ROWS][LOWS], int row, int low, char arr1[ROWS][LOWS]) { int x = 0; int y = 0; while (1) { printf("请输入坐标:>"); scanf("%d,%d", &x, &y); if (x >= 1 && x <= ROW && y >= 1 && y <= LOW) { if (arr1[x][y] == '1') { arr2[x][y] = '#'; displayboard(arr2, ROW, LOW);//排雷 printf("遗憾你输了\n"); break; } else { Judge(arr2, arr1, x, y); displayboard(arr2, ROW, LOW);//排雷 } } else { printf("输入错误!\n"); } //判断扫雷是否赢 int i = 0, flag = 0; for (i = 1; i <= ROW; i++) { int j = 0; for (j = 1; j <= LOW; j++) { if (arr2[i][j] != '*') { flag++; } } } if (flag == ROW*LOW - LEI) { printf("你赢了!\n"); break; } } }
game.h实现
#pragma once #include <stdio.h> #include <stdlib.h> #define LEI 10 #define ROW 10 #define LOW 10 #define ROWS ROW+2 #define LOWS LOW+2 //初始化棋盘 void board(char arr1[ROWS][LOWS],int rows,int lows,char ret); //打印棋盘 void displayboard(char arr1[ROWS][LOWS], int row, int low); //布置雷 void Get_lei(char arr1[ROWS][LOWS], int row, int low); //玩家盘 void Out_lei(char arr2[ROWS][LOWS], int row, int low, char arr1[ROWS][LOWS]);
递归部分详解
递归条件:1.有停止的条件。2.每一次递归都会向这个条件靠拢。
那么这里的停止条件是什么呢?
递归:当返回雷的个数为0时,就符合继续递归的条件,我们需要将当前坐标周围的点全部排除。且需要将已经排查了的坐标做一个标记,否则就会不停的排查下去,就会形成死递归。所以
停止条件:当前这个坐标是已被排查过的,就停止递归。
因为每一次排查都会的一个标记,所以这就是那个不断向停止条件靠拢的过程。
//判断是否展开,实现函数 static void Judge(char arr2[ROWS][LOWS], char arr1[ROWS][LOWS], int x, int y) { if (x > 0 && x <= ROW && y > 0 && y <= LOW) { int ret = Get_num(arr1, x, y); if (ret != 0) arr2[x][y] = ret + '0'; //递归散开 else if (arr1[x][y] != ' ') { arr2[x][y] = '0';//玩家盘 arr1[x][y] = ' ';//雷盘 int i = 0; for (i = x - 1; i <= x + 1; i++) { int j = 0; for (j = y - 1; j <= y + 1; j++) { Judge(arr2, arr1, i, j); } } } else { return; } } }
总结
到此这篇关于C语言实现递归版扫雷游戏实例的文章就介绍到这了,更多相关C语言递归版扫雷内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://blog.csdn.net/weixin_63246064/article/details/122648
相关文章
- 这篇文章主要为大家详细介绍了C语言实现放烟花的程序,有音乐播放,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-23
- 本篇文章主要介绍C语言中char的知识,并附有代码实例,以便大家在学习的时候更好的理解,有需要的可以看一下...2020-04-25
- 这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
- 这篇文章主要介绍了详解如何将c语言文件打包成exe可执行程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-25
- free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
- 这篇文章主要介绍了C语言中计算正弦的相关函数总结,包括正弦和双曲线正弦以及反正弦的函数,需要的朋友可以参考下...2020-04-25
详解C语言中的rename()函数和remove()函数的使用方法
这篇文章主要介绍了详解C语言中的rename()函数和remove()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25- 这篇文章主要介绍了C语言中求和、计算平均值、方差和标准差的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-10
- 本篇文章主要讲解C语言 基本语法,这里提供简单的示例和代码来详细讲解C语言的基本语法,开始学习C语言的朋友可以看一下,希望能够给你带来帮助...2021-09-18
- 这篇文章主要介绍了C语言中send()函数和sendto()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25
- 今天小编就为大家分享一篇C语言实现从文件读入一个3*3数组,并计算每行的平均值,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
- 这篇文章主要介绍了C++递归删除一个目录的实现方法,涉及到目录的操作及递归算法的应用,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了使用C语言操作文件的基本函数整理,包括创建和打开以及关闭文件的操作方法,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了C语言中memcpy 函数的用法详解的相关资料,需要的朋友可以参考下...2020-04-25
- 在本篇内容里小编给大家分享了关于C++实现递归函数的教学步骤,需要的朋友跟着参考下。...2020-04-25
- 这篇文章主要介绍了C语言中查找字符在字符串中出现的位置的方法,分别是strchr()函数和strrchr()函数的使用,需要的朋友可以参考下...2020-04-25
- 很多同学在学习c语言的时候是不是会碰到a++和++a都有甚么作用啊。今天我们就来探讨下...2020-04-25
- 下面小编就为大家带来一篇C语言实现时间戳转日期的算法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
- 这篇文章主要对C语言中const关键字的用法进行了详细的分析介绍,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了C语言之整数划分问题(递归法)实例代码的相关资料,需要的朋友可以参考下...2020-04-25