扫雷游戏(C语言详解)

news2024/11/24 8:49:07

扫雷游戏(C语言详解)

  • 放在最前面的
  • 1、前言(扫雷游戏的简介)
  • 2、扫雷游戏的规则(简易版)
  • 3、代码实现
    • (3.1)提醒一下:
        • ( i ) 提醒1:
        • ( ii ) 提醒2:
    • (3.2) 上代码
        • **game.h** 头文件
        • **game.c** 头文件
        • **test.c** 头文件
  • 4、结果展示
    • (4.1)输入的坐标是非法的(即不在坐标的范围)
    • (4.2)输入的坐标是雷,则游戏提前结束
    • (4.3)输入的坐标 不是雷,打印四周(八个坐标)有几个雷
    • (4.4)成功避免所有布置的雷,游戏完美结束
  • 5、END

放在最前面的

🎈 🎈 我的CSDN主页:OTWOL的主页,欢迎!!!👋🏼👋🏼
🎉🎉我的C语言初阶合集:C语言初阶合集,希望能帮到你!!!😍 😍
👋🏼🎉🎊创作不易,欢迎大家留言、点赞加收藏!!! 🥳😁😍

1、前言(扫雷游戏的简介)

《扫雷》中玩家的目标是在最短时间内识别出所有非雷区的格子,同时避免触碰到地雷。
游戏区域由多个隐藏格子组成,每个格子可能隐藏着地雷或数字,数字表示周围八个格子中地雷的数量
玩家通过点击格子揭示内容,使用逻辑推理逐步排除雷区。
游戏考验玩家的观察力和推理能力,任何一次误点地雷都会导致游戏失败

2、扫雷游戏的规则(简易版)

1. 第一次点击不会是雷。
2. 格子里的数字表示它周围有几个雷。
3. 游戏目标是找出所有雷,如果 “触雷” 则输。

3、代码实现

(3.1)提醒一下:

( i ) 提醒1:

我在代码注释中对每一行代码进行了 详细的 解释,保证 0基础小白能看得懂!

( ii ) 提醒2:

我写了三个文件,分别是
game.h、 game.c、test.c


game.h 里面存放着与game相关函数的声明 的 头文件

game.c里面存放着与扫雷游戏有关的函数的实现即定义
如:初始化函数 Init()函数、布置雷 set_mine 函数等 的
源文件

test.c 里面存放着 主函数(main)和 测试运行整个扫雷游戏的代码块头文件

(3.2) 上代码

game.h 头文件
//标准输出输出调用的头文件
#include<stdio.h>
// rand 函数 和 srand 函数调用的头文件
#include<stdlib.h>
// time()时间戳函数调用的头文件
#include<time.h>

//定义一个宏定义常量 ROW 数值是 9
#define ROW 9
//定义一个宏定义常量 COL 数值是 9
#define COL 9
//定义一个宏定义常量 ROWS 数值是 9+2 = 11
#define ROWS ROW+2
//定义一个宏定义常量 COLS 数值是 9+2 = 11
#define COLS COL+2
定义一个宏定义常量 NUM(用作存储 放置雷的个数) 数值是 76
#define NUM 76

//初始化函数 Init() 的声明
void Init(char board[ROWS][COLS], int rows, int cols, char set);
//打印函数 Print() 的声明
void Print(char board[ROWS][COLS], int row, int col);
//布置雷 set_mine() 的声明
void set_mine(char mine[ROWS][COLS], int row, int col);
//排雷 clear_mine() 的声明
void clear_mine(char mine[ROWS][COLS], char show[ROWS][COLS] , int row, int col);

game.c 头文件
#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"//引用 game.h 头文件

//初始化扫雷棋盘函数 Init() 的调用
void Init(char board[ROWS][COLS], int rows, int cols, char set)
{
	// 定义一个整型变量 i,
	// 并且初始化为 0
	int i = 0;
	//外层 for 循环
	for (i = 0; i < rows; i++)
	{
		// 定义一个整型变量 j,
		// 并且初始化为 0
		int j = 0;
		//内层 for 循环
		for (j = 0; j < cols; j++)
		{
			//将字符set的值,赋值给 board[i][j]
			board[i][j] = set;
		}
	}

}

