C语言——简易版扫雷

目录

前言

​编辑

 游戏规则

 游戏结构的分析

游戏的设计 

使用多文件的好处有以下几点:

 游戏代码实现

框架(test.c)

 game函数(test.c)

InitBoard初始化(game.c)

 Print打印棋盘(game.c)

Setmine设置雷(game.c)

Findmine排查雷(game.c) 

GetMine  

game.h

game.c

exe程序

 Debug和Release的区别



前言

扫雷游戏是一种益智类的游戏,目标是通过揭示方块上的数字来找到不带雷的方块,避免触雷。 


 游戏规则

玩家的目标是根据已翻开的方块信息来推测出地雷的位置,并避开它们。每个方块要么是空白,要么显示数字。数字表示该方块周围八个方向上的地雷数量。通过使用数字信息和逻辑推理,玩家可以确定哪些方块是安全的,哪些是地雷。当玩家翻开所有非地雷方块时,游戏胜利。如果玩家不慎踩到地雷,游戏失败。


 游戏结构的分析

扫雷的过程中,布置的雷和排查出的雷的信息都需要存储,所以我们需要⼀定的数据结构来存储这些 信息。

所以我们首先会想到一个9*9的矩阵。

我们将有雷的设置为“1”,没雷的地方设置为“0”

示例

0123456789
1010000000
2000000000
3000001010
4100100000
5000000000
6000000000
7001000001
8000010000
9100000100

假设我们排查(5,3),在(5,3)周围的一圈有雷,则会在屏幕上记起来。

这就是我们想要设计的样子,但是当我们想访问(6,9)的时候,我访问就会越界,到了界外去了,为了解决这一问题,我们将表格变成11*11的模型,这就能很好的解决这个问题。

0123456789
1010000000
2000000000
3000001010
4100100000
5000000000
6000000000
7001000001
8000010000
9100000100

继续分析,我们已经设置了数字“1”为雷,“0”为非雷,当我们排查到一个雷时,需要将这个雷的信息储存起来,然后将它打印出来,作为排雷的重要参考信息的。。那这个雷的个数信息存放在哪⾥呢?如果存放在布 置雷的数组中,这样雷的信息和雷的个数信息就可能或产⽣混淆和打印上的困难。

将雷和⾮雷的信息不要使⽤数字,使⽤某些字符就⾏,这样就避免冲 突了,但是这样做棋盘上有雷和⾮雷的信息,还有排查出的雷的个数信息,就⽐较混杂,不够⽅便。

 这⾥我们采⽤另外⼀种⽅案,我们专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。这样就互不⼲扰了,把雷布置到 mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期 排查参考。

mine数组

01234567891011
0
1‘1’‘0’‘0’‘0’‘0’‘0’‘0’‘1’‘0’‘0’
2‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘1’
3‘0’‘0’‘0’‘0’‘1’‘0’‘0’‘0’‘0’‘0’
4‘0’‘1’‘0’‘0’‘0’‘0’‘0’‘0’‘1’‘0’
5‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’
6‘0’‘0’‘0’‘0’‘1’‘0’‘0’‘0’‘0’‘0’
7‘1’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘1’‘0’
8‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’
9‘0’‘0’‘0’‘0’‘1’‘0’‘0’‘0’‘0’‘0’
10‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’‘0’
11

char mine[11][11] = {0};//⽤来存放布置好的雷的信息
 
char show[11][11] = {0};//⽤来存放排查出的雷的个数信息
 

对于show数组就是将所有‘0’和‘1’换成‘*’这里就不展示了,不水字数了。


游戏的设计 

使用多文件的好处有以下几点:

  • 1. 组织性好:将代码划分到不同的文件中,可以更好地组织和管理代码。每个文件可以分别负责不同的功能模块,使代码结构更清晰。

  • 2. 可维护性强:多文件的编程方式使得修改或更新某个功能模块变得更加简单。只需修改相应的文件,不需要修改整个程序。

  • 3. 可重用性高:将一些常用的函数或功能封装到单独的文件中,可以在多个项目中复用这些代码。

  • 4. 编译效率高:当调用某个函数时,编译器只需要编译包含该函数的文件,而不需要重新编译整个程序,提高了编译速度。

  • 5. 可扩展性强:如果需要添加新的功能模块,只需添加一个新的文件,不会对原有代码造成影响。

  • 6. 可测试性好:每个文件可以独立地进行测试,便于定位和修复问题。

