控制台小游戏—扫雷

news2024/12/26 0:16:56

引言:

在前面一篇中,小编介绍了如何将代码分装在多个文件中的操作。在本篇文章中,小编将介绍一个广受欢迎的小游戏,以帮助大家熟悉这个操作。这个小游戏不仅可以让我们熟悉将代码放在多个文件中的操作,还可以加深我们对数组和函数的理解。快来和小编一起探索扫雷小游戏的乐趣吧!

C:将代码拆分放在多个文件的操作_c语言如何将一个文件的内容分成多个文件-CSDN博客

1、扫雷游戏的起源

扫雷游戏起源于1937年的“方块”游戏,1992年微软发布的Window3.1中加入了该游戏,从此风靡全球。玩扫雷游戏,可以锻炼你的观察和推理能力,培养细心和耐心。

2、畅玩扫雷游戏的设备

网页版的链接:扫雷游戏网页版 - Minesweeper

电脑:鼠标右键点击原始方块,以小旗标记为雷,再右键取消标记。标记的雷数和数字匹配时,点击数字(左右键均可)翻开周围的安全区域。鼠标左键带年纪无标记方块则直接打开。

手机或平板:再触屏上点击方块即标记为雷,再点去除标记。标记的雷数和数字匹配时,点击数字翻开周围的安全区域。长按方块直接打开。(可设置为点击直接打开,或者点击三次打开

关于安卓手机上连击放大问题:【设置】->【智能辅助】->【无障碍】->【放大手势】-关闭。(直接搜索放大手势关闭也可以)有的手机可能搜不到智能辅助。

3、简述一下游戏的设计

随机布置雷,第一次点击不是雷,格子里的数字表示它周围有几个雷(周围指已点击格子为中心,3*3的范围)游戏目标是找出所有雷。“触雷”则输。点击表情重新开始。二选一留到最后,可任选,需先清完其它方块。

简要逻辑实现:

在9*9的棋盘上

随机布置10个雷

排查雷,如果是雷,游戏结束,如果不是雷,就会显示周围有几个雷(图中数字就是显示该数字周围3*3的格子中有几个雷),当把所有不是雷的位置全部找出来,游戏就结束了,游戏胜利。

 

4、关于游戏代码分装

扫雷游戏大概一共200行代码,因此,我们将代码按照不同功能分装在三个文件中

test.c ------main函数,主要是来测试游戏的主逻辑

game.h ----- 函数的声明

game.c ------ 函数的实现

game.h和game.c是游戏实现的逻辑

5、棋盘的设计 

 完成扫雷游戏的运行,我们需要在 9*9 的棋盘上随机布置雷

我们需要将这些数据存放起来,存放数据我们要么使用变量,要么使用数组,这里我们需要存放的是9*9的棋盘,那么我们使用二维数组存放比较合适。

我们需要将布置的雷存放到棋盘中。可以假设数字1是雷。剩下不是雷的位置我们用0来表示。

当我们将雷布置完成后,我们需要排雷,那么该怎么排呢?

有没有发现什么问题?如果我们所要排的点周围雷有一个的情况下就会形成歧义

前面我们用1来表示雷,这里的1又用来排查出来周围雷的个数,这样在后面出现1的话究竟是表示什么呢?

既然如此,我们怎么避免这个问题呢?

我们可以在创建一个棋盘用来排查雷

                 布置雷的棋盘                                    排查出雷的信息

由于两个棋盘是一摸一样的,所以对应的位置是相同的。

到这里我们就可以解决信息拥挤或者歧义的情况,使用两个棋盘可以有效避免以一个棋盘上出现多种标识符,导致编写代码的时候出现紊乱。接下来还有一个问题。

还有一个问题,我们创建的数组该是什么类型的呢?

char board[11][11]

为什么使用字符数组呢?

因为我们对外所展示的是排查出的雷的信息的棋盘,布置好的雷的棋盘是隐藏的,这样的话当我们使用字符数组的时候,在未排查之前所展示的棋盘上每个位置都有*显示                                                                    

主要是神秘。

6、代码的具体实现

6.1 menu函数设计

通过菜单来实现开始游戏,退出游戏等……选项

我们自定义一个函数menu来实现打印菜单

void menu()
{
	printf("———— 1.play ————");
	printf("———— 0.exit ————");
}

6.2 main函数设计

do…while循环用来实现游戏的开始和结束

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}	
	} 
	while (input);

	return 0;
 }