//打印函数 Print() 的定义
void Print(char board[ROWS][COLS], int row, int col)
{
	// 定义一个整型变量 i,
	// 并且初始化为 0
	int i = 0;
	//输出打印 提示信息
	printf("\n------扫雷游戏------\n");
	// 定义一个整型变量 j,
	// 并且初始化为 0
	int j = 0;
	//for 循环 
	//用于 输出列数
	for (j = 0; j <= col; j++)
	{
		//打印列数
		printf("%d列\t", j);
	}
	//换行
	printf("\n");
	//外层 for 循环
	for (i = 1; i <= row; i++)
	{
		//打印行数
		printf("%d行\t", i);
		//内层 for 循环
		for (j = 1; j <= col; j++)
		{
			//输出打印 board[i][j] 对应的内容
			// \t 是转义字符,含义是 制表符
			//并按照%c\t的格式 进行打印
			printf("%c\t", board[i][j]);
		}
		//换行
		printf("\n");
	}
	//输出打印 提示信息
	printf("------扫雷游戏------\n\n");
}

//布置雷 set_mine() 的定义
void set_mine(char mine[ROWS][COLS], int row, int col)
{
	//定义一个整型变量 n
	//并将 放置雷的个数 NUM 赋值给 n
	int n = NUM;
	// while 循环
	while (n)
	{
		//定义两个整型变量 x y,
		//并将 rand() --随机数字的生成 函数 % row
		//生成的结果 分别 赋值给 x y
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		//如果 mine[x][y] 的 内容 等于 ‘0’(字符0), 则执行下面的语句块
		if (mine[x][y] == '0')
		{
			//将 ‘1’(字符1) 赋值给 board[x][y]
			mine[x][y] = '1';
			//雷的个数 - 1(减1)
			n--;
		}
	}
}



//排雷 clear_mine() 的定义
void clear_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	//输出打印 提示信息
	printf("一共有%d 个雷\n", NUM);
	//定义两个整型变量 x y,
	//并进行初始化,赋值为 0
	int x = 0;
	int y = 0;
	//定义两个整型变量 count,
	//用作计算第几次排雷次数 即避开了多少雷
	int count = 0;
	// while 循环,
	// 循环判断的条件是 count < NUM 
	while (count < NUM)
	{
			//输出打印 提示信息
			printf("\n欢迎您,请输入要排查的坐标\n");
			printf("提示1:(横、纵坐标中间用空格隔开)\n");
			printf("提示2:(横、纵坐标都是[1~9]):>");
			//输入 两个整型数字 
			int n2 = scanf("%d %d", &x, &y);
			//if 条件判断语句
			// 如果函数 x > 0 && x <= row && y > 0 && y <= col,执行下面的语句块
			// 即 if 条件判断条件是 输入的坐标是否有效
			if (x > 0 && x <= row && y > 0 && y <= col)
			{
				// if 条件判断语句
				// 如果函数 board[x][y]的 内容 不等于 ‘1’(字符1),执行下面的语句块
				if (mine[x][y] != '1')
				{
					// if 条件判断语句
					// 如果函数 board[x][y]的 内容 等于 ‘*’(字符*),执行下面的语句块
					if (show[x][y] == '*')
					{
						//输出打印 提示信息
						printf("\n第%d次 排查!\n", count + 1);
						// 将mine[x - 1][y] + mine[x - 1][y - 1]
						// +mine[x][y - 1] + mine[x + 1][y - 1]
						// + mine[x + 1][y] + mine[x + 1][y + 1]
						// + mine[x][y + 1] + mine[x - 1][y + 1] 即统计求和 show[x][y] 四周 七个坐标的雷数
						// 并将结果以字符的形式赋值给 show[x][y] 
						// (因为 mine[x][y]、show[x][y] 都是字符数组,元素必须是字符的形式!!!)

						show[x][y] = (mine[x - 1][y] + mine[x - 1][y - 1]
							+ mine[x][y - 1] + mine[x + 1][y - 1]
							+ mine[x + 1][y] + mine[x + 1][y + 1]
							+ mine[x][y + 1] + mine[x - 1][y + 1]) - 7 * '0';
						//输入的坐标有效,
						// 并且不是雷,
						// 还有没有被排查过
						// (三个条件同时满足!!!),
						// 则用作计算第几次排雷次数 即避开了多少雷的变量 count自增 1
						count++;
						//打印函数 Print() 的调用
						Print(show, ROW, COL);
						//如果用作计算第几次排雷次数 即避开了多少雷的变量 count
						//等于 ROW * COL -NUM 即(没有放置雷的个数),执行下面的语句块
						if (count == ( ROW * COL -NUM) ) 
						{
							//输出打印 提示信息
							printf("恭喜您,你成功避开 %d个雷!\n", NUM);
							printf("棒棒哒!游戏结束!\n");
							//跳出循环
							break;
						}
					}
					//
					else
					{
						//输出打印 提示信息
						printf("\n该坐标已经排查过了,请重新输入!\n");
					}
				}
				// mine[x][y] == '1',即 mine[x][y] 里面的内容是雷。
				else
				{
					//输出打印提示信息
					printf("\n非常遗憾!你被炸死了!游戏结束!\n");
					//输出打印 提示信息
					printf("\n雷区布置展示:>\n");
					//打印函数 Print() 的调用
					Print(mine, ROW, COL);
					//跳出循环
					break;
				}
			}
			//
			else
			{
				//输出打印 提示信息
				printf("坐标非法,请输入有效坐标\n");
			}
	}
}
test.c 头文件
#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"//引用 game.h 头文件


