C语言详细讲解通过递归实现扫雷的展开

目录
  • 用户选择菜单
  • 棋盘初始化
  • 布置雷(随机布置)
  • 打印棋盘
  • 玩家下棋
  • 棋盘展开
  • 展开部分思维导图
    • 展开函数最后一个else return 作用
  • 周围雷个数判断

用户选择菜单

void menu()
{
	printf("****************************\n");
	printf("********  1.play  **********\n");
	printf("********  0.exit  **********\n");
	printf("****************************\n");
}

用户按1进入游戏

棋盘初始化

void Itnboard(char board[ROWS][COLS], int rows, int cols,char c)
{
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j <cols; j++)
		{
			board[i][j] = c;
		}
	}
}

创建数组,并对其进行初始化

布置雷(随机布置)

void Setboard(char board[ROWS][COLS], int row, int col)
{
	int count = Easy_count;
	while (count)
	{
		int x = rand() % row+1;
		int y = rand() % col+1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

用time函数产生随机值

打印棋盘

void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i, j;
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

打印棋盘

玩家下棋

void Player(char board[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x, y;
	int count = 0;
	while (1)
	{
		printf("请排雷:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
		{
			if (board[x][y] == '0')
			{
				Openboard(show, board, x, y);
				Displayboard(show, ROW, COL);
			}
			else if (board[x][y] == '1')
			{
				printf("你死了\n");
				break;
			}
		}
		else
		{
			printf("请重新输入");
		}
		int i, j;
		for (i = 1; i <= row; i++)
		{
			for (j = 1; j <= col; j++)
			{
				if (show[i][j] == '*')
				{
					count++;
				}
			}
		}
		if (count == Easy_count)
		{
			printf("成功\n");   //这里的判断条件是遍历整个数组,统计雷的个数,如果雷的个数等于所剩余未排的*,说明排雷成功
			break;
		}
	}
}

用户输入值,并进行判断,如果该位置没有雷,我们进入展开函数

棋盘展开

void Openboard(char show[ROWS][COLS], char board[ROWS][COLS], int row, int col)
{
	if (row >= 1 && row <= ROW && col >= 1 && col <= COL)
	{
		int count=sum(board, row, col);
		if (count != 0)
		{
			show[row][col] = count + '0';
		}
		else if (show[row][col] != '_')
		{
			show[row][col] = '_';
			int i = 0, j = 0;
			for (i = row - 1; i <= row + 1; i++)
			{
				for (j = col - 1; j <= col + 1; j++)
				{
					Openboard(show, board, i,j);
				}
			}
		}
		else
		{
			return;
		}
	}
}

如果用户输入的这个位置没有雷,我们对其周围8个位置进行判断是否有雷,若有雷,我们把雷的个数显示在该位置上,若其周围8个位置没有雷并且不是下划线,我们把这个位置赋值为下划线,然后并对其8个位置进行同样的判断,如果周围没雷,而且周围的棋子也不是下划线,我们对其进行返回。

展开部分思维导图

展开函数最后一个else return 作用

这里我们show棋盘有三种情况,

1.该位置是*

2.该位置是下划线

3.该位置是雷的个数

else

return;

这里是作用:如果是下划线,我们就返回上一层函数。因为如果这里不是下划线,我们会在else return 之前的语句中进行判断,并对其周围8个位置进行操作,然后再对这8个棋子各个周围8个位置进行判断并操作,如果这里是下划线,就说明由这个位置为中心的周围8个棋子已经判断过了,并且以这8个位置为中心,已经递归过了,我们不需要再进行判断,所以直接返回就行

周围雷个数判断

int sum(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y - 1] +
		board[x - 1][y] +
		board[x - 1][y + 1] +
		board[x][y - 1] +
		board[x][y + 1] +
		board[x + 1][y - 1] +
		board[x + 1][y] +
		board[x + 1][y + 1] - 8 * '0');
}

test.c

#include"game.h"
void menu()
{
	printf("****************************\n");
	printf("********  1.play  **********\n");
	printf("********  0.exit  **********\n");
	printf("****************************\n");
}
void game()
{
	char board[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	Itnboard(board, ROWS, COLS,'0');  //初始化棋盘
	Itnboard(show, ROWS, COLS, '*');
	Setboard(board, ROW, COL);
	Displayboard(board, ROW, COL);
	Player(board, show, ROW, COL);            //玩家输入
}
int main()
{
	int input=1;
  srand((unsigned int)time(NULL));
	do{
		menu();
	scanf("%d", &input);
	switch (input)
	{
	case 1:
		game();
		break;
	case 0:
		break;
	default:
		printf("输入错误请重新输入:\n ");
	}
	} while (input);
}

game.c

#include"game.h"
void Itnboard(char board[ROWS][COLS], int rows, int cols,char c)
{
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j <cols; j++)
		{
			board[i][j] = c;
		}
	}
}
void Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i, j;
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}
void Setboard(char board[ROWS][COLS], int row, int col)
{
	int count = Easy_count;
	while (count)
	{
		int x = rand() % row+1;
		int y = rand() % col+1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}
int sum(char board[ROWS][COLS], int x, int y)
{

	return (board[x - 1][y - 1] +
		board[x - 1][y] +
		board[x - 1][y + 1] +
		board[x][y - 1] +
		board[x][y + 1] +
		board[x + 1][y - 1] +
		board[x + 1][y] +
		board[x + 1][y + 1] - 8 * '0');
}
void Player(char board[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x, y;
	int count = 0;
	while (1)
	{
		printf("请排雷:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
		{
			if (board[x][y] == '0')
			{
				Openboard(show, board, x, y);
				Displayboard(show, ROW, COL);
			}
			else if (board[x][y] == '1')
			{
				printf("你死了\n");
				break;
			}
		}
		else
		{
			printf("请重新输入");
		}
		int i, j;
		for (i = 1; i <= row; i++)
		{
			for (j = 1; j <= col; j++)
			{
				if (show[i][j] == '*')
				{
					count++;
				}
			}
		}
		if (count == Easy_count)
		{
			printf("成功\n");
			break;
		}
	}
}
void Openboard(char show[ROWS][COLS], char board[ROWS][COLS], int row, int col)
{

	if (row >= 1 && row <= ROW && col >= 1 && col <= COL)
	{
		int count=sum(board, row, col);
		if (count != 0)
		{
			show[row][col] = count + '0';
		}
		else if (show[row][col] != '_')
		{
			show[row][col] = '_';
			int i = 0, j = 0;
			for (i = row - 1; i <= row + 1; i++)
			{
				for (j = col - 1; j <= col + 1; j++)
				{

					Openboard(show, board, i,j);
				}
			}
		}
		else
		{
			return;
		}
	}
}

game.h

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Easy_count 10
void Itnboard(char board[ROWS][COLS], int rows, int cols,char c);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Setboard(char board[ROWS][COLS], int row, int col);
void Player(char board[ROWS][COLS], char show[ROWS][COLS], int row, int col);
void Openboard(char show[ROWS][COLS], char board[ROWS][COLS], int row, int col);

到此这篇关于C语言详细讲解通过递归实现扫雷的展开的文章就介绍到这了,更多相关C语言扫雷内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言实现第一次防死版扫雷游戏

    目录 前言 一.功能描述 二.实现的步骤 1.菜单的打印函数: 2.初始化雷盘函数: 3.打印雷盘函数: 4.埋雷函数: 5.排雷函数: 6.防止第一次死的函数: 7.展开函数: 总结 前言 扫雷这款经典的游戏想必大多数人都玩过了,今天用C语言实现了扫雷小游戏,小伙伴们快来看看吧. 一.功能描述 扫雷代码有以下功能: 1.若输入的坐标周围没雷,可以直接展开 2.防止第一次玩就直接踩雷,被炸死 3.若输入的坐标周围有雷,会显示周围雷的个数 4.若排雷失败,会展示出雷图的雷分布是怎样的 二.实现的步

  • C语言实现自定义扫雷游戏(递归版)

    本文实例为大家分享了C语言自定义扫雷游戏的具体代码,供大家参考,具体内容如下 实现过程 对于用C语言实现扫雷游戏得实现,可将游戏过程分为两个板块. 实现游戏关键功能得函数 搭建合理得游戏过程 实现游戏关键功能 为了将游戏功能方便管理和键入,首先我们创建一个头文件,mine.h对游戏功能进行声明.然后创建对应的源文件mine.c对这些函数进行定义. 对于游戏功能,我们首先想到的是构建一个目标规格的雷盘,也就是二维数组.为了使游戏更具可玩性,所以雷盘的规格应可以自定义.所以在mine.h头文件中,应

  • C语言扫雷排雷小游戏实现全程

    目录 test.c game.h game.c 详解游戏代码的实现 1初化扫雷区 2打印扫雷区 3 设置雷 4 排雷 4.1展开一片的功能 4.2雷标记功能的实现 游戏过程 test.c 在这个文件中,我们主要是完成游戏逻辑的测试,在这里我们要注意的点,我们建立了二个数组,mine数组我们用来存放布置雷的信息,show数组存放排查出雷的信息.本次排雷区域是9*9的格子,为了防止数组出现越界,我们特意把数组的下标定义大点变为11*11. #define _CRT_SECURE_NO_WARNING

  • C语言实现经典扫雷小游戏完整代码(递归展开 + 选择标记)

    目录 游戏介绍 游戏整体框架 游戏具体功能及实现 1.雷盘的定义 2.雷盘的初始化 3.布置雷 4.排查雷 5.递归式展开一片 6.获取周围雷的个数 7.标记特定位置 8.打印雷盘 游戏完整代码 1.test.c 2.game.h 3.game.c 游戏效果展示 大家好,今天我们将一起用C语言实现一个经典小游戏 – 扫雷,Let is go ! 游戏介绍 扫雷游戏相信大家都玩过,上图就是一个网页版的扫雷,它的规则是玩家选择一个方格,若此方格没有地雷,那么该方格会显示与它相邻的八个方格中雷的个数,

  • C语言实现递归版扫雷游戏实例

    目录 思路 清晰的逻辑 菜单 棋盘 布置雷 排雷 判断输赢 text.c实现 game.c实现 game.h实现 递归部分详解 总结 思路 清晰的逻辑 为方便将其分为三个文件:text.c(测试) game.c(函数实现) game.h(头文件声明) 在排雷的时候为了方便,我们需要将每一行每一列对应的行数,列数打印出来. #define LEI 10 #define ROW 10 #define LOW 10 #define ROWS ROW+2 #define LOWS LOW+2 //在定义

  • C语言实现扫雷小游戏(扩展版)

    本文实例为大家分享了C语言实现扫雷小游戏的具体代码,供大家参考,具体内容如下 实现的拓展功能如下: 1.设置游戏难度等级2.保证玩家在第一把踩雷后不被炸死3.若排雷的地方无雷,自动扩展到有雷的周围,并给出雷数4.标记(相当于扫雷游戏中的插旗子)5.取消标记 分析: 1.用二维字符数组mine[ROWS][COLS]来存储雷,现在我们用字符1来表示有雷,字符0表示无雷.用二维字符数组show[ROWS][COLS]将所有的元素初始化为*,并打印作为展现给玩家的.同时用show数组来表示对应的min

  • C语言实现简易的扫雷小游戏

    这是一个用C语言实现的控制台扫雷小游戏,实现了随机布置炸弹.扫描炸弹.标记炸弹.百分百第一次不被炸死等功能. 编译器:vs2015 功能模块图 源代码 #include<stdio.h> #include<stdlib.h> #include<time.h> void show(int cbd[10][10],int u[10][10])  //界面输出函数 {     int i, j;     //for (i = 0; i < 10; i++)  //输出全

  • C语言实现扫雷游戏详细流程

    目录 前言 头文件部分 主函数部分(源文件) 函数定义(原文件) 1.菜单打印 2.初始化棋盘 3.打印棋盘 4.生成地雷 5.数雷并赋值给trueboard 6.排查雷区 7.展开 8.判断输赢 前言 嘿!是不是写扫雷小游戏的时候发现一个个输入太慢了?是不是想要展开却发现陷入了死递归?让小黄教教你怎么巧妙地解决这个问题吧! 其实总结起来就是一句话“可以让计算机多判断,但是不能让他多算”.只要每次判断一个格子周围雷数的时候赋值到另一个棋盘,后续递归的时候就不判断这个地方的棋盘就解决啦! PS:采

  • C语言详细讲解通过递归实现扫雷的展开

    目录 用户选择菜单 棋盘初始化 布置雷(随机布置) 打印棋盘 玩家下棋 棋盘展开 展开部分思维导图 展开函数最后一个else return 作用 周围雷个数判断 用户选择菜单 void menu() { printf("****************************\n"); printf("******** 1.play **********\n"); printf("******** 0.exit **********\n"); p

  • C语言 详细讲解逻辑运算符的使用

    目录 一.&& 与 II 分析 二.!分析 三.小结 一.&& 与 II 分析 下面的程序运行结束后,i, j,k 的值分别为多少? #include <stdio.h> int main() { int i = 0; int j = 0; int k = 0; ++i || ++j && ++k; printf("i = %d\n", i); printf("j = %d\n", j); printf(&

  • C语言详细讲解位运算符的使用

    目录 一.位运算符分析 二.小贴士 三.位运算与逻辑运算 四.小结 一.位运算符分析 C语言中的位运算符 位运算符直接对 bit 位进行操作,其效率最高. & 按位与 | 按位或 ^ 按位异或 ~ 取反 << 左移 >> 右移 左移和右移注意点 左操作数必须为整数类型 char 和 short 被隐式转换为 int 后进行移位操作 右操作数的范围必须为:[0,31] 左移运算符<< 将运算数的二进制位左移 规则:高位丢弃,低位补0 右移运算符>> 把

  • C语言详细讲解注释符号的使用

    目录 一.注释规则 二.注释中一个有趣的问题 三.教科书型注释 四.迷惑型的注释 五.忽悠型注释 六.搞笑型注释 七.漂亮的程序注释 八.小结 一.注释规则 编译器在编译过程中使用空格替换整个注释 字符串字面量中的 // 和 /*...*/ 不代表注释符号 /*......*/ 型注释不能被嵌套 下面看一下这样一段代码: #include <stdio.h> int main() { int/*...*/i; char* s = "abcdefgh //hijklmn";

  • C语言详细讲解多维数组与多维指针

    目录 一.指向指针的指针 二.二维数组与二维指针 三.数组名 四.小结 一.指向指针的指针 指针的本质是变量 指针会占用一定的内存空间 可以定义指针的指针来保存指针变量的地址值 为什么需要指向指针的指针? 指针在本质上也是变量 对于指针也同样存在传值调用与传址调用 下面看一个重置动态空间大小(从 size 到 new_size)的代码: #include <stdio.h> #include <malloc.h> int reset(char** p, int size, int

  • C语言 详细讲解数组参数与指针参数

    目录 一.C语言中的数组参数退化为指针的意义 二.二维数组参数 三.等价关系 四.被忽视的知识点 五.小结 一.C语言中的数组参数退化为指针的意义 C 语言中只会以值拷贝的方式传递参数 当向函数传递数组时: 将整个数组拷贝一份传入函数        × 将数组名看做常量指针传数组首元素地址    √ C 语言以高效作为最初设计目标: a) 参数传递的时候如果拷贝整个数组执行效率将大大下降. b) 参数位于栈上,太大的数组拷贝将导致栈溢出. 二.二维数组参数 二维数组参数同样存在退化的问题 二维数

  • C语言详细讲解循环语句的妙用

    目录 一.循环语句分析 二.do ... while 语句的循环方式 三.while 语句的循环方式 四.for 语句的循环方式 五.break和 continue 的区别 六.do 和 break 的妙用 七.小结 一.循环语句分析 循环语句的基本工作方式 通过条件表达式判定是否执行循环体 条件表达式遵循 if 语句表达式的原则 do,while,for的区别 do 语句先执行后判断,循环体至少执行一次 while 语句先判断后执行,循环体可能不执行 for 语句先判断后执行,相比 while

  • C语言 详细讲解#pragma的使用方法

    目录 一.#pragma 简介 二.#pragma message 三.#pragma once 四.#pragma pack 五.小结 一.#pragma 简介 #pragma 用于指示编译器完成一些特定的动作 #pragma 所定义的很多指示字是编译器特有的 #pragma 在不同的编译器间是不可移植的 预处理器将忽略它不认识的 #pragma 指令 不同的编译器可能以不同的方式解释同一条 #pragma 指令 一般用法: #pragma parameter 注:不同的 parameter

  • C语言 详细讲解接续符和转义符的使用

    目录 一.接续符的意义 二.接续符的使用 三.转义符的意义 四.转义符的使用 五.转义符和其他的语法混合 六.小结 一.接续符的意义 C语言中的接续符(\)是指示编译器行为的利器 下面看一段接续符的代码(代码1-1): #in\clud\e <st\dio.h>in\t m\ain(\){pri\ntf\    (\    "Hello AutumnZe.\n"    )\    ;  ret\urn 0;} 可以看到上述代码写的很凌乱,但是可以正常编译运行,如下: 二.接

  • C语言详细讲解二分查找用法

    目录 [力扣题号]704.二分查找 力扣题目链接 示例 1: 输入: nums = [-1,0,3,5,9,12], target = 9     输出: 4       解释: 9 出现在 nums 中并且下标为 4 示例 2: 输入: nums = [-1,0,3,5,9,12], target = 2     输出: -1        解释: 2 不存在 nums 中因此返回 -1 提示: 你可以假设 nums中的所有元素是不重复的. n将在[1, 10000]之间. nums的每个元素

随机推荐