6.3 game函数的设计

首先需要实现棋盘的打印

通过棋盘的设计我们知道有两个字符数组,一个用来存放布置好的雷的信息,一个用来存放排查出雷的的信息,

char mine[11][11]; //用来存放布置好的雷的信息;

char show[11][11]; //用来存放排查出雷的的信息。

在mine 棋盘上,没有布置雷的时候,棋盘上显示的都是字符‘0'

在show 棋盘上,没有排查雷的时候,全部都是' * '。

6.4 InitBoard函数的设计

数组创建好后需要初始化,那应该怎么操作呢?

可以使用InitBoard函数来初始化

由于11大量的重复,后面再修改棋盘大小的时候比较麻烦,因此使用ROW 来表示行,COL来表示列,在game.h文件中定义:

#define ROW 9
#define COL 9

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

char mine[ROWS][COLS]; //用来存放布置好的雷的信息;
char show[ROWS][COLS]; //用来存放排查出雷的的信息。

关于函数的声明我们都放到 game.h 文件中

void InitBoard(char board[ROWS][COLS], int row, int cot,char set);

函数的实现: (放在game.c中)

void InitBoard(char board[11][11], int row, int col,char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}

6.5 DisplayBoard函数的设计

由于棋盘会不断打印,因此我们单独创建一个函数来打印棋盘。

DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);

DisplayBoard的声明我们放在game.h中

void DisplayBoard(char board[ROWS][COLS], int row, int col);

函数的实现:(放在game.c中)

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("------扫雷------\n");
	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");
	}
}

6.6 SetMine函数的设计 

当棋盘打印完成后,我们需要布置雷,设计一个函数

SetMine(mine, ROW, COL);

函数的实现:(放在game.c中)

void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = 10;
	while (count)
	{
		//生成随机的下标
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] != '1');
		{
			board[x][y] = '1';
			count--;
		}
	}
}

6.7 FindMine函数的设计

布置完雷后,我们开始排查雷

FindMine(mine, show, ROW, COL);

排查雷的声明:

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); 

这里面传ROW,COL是因为我们只需要排查9*9的棋盘即可

我们在mine棋盘排查,排查的数据放到show里面,排查的范围是9行9列

函数的实现:(放在game.c中)

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入要排查的位置:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == "1")
			{
				printf("很遗憾,中招了\n");
				DisplayBoard(mine, ROW, COL);
			}
			else
			{
				int c = GetMineCount(mine,x,y);
				show[x][y] = c + '0';
				DisplayBoard(show, ROW, COL);
			}
		}
		else
		{
			printf("输入坐标有误,重新输入\n:");
		}
	}
}

6.8 GetMineCount函数设计

int GetMineCount(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');
}

7、将代码分装到文件中

7.1 test.c文件


#include "game.h"
void menu()
{
	printf("———— 1.play ————");
	printf("———— 0.exit ————");
}
void game()
{
	char mine[ROWS][COLS]; //用来存放布置好的雷的信息;
	char show[ROWS][COLS]; //用来存放排查出雷的的信息。
	//初始化数组
	InitBoard(mine, ROWS, COLS,'0');
	InitBoard(show, ROWS, COLS,'*');

	//打印棋盘
	DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);
	//布置雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(mine, ROW, COL);
	
	//排查雷
	FindMine(mine, show, ROW, COL);
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}	
	} 
	while (input);

	return 0;
 }

7.2 game.h

#include <stdio.h>
#define ROW 9
#define COL 9

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

//初始化棋盘声明
void InitBoard(char board[11][11], int row, int col,char set);
//打印棋盘声明
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷声明
void SetMine(char board[ROWS][COLS], int row, int col);
//排查雷声明
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

7.3 game.c