总之,使用多文件的编程方式可以提高代码的组织性、可维护性、可重用性和扩展性,提高编译效率和测试效率。

在这个扫雷中我们需要:

game.h         ⽂件中写游戏需要的数据类型和函数声明等

game.c         ⽂件中写游戏中函数的实现等

text.c            ⽂件中写游戏的测试逻辑


 游戏代码实现

框架(test.c)

我们写个基础的框架。将头文件都放在game.h里面,就需要包含头文件,而我们自己的头文件要用“”。

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
int main()
{
	text();
	return 0;
}

我们进入text函数是,打印菜单menu(),让玩家进行选择,是进入游戏,还是退出游戏。

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

 函数进来是直接do-while进行打印菜单,然后供玩家选择,选择1进入游戏,0退出游戏,若输入以外的内容则会提示出错误,需要重新输入。

void text()
{
	
	int input = 0;
	srand((unsigned int)time(NULL));//这是播种由函数 rand 使用的随机数发生器。
    //我们先放在这里
	do
	{
		menu();
		printf("请输入你的选择:");
        scanf("%d", &input);
		switch(input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
            printf("选择错误,请重新输入:");
			break;
		}
	} while (input);
}

 game函数(test.c)

我们整体思路是将数组初始化,mine初始化为‘0’,show初始化为‘*’;随后布置地雷,我们初始化和布置雷好后都能打印一下看看是否符合我们的要求。最后进行排查地雷,将所有的雷找出来就行了。

void game()
{
	char mine[ROWS][COLS] ;
	char show[ROWS][COLS] ;

	//初始化
	InitBoard(mine, ROWS, COLS, '0'); 
	InitBoard(show, ROWS, COLS, '*');

	//打印棋盘
	Print(show, ROWS, COLS);
	/*Print(mine, ROWS, COLS);*/

	//布置地雷
	Setmine(mine, ROW ,COL);

	//排查地雷
	Findmine(mine,show,ROW,COL);
}

InitBoard初始化(game.c)

对数组mine和show进行初始化,将mine的数组全部初始化为‘0’,show初始化为‘*’。如果只是简单的在数组中初始化化‘0’,‘*’。我们传入应该char set就能够让代码更加灵活,不用在写一样的代码浪费时间和空间。

void InitBoard(char arr[ROWS][COLS], int rols, int cols,char set)
{
	for (int i = 0; i < rols; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			arr[i][j] = set;//'0' , '*'
		}
	}
}

 Print打印棋盘(game.c)

对数组mine和数组show进行打印虽然我们设置的是11*11的棋盘,但是对于玩家来说他们只需要再9*9的棋盘里面进行排查雷就行了,所以我们打印的是9*9的棋盘。在加上坐标,能让玩家更精确的定位。