//定义菜单 menu() 函数
void menu()
{
	//输出打印 提示信息
	printf("\n********************\n");
	printf("*****  1.play  *****\n");
	printf("*****  0.exit  *****\n");
	printf("********************\n\n");
}

//
void game()
{
	// 定义一个二维的字符型数组,
	// 数组名字是 mine,
	// 有 ROWS 行、COLS 列
	char mine[ROWS][COLS];
	// 定义一个二维的字符型数组,
	// 数组名字是 show,
	// 有 ROWS 行、COLS 列
	char show[ROWS][COLS];
	//初始化函数 Init() 的调用
	Init(mine, ROWS, COLS,'0');
	//初始化函数 Init() 的调用
	Init(show, ROWS, COLS,'*');
	//输出打印 提示信息
	printf("\n扫雷游戏页面:>\n");
	//打印函数 Print() 的调用
	Print(show, ROW, COL);
	//布置雷 set_mine() 的调用
	set_mine(mine, ROW, COL);
	//输出打印 提示信息
	printf("\n雷区布置展示:>\n");
	//打印函数 Print() 的调用
	Print(mine, ROW, COL);
	//排雷 clear_mine() 的调用
	clear_mine(mine, show, ROW, COL);
}


//定义测试函数 test()
void test()
{
	// rand 函数(随机数的生成函数)使用前,
	// 必须要提前引用 srand 函数,
	// time() 函数是时间戳函数
	srand((unsigned int)time(NULL));
	//定义一个整型变量 input
	//并且初始化为0
	int input = 0;
	//使用 do while 循环语句
	do
	{
		//调用 菜单函数
		menu();
		//打印提示信息
		printf("请选择:>");
		// n1 来接受 scanf 函数的返回值,
		// 输入一个整数
		int n1 = scanf("%d", &input);
		//使用 switch 分支语句
		switch (input)
		{
		// 如果 input = 1
		// 执行 case 1:后面的语句
		case 1:
			//调用 game()函数
			game();
			//break 语句用来跳出 switch 分支语句 
			break;
		case 0:
			//打印提示信息
			printf("退出游戏\n");
			//break 语句用来跳出 switch 分支语句 
			break;
		default:
			// 如果 input 不等于 0 也不等于 1
			// 执行 default:后面的语句
			printf("选择错误,请重新选择\n");
			//break 语句用来跳出 switch 分支语句 
			break;
		}
	} while (input);//跳出 do-while 循环的条件是 input 等于 0
}