#include "game.h"
//实现初始化
void InitBoard(char board[11][11], int row, int col,char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}
//实现打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("------扫雷------\n");
	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 SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = 10;
	while (count)
	{
		//生成随机的下标
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] != '1');
		{
			board[x][y] = '1';
			count--;
		}
	}
}
int GetMineCount(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');
}
//排查雷代码实现
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入要排查的位置:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == "1")
			{
				printf("很遗憾,中招了\n");
				DisplayBoard(mine, ROW, COL);
			}
			else
			{
				int c = GetMineCount(mine,x,y);
				show[x][y] = c + '0';
				DisplayBoard(show, ROW, COL);
			}
		}
		else
		{
			printf("输入坐标有误,重新输入\n:");
		}
	}

结语:

还是决定更新一下,闲下来的时候没事做! 

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

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

相关文章

PPT时间轴怎么做?用这款AI软件一键快速生成!

当ppt中需要呈现时间顺序、发展历程甚至是沧海桑田的变化时&#xff0c;很多人都会首选ppt时间轴这种视觉化的方式&#xff0c;它简洁直观&#xff0c;让人可以快速领会ppt想表达的意图&#xff0c;达到一图胜千言的目的。 对于不擅长制作ppt时间轴的人&#xff0c;最好的方式…

2024买一个机械硬盘

1997年&#xff0c;博主配了第一个电脑&#xff0c;CPU是6X86, 您可能没有听说过&#xff0c;那时的硬盘只有2GB~4GB&#xff0c;侯杰在深入浅出MFC中说以后要有大颗的硬盘&#xff0c;当时感觉看到这个单位来描述硬盘&#xff0c;感觉挺有意思。1999年&#xff0c;博主在电脑城…

mujoco_py ERROR: GLEW initalization error: Missing GL version

1. 问题描述&#xff1a; 运行mujoco ROS节点的时候&#xff0c;遇到错误如下&#xff1a; from pkg_resources import load_entry_point Creating window glfw ERROR: GLEW initalization error: Missing GL version 2. 解决方法 在./bashrc文件中添加&#xff1a; export L…

Vue状态管理工具:Pinia

基本概念 Pinia 是一个专为 Vue.js 设计的状态管理库&#xff0c;特别是针对 Vue 3 进行了优化&#xff0c;完美支持Vue3的Composition api 以及TypesCcript语法。它提供了一种更加简单、直观且可扩展的方式来组织和访问应用程序的状态。目前Pinia已经取代Vuex成为vue官方文档…

总结:数字图像处理基础知识

数字图像处理中的图像坐标系是理解图像数据结构和图像处理算法的基础。在计算机视觉和图像处理领域&#xff0c;通常有两种主要的坐标系统用于描述图像中的像素位置&#xff1a;笛卡尔坐标系和像素坐标系。下面我将详细介绍这两种坐标系统及其在数字图像处理中的应用。 1. 笛卡…

T/CECS 10035-2019 绿色建材评价 金属复合装饰材料

一、绿色建材 绿色建材是指在全生命周期内减少对天然资源消耗和减轻对生态环境影响&#xff0c;具有节能、减排、安全、便利和可循环的建材产品&#xff0c;获得绿色产品证书的产品在实际招投标以及品牌宣传中具有绝对优势。 二、认证模式 初始工厂检查产品抽样检验获证后监督…

稳压二极管、肖特基二极管、TVS管、静电ESD管的区别

1.稳压二极管 正向导通电压跟普通二级管一样约为0.7v&#xff0c;反向状态下在临界电压之前截止&#xff0c;在达到临界电压的条件下会处于导通的状态&#xff0c;电压也不再升高&#xff0c;所以用在重要元器件上&#xff0c;起到稳压作用。 稳压二极管主要利用其反向击穿时…

LLM概念梳理(二):检索增强RAG

非常感谢RAG&#xff08;检索增强生成&#xff09;技术详解&#xff1a;基于垂直领域专有数据的 Chatbots 是如何实现的&#xff0c;这篇文章对 RAG 技术进行了详细的描述。我根据自己的理解&#xff0c;并且按照代码思路重新进行整理。 RAG 技术看似神奇&#xff0c;其本质是…

2024.8.22(Docker)