void Print(char arr[ROWS][COLS], int rols, int cols)
{
	printf("-----扫雷游戏——————\n");//让界面整体更加美观
	for (int i = 0; i < rols - 1 ; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i < rols - 1; i++)
	{
		printf("%d ", i);
		for (int j = 1; j < cols - 1; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

Setmine设置雷(game.c)

我们只需要在9*9的棋盘随机布置雷就行了,这时需要用到rand这个函数rand()%row = 8 再加1。

void Setmine (char board[ROWS][COLS], int row, int col)
{
	int count = minebox;
	while(count)
	{
		//设置行数和列数的随机
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

需要的头文件 

 rand---->  #inlcude<stdlib.h>

 time---->  #include<time.h>

Findmine排查雷(game.c) 

开始我们需要踹按创建变量x和y,供玩家输入坐标,我们的坐标只有1~9所以需要  0<x<10,0<y<10作为条件,这个坐标之外的为非法最标,需要重新输入如果玩家排查的坐标是雷,那么游戏结束,并打印棋盘。如果不是雷,我们需要统计一下它周围有几个雷,这就需要统计雷GetMine,将雷的信息传到数组show上,个数统计出来还要加上‘0’;如果仅仅是这样的话游戏是不会结束的,还需要给whle加上条件win< row * col - minebox(minebox是雷的数量),每次没排查到雷级win++。

如果有耐心的坚持去玩,那么肯定是能玩完的,前提是没被炸死哈。

void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win< row * col - minebox)
	{
		printf("请输入要扫的坐标:");
		scanf("%d %d", &x, &y);
		if (x > 0 && x < row && y >0 && y < col)
		{
			system("cls");
			if (mine[x][y] == '1')
			{
				printf("你被炸死了,游戏失败\n");
				Print(show, ROWS, COLS);
				break;
			}
			else 
			{
				int count = GetMine(mine, x, y);
				show[x][y] = count + '0';
				Print(show, ROWS, COLS);
				win++;
			}
		}
		else
		{
			printf("非法输入\n");
		}
	}
    if (win == row * col - minebox)
	{
		printf("恭喜你,排雷成功\n");
		Print(mine, ROW, COL);
	}

}

system("cls")的头文件跟rand的一样

GetMine  

static是静态的意思,静态函数只能在声明它的文件中可见,其他文件不能引用该函数。

‘1’的值是49;'0'的值是48;‘1’-‘0’=1是个整数。我们将周边的数都加起来-8*‘0’就能得到雷的数。

static int GetMine(char mine[ROWS][COLS], int x, int y)
{
	return (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] -
		8 * '0');
}

game.h

#define ROW 9 //行数
#define COL 9 //列数

#define ROWS ROW+2 
#define COLS COL+2

#define minebox 10 //雷的个数

#include<stdio.h>   //main函数的头文件
#include<time.h>    //time函数的头文件
#include<stdlib.h>  //system,rand函数的头文件

//初始化棋盘
void InitBoard(char arr[ROWS][COLS], int rols, int cols, char set);


//打印棋盘
void Print(char arr[ROWS][COLS], int rols, int cols);

//设置雷
void Setmine(char arr[ROWS][COLS], int x, int y);

//找雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c

同理,game.c要使用game.h的东西也得包含头文件。

到这里,我们这个简易版的扫雷就实现了。

怎么把代码编程可发布的exe程序呢?


exe程序

  1. 将debug模式改为Release模式。
  2. 打开“项目”点击属性。
  3. 打开“C/C++”下的“代码生成”将“运行库”改为多线程(/MT)
  4. “Ctrl+F5”运行程序,这里exe的程序就出现在文件夹里面了。
  5. 打开我们存放代码的文件夹找到x64里面会有两个文件夹,一个是Debug,一个是Relase,点开,我们就能看到一个exe的程序后缀,这样就能直接发给其他人。

 Debug和Release的区别

Debug和release是软件开发中常见的两种构建(build)模式,它们在编译、优化和调试方面有以下区别:

  • 1. 编译方式:Debug模式通常会生成包含调试信息的可执行文件,以便在调试过程中能够准确定位代码的问题。而release模式会采用更高级别的优化和压缩,生成体积更小、性能更高的可执行文件。
  • 2. 优化级别:Debug模式通常会使用较低级别的优化,以便更好地保留源代码的结构和逻辑,使得调试更容易。而release模式会使用更高级别的优化,以提高程序的运行性能。
  • 3. 调试信息:Debug模式会保留更多的调试信息,如变量名、函数名等,以便在调试器中能够查看和修改这些信息。而release模式会舍弃部分调试信息,以减小可执行文件的体积。
  • 4. 异常处理:Debug模式通常会提供更多的异常信息,使得在程序出错时能够更方便地定位问题。而release模式会舍弃部分异常信息,以提高程序的性能和稳定性。

总之,Debug模式适用于开发和调试阶段,能够提供更多的调试信息和更好的可读性;而release模式适用于发布阶段,能够提供更高的性能和较小的体积。在实际开发中,通常会进行Debug模式的开发和调试,然后再切换到release模式进行最终的发布。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【物联网设备端开发】FastBee Arduino固件开发指南

目录 一、收集数据 二、打开FastBeeArduino 源码 三、修改 Config.cpp 文件 四、修改物模型数据 五、小程序配网 本文以 WeMOS D1 R1&#xff08;8266WIFI 模块&#xff09;固件开发为例&#xff0c;实现以下功能&#xff1a; 设备认证设备 Mqtt 交互Wifi 类设备配网 一…

vue学习笔记23-组件事件⭐

组件事件 在组件的模板表达式中&#xff0c;可以直接使用$emit方法触发自定义事件&#xff1b;触发自定义事件的目的是组件之间传递数据 好好好今天又碰到问题了&#xff0c;来吧来吧 测试发现其他项目都可以 正常的run ,就它不行 搜索发现新建项目并进入以后&#xff0c;用指…

搭建mysql主从复制(主主复制)

1&#xff1a;设主库允许远程连接(注意&#xff1a;设置账号密码必须使用的插件是mysql_native_password&#xff0c;其他的会连接失败) #切换到mysql这个数据库&#xff0c;修改user表中的host&#xff0c;使其可以实现远程连接 mysql>use mysql; mysql>update user se…

使用C#创建服务端Web API

前言 C# Web API 是一种基于 .NET 平台&#xff08;包括但不限于.NET Framework 和 .NET Core&#xff09;构建 HTTP 服务的框架&#xff0c;用于创建 RESTful Web 服务。REST&#xff08;Representational State Transfer&#xff09;是一种软件架构风格&#xff0c;它利用HT…

linux中查看目录文件(ls)用法:

查看目录下的文件&#xff1a;ls&#xff08;list&#xff09; 作用 查看目录下的内容 格式 ls -参数 操作对象参数 参数功能-l以长格形式显示文件和目录的详细信息,ls命令默认只显示名称的短格式。-d显示指定目录本身的信息,而不显示目录下的各个文件和子目录的信息。-…

【机器学习】机器学习是什么?用在哪里?怎么用?

1.机器学习是什么&#xff1f; 机器学习&#xff08;Machine Learning&#xff09;是人工智能的一个分支&#xff0c;它是一种通过对数据进行训练和学习&#xff0c;让计算机系统从中获取知识并改善性能的方法。简而言之&#xff0c;机器学习使计算机具有从数据中学习并自动改…

信息系统项目管理师009:消费互联网(1信息化发展—1.3现代化创新发展—1.3.3 消费互联网)

文章目录 1.3.3 消费互联网1.基本属性2.应用新格局 1.3.3 消费互联网 消费互联网是以个人为用户&#xff0c;以日常生活为应用场景的应用形式&#xff0c;满足消费者在互联网中的消费需求而生的互联网类型。消费互联网以消费者为服务中心&#xff0c;针对个人用户提升消费过程的…

机器学习模型—支持向量机 (SVM)

机器学习模型—支持向量机 (SVM) 支持向量机 (SVM) 是一种强大的机器学习算法,用于线性或非线性分类、回归,甚至异常值检测任务。SVM 可用于各种任务,例如文本分类、图像分类、垃圾邮件检测、笔迹识别、基因表达分析、人脸检测和异常检测。SVM 在各种应用中具有适应性和高效…

Github上哪些好用的工具

专注于web漏洞挖掘、内网渗透、免杀和代码审计&#xff0c;感谢各位师傅的关注&#xff01;网安之路漫长&#xff0c;与君共勉&#xff01; Qexo-爱写博客的师傅强烈推荐 漂亮的 Hexo 静态博客编辑器。该项目是基于 Django 的 Hexo 静态博客管理后台&#xff0c;支持文章管理、…

【Linux杂货铺】操作系统

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 冯诺依曼体系结构 &#x1f4c2; 拓展问题&#xff1a;程序为什么要被加载到内存&#xff1f; &#x1f4c2; 主机与主机的交互 &#x1f4c1; 操作系统的概念 &#x1f4c2; 作用 &#x1f4c2; 理解“管理” &#x…

Hadoop学习3:问题解决

文章目录 问题解决1. ERROR: but there is no HDFS_NAMENODE_USER defined2. JAVA_HOME is not set and could not be found.3. Hadoop-DFS页面访问不了4. namenode格式化失败&#xff0c;或者dfs页面打开失败5. ERROR: but there is no YARN_RESOURCEMANAGER_USER defined. Ab…

YOLOv5独家改进:backbone改进 | 最新大卷积核CNN架构UniRepLKNet,ImageNet 88% | CVPR2024

💡💡💡本文独家改进:大核卷积一统多种模态!RepLK正统续作UniRepLKNet,代替YOLOv5 Backbone 改进结构图如下: 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/category_12511931.html 💡💡💡全网独家首发创新(原创),适合paper !!! 💡…

对于双列集合map的学习

双列集合 特点 1.双列集合一次需要存一对数据&#xff0c;分别是键和值。 2.键和值一一对应&#xff0c;键不能重复&#xff0c;值能重复。 3.键值这个整体我们称之为键值对或者键值对对象&#xff0c;在java中叫做Entry对象。 Map的常见API Map是双列集合的顶层接口&…

ChatGLM:基于ChatGLM-6B使用ptuning进行微调,实现类instruction的效果

由于业务需要&#xff0c;调研下怎么训练一个虚拟角色出来&#xff0c;所以找了一些文档参考&#xff0c;其中有一个基于ChatGLM-6B使用ptuning进行微调&#xff0c;实现类instruction的效果的现成的项目&#xff0c;给大家分享下。 一、介绍 由于ChatGLM-6B 不支持instructio…

五子棋小游戏(sut实验报告)

实验目的 实现人与人或人与电脑进行五子棋对弈 实验内容 启动游戏&#xff0c;显示游戏参数设置界面&#xff0c;用户输入参数后进入游戏界面&#xff0c;显示棋盘及双方博弈过程&#xff0c;游戏过程中可选择退出游戏。判定一方获胜后结束本局游戏&#xff0c;可选择继续下…

Qt/QML编程之路:基于QWidget编程及各种2D/3D/PIC绘制的示例(45)

关于使用GWidget,这里有一个示例,看了之后很多图形绘制,控件使用,及最基本的QWidget编程都比较清楚了。ui的绘制: 运行后的界面如 工程中有非常丰富的关于各种图形的绘制,比如上图中circle,还有image。有下面一段readme的说明: # EasyQPainter Various operation pra…

容量治理三板斧:扩容、限流与降级

前言 随着现代软件系统日益复杂和用户规模的不断增长&#xff0c;分布式架构成为了保持系统高可用性与高性能的标准解决方案。然而&#xff0c;随之而来的是对系统容量治理的新挑战。在这样的背景下&#xff0c;容量治理成为了分布式系统设计和运维中不可或缺的一环。要确保系…

Java毕业设计 基于SpringBoot vue学科竞赛项目管理系统

Java毕业设计 基于SpringBoot vue学科竞赛项目管理系统 SpringBoot vue 学科竞赛项目管理系统 功能介绍 学生&#xff1a;登录 验证码 首页推广 图片轮播 竞赛通知 我的比赛队伍 组队招募 获奖通告 系统公告 统计分析 修改密码 修改个人信息 投诉建议 教师&#xff1a;登录 …

腾讯云和阿里云4核8G云服务器多少钱一年和1个月费用对比

4核8G云服务器多少钱一年&#xff1f;阿里云ECS服务器u1价格955.58元一年&#xff0c;腾讯云轻量4核8G12M带宽价格是646元15个月&#xff0c;阿腾云atengyun.com整理4核8G云服务器价格表&#xff0c;包括一年费用和1个月收费明细&#xff1a; 云服务器4核8G配置收费价格 阿里…

以某厂商方案为例,讲一下如何手工配置传统网络到SD-WAN网络的改造实施

正文共&#xff1a;1024 字 8 图&#xff0c;预估阅读时间&#xff1a;3 分钟 假设有这样一张网络&#xff0c;其中RTA和PCA表示某公司的A分支&#xff0c;通过中国电信CT路由器接入互联网ISP&#xff1b;RTB和PCB表示某公司的B分支&#xff0c;通过中国联通CU路由器接入互联网…