//主函数
int main()
{
	//调用测试函数 test()
	test();

	return 0;
}

4、结果展示

提示:我写的是9*9的扫雷简易版游戏

(4.1)输入的坐标是非法的(即不在坐标的范围)

(4.2)输入的坐标是雷,则游戏提前结束

(4.3)输入的坐标 不是雷,打印四周(八个坐标)有几个雷

(4.4)成功避免所有布置的雷,游戏完美结束

5、END

每天都在学习的路上!
On The Way Of Learning

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2229060.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PointLIO利用unilidar复现

配置宇树激光雷达的时候出现程序报错问题 问题&#xff1a; 问题链接 原因&#xff1a;普通账户没有权限访问设备——也就是ubuntu 存在串口数据读取权限问题 ttyS0设备的用户主为root,所属的组为dialout 同时owner和group都是有相同的rw权限的&#xff0c;但others是没有任何…

Kafka 客户端工具使用分享【offsetexplorer】

前言&#xff1a; 前面我们使用 Spring Boot 继承 Kafka 完成了消息发送&#xff0c;有朋友会问 Kafka 有没有好用的客户端工具&#xff0c;RabbitMQ、RocketMQ 都有自己的管理端&#xff0c;那 Kafka 如何去查看发送出去的消息呢&#xff1f; 本篇我们就来分享一个好用的工具…

5G基础知识

那个工种&#xff1f; FDD 频分双工&#xff08;Frequency Division Duplexing&#xff09;&#xff0c;理解起来很简单&#xff0c;就是把上行和下行业务隔离在两个频段&#xff0c;互不干扰。 而 TDD 时分双工&#xff08;Time-Division Duplexing&#xff09;&#xff0c;是…

python读取视频并转换成gif图片

1. 安装三方库 moviepy 将视频转换成gif&#xff0c;需要使用 moviepy库 确保已经安装了moviepy库 pip install moviepy2. 代码实现&#xff1a; from moviepy.editor import VideoFileClipmyclip VideoFileClip("video.mp4") myclip2 myclip.subclip(0, 10).re…

Webserver(2.4)进程控制

目录 进程退出孤儿进程僵尸进程wait函数waitpid函数 进程退出 exit 刷新IO缓冲区 _exit 孤儿进程 父进程运行结束&#xff0c;但子进程还在运行&#xff0c;这样的子进程称为孤儿进程。 每当出现一个孤儿进程的时候&#xff0c;内核就把孤儿进程的父进程设置为init&#xff…

UART-通用异步收发器

1. UART的基本工作原理 UART通信主要有两个部分构成&#xff1a;发送器和接收器&#xff0c;也就是我们常见的&#xff08;RX接收&#xff0c;TX发送&#xff09;两个独立的线路来实现数据的双向传输&#xff0c;由于是异步的&#xff0c;UART并不需要时钟信号&#xff0c;而是…

linux 互斥锁

首先是概念 互斥锁是可以休眠的。 所以不能在中断中使用&#xff0c; 在中断中只能使用 自旋锁。 然后是 函数&#xff1a; 然后是 open 如果以 NONBLOCK 打开&#xff0c; 遇到 互斥锁怎么办&#xff1f; 总结一下&#xff1a; 1 open() 函数的 阻塞与不阻塞的标志&#…

第72期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

[ 应急响应靶场实战 ] VMware 搭建win server 2012应急响应靶机 攻击者获取服务器权限上传恶意病毒 防守方人员应急响应并溯源

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

Linux运维高手工具全集及功能分类:20+必备神器

文章目录 Linux运维高手工具全集及功能分类&#xff1a;20必备神器一、系统管理与配置1.1 Shell1.2 Ansible1.3 Puppet1.4 Chef 二、监控与告警2.1 Prometheus2.2 Grafana2.3 Zabbix2.4 Nagios2.5 ELK Stack&#xff08;Elasticsearch, Logstash, Kibana&#xff09; 三、容器与…

安卓APP开发中,如何使用加密芯片?