一、回顾 高并发集群 eleme后端登录模块 1、数据库 1.主从复制(高可用) 2.传统的主从复制 3.gtids事务型的主从复制 4.注意 &#xff08;1&#xff09;server_id唯一 &#xff08;2&#xff09;8.x版本需要get_ssl_pub_key &#xff08;3&#xff09;5.x不需要 &#xff08;4…

ts枚举类型校验,提示枚举信息

ts 类型验证&#xff0c;提示枚举信息 const eventTypeList [MOUSE_MOVE, // 鼠标移动LEFT_CLICK // 左键单击// MOUSE_OUT, ] as consttype EventTypeList typeof eventTypeList[number]

FST(Finite State Transducer)

有限状态转换器&#xff08;Finite State Transducer&#xff0c;简称FST&#xff09;是一种计算模型&#xff0c;它是有限状态自动机&#xff08;Finite State Automaton&#xff0c;简称FSA&#xff09;的扩展。FSA是一种理论计算模型&#xff0c;用于表示和处理正则语言&…

苹果iOS / iPadOS 18 beta 7版本发布,或将是最后一个iOS / iPadOS 18beta版本

今日苹果公司向 iPhone 和 iPad 用户推送了 iOS/iPadOS 18 开发者预览版 Beta 7 更新&#xff08;内部版本号&#xff1a;22A5346a&#xff09;&#xff0c;本次更新距离上次发布 Beta/RC 间隔 8 天。 值得注意的是&#xff0c;本次更新版本号以a结尾&#xff0c;意味着如果不…

国密算法SSL证书:守护网络安全的利器

国密算法SSL证书是基于中国自主研发的密码算法标准生成的安全套接层证书&#xff0c;主要用于保护网站和应用程序的数据传输安全。该证书采用SM2椭圆曲线公钥密码算法、SM3密码哈希函数和SM4对称密钥加密算法&#xff0c;确保数据传输过程中的机密性、完整性和抗攻击性。 国密…

KKView远程Microsoft Remote Desktop

Microsoft Remote Desktop&#xff1a;高效稳定的远程连接解决方案 在当今这个信息化、网络化的时代&#xff0c;远程桌面工具成为了许多用户进行远程办公、学习及技术支持的重要工具。其中&#xff0c;Microsoft Remote Desktop以其高效稳定的连接性能、强大的跨平台支持及出…

学校每年比用的招生简章在线制作平台!

每年招生季节&#xff0c;各大中小学及高校都会面临一个重要的任务&#xff1a;更新和发布招生简章。这不仅是一份简单的招生说明&#xff0c;它更是学校向外界展示自身特色、招生政策和培养目标的重要窗口。随着信息技术的发展&#xff0c;传统的纸质招生简章逐渐演变为在线制…

通过拖拽添加dom和一些属性

将图片通过拖拽添加到指定位置 <template><div class"draggle-box"><imgclass"draggle-source"src"/assets/bg/cat.jpg"dragstart"handleDragStart($event, 图片)"/><divclass"draggle-target"dragove…

嵌入式学习——(Linux高级编程——线程控制)

线程的互斥 一、互斥的重要性 在多线程编程中&#xff0c;互斥机制至关重要。当多个线程同时访问临界资源时&#xff0c;如果没有有效的互斥控制&#xff0c;可能会导致数据不一致、资源竞争等问题。通过互斥锁&#xff0c;可以确保在任何时刻只有一个线程能够访问临界资源&am…

Axure RP 9高手速成秘籍:解锁终极快捷键,设计效率飙升10倍!

Axure RP 9作为一款功能强大的原型设计工具&#xff0c;提供了丰富的快捷键来加速设计流程。以下是一份详尽的Axure RP 9快捷键大全&#xff0c;旨在帮助用户更高效地完成设计工作。 一、文件操作 新建&#xff1a;Ctrl N&#xff08;Windows&#xff09;/ Command N&#…

【LLM大模型】本地玩转多模态Llama3

一般开源的LLM&#xff0c;例如Llama3和Qwen2等&#xff0c;只支持文本的输入&#xff0c;只能理解文本的内容&#xff0c;实现基于文本的逻辑推理和意图识别。 但是一些Chatbot&#xff0c;例如GPT-4V&#xff0c;就是拥有视觉能力&#xff0c;能够理解图片内容&#xff0c;能…