加密芯片是一种专门设计用于保护信息安全的硬件设备&#xff0c;它通过内置的加密算法对数据进行加密和解密&#xff0c;以防止敏感数据被窃取或篡改。如下图HD-RK3568-IOT工控板&#xff0c;搭载ATSHA204A加密芯片&#xff0c;常用于有安全防护要求的工商业场景&#xff0c;下…

什么是x86架构,什么是arm架构

什么是 x86 架构&#xff1f; x86 架构是一种经典的指令集架构&#xff08;ISA&#xff09;&#xff0c;最早由英特尔在 1978 年推出&#xff0c;主要用于 PC、服务器等领域。 它是一种复杂指令集计算&#xff08;CISC&#xff09;架构&#xff0c;支持大量的复杂指令和操作&…

知识分享 | SNP检测试剂盒开发注意事项及启衡星CDMO案例分享

一、SNP检测方法 常规有阵列的杂交、qPCR和测序等多种方法&#xff0c;其中基于qPCR方法的SNP检测试剂盒因具有快速、简便的优势&#xff0c;已有大量检测试剂盒上市。如&#xff1a;人CYP2C9和VKORC1基因检测试剂盒、人类SLCO1B1和ApoE基因分型检测试剂盒、人ADRB1&#xff0…

详解varint,zigzag编码, 以及在Go标准库中的实现

文章目录 为啥需要varint编码为啥需要zigzag编码varint编码解码 zigzag编码解码 局限性 为啥需要varint编码 当我们用定长数字类型int32来表示整数时&#xff0c;为了传输一个整数1&#xff0c;我们需要传输00000000 00000000 00000000 00000001 32 个 bits&#xff0c;而有价…

又一部神作登场,MTC高分8.8认证,堪称年度佳片

威尼斯电影节上&#xff0c;布拉迪科贝特导演的新作《粗野派》大放异彩。这部电影&#xff0c;不仅在现场收获了观众的真诚掌声&#xff0c;甚至被不少专业影评人评为“2024年度最佳电影”&#xff0c;而这个评价背后&#xff0c;是一部作品真正打动人心的力量。 布拉迪科贝特&…

低代码平台如何通过AI赋能,实现更智能的业务自动化?

引言 随着数字化转型的加速推进&#xff0c;企业在日常运营中面临的业务复杂性与日俱增。如何快速响应市场需求&#xff0c;优化流程&#xff0c;并降低开发成本&#xff0c;成为各行业共同关注的核心问题。低代码平台作为一种能够快速构建应用程序的工具&#xff0c;因其可视化…

进程、孤儿进程、僵尸进程、fork、wait简介

进程相关概念 程序和进程 程序&#xff1a;是指编译好的二进制文件&#xff0c;在磁盘上&#xff0c;占用磁盘空间, 是一个静态的概念. 进程&#xff1a;一个启动的程序&#xff0c; 进程占用的是系统资源&#xff0c;如&#xff1a;物理内存&#xff0c;CPU&#xff0c;终端等…

已解决:VS2022一直显示编译中但无法运行的情况

本问题已得到解决&#xff0c;请看以下小结&#xff1a; 关于《VS2022一直显示编译中但无法运行的情况》的解决方案 记录备注报错时间2024年报错版本VS2022报错复现突然VS2022不能启动&#xff0c;一直显示编译中&#xff0c;取消重试无效&#xff0c;重新生成解决方案无效报错…

12. MapReduce全局计数器

一. 计数器概述 在执行MapReduce程序时&#xff0c;控制台的输出中一般会包含如下内容。 这些输出就是MapReduce的全局计数器的输出信息。计数器是用来记录job的执行进度和状态的&#xff0c;它的作用可以理解为日志&#xff0c;方便用户了解任务的执行状况&#xff0c;辅助…

Springboot集成阿里云通义千问(灵积模型)

我这里集成后&#xff0c;做成了一个工具jar包&#xff0c;如果有不同方式的&#xff0c;欢迎大家讨论&#xff0c;共同进步。 集成限制&#xff1a; 1、灵积模型有QPM(QPS)限制&#xff0c;每个模型不一样&#xff0c;需要根据每个模型适配 集成开发思路&#xff1a; 因有…