C语言项目:数组与函数实践:扫雷游戏

目录

目录:

1.扫雷游戏分析与设计

    1.1扫雷游戏的功能说明:

     1.1.1使用控制台实现经典扫雷的游戏

     1.1.2游戏可以通过菜单实现继续玩或者退出游戏

     1.1.3扫雷棋盘是9*9的格子

     1.1.4默认随机布置10个雷

    1.1.5 可以排查雷

2.扫雷游戏的代码实现

 1.遇到的问题

2.如何去实现 

3.扫雷游戏的扩展

4.最终代码


1.扫雷游戏分析与设计

    1.1扫雷游戏的功能说明:

     1.1.1使用控制台实现经典扫雷的游戏
     1.1.2游戏可以通过菜单实现继续玩或者退出游戏
     1.1.3扫雷棋盘是9*9的格子
     1.1.4默认随机布置10个雷
    1.1.5 可以排查雷

           1.如果位置不是雷,就显示周围有几个雷

            2.如果位置是雷,就炸死结束游戏

            3.把除10个雷之外的所有非雷都找出来,排雷成功,游戏结束

2.扫雷游戏的代码实现

 1.遇到的问题

test.c //游戏的测试逻辑

game.c game.h //游戏逻辑的实现

扫雷过程中,布置的雷和排查出的雷的信息都需要存储,所以我们需要一定的数据结构来存储这些信息,因为我们需要在9*9的棋盘上布置雷的信息和排查雷,我们首先想到的就是创建一个9*9的数组来存放信息,

如果这个位置布置雷,我们就存放1,没有布置雷就存放0.

假如我们排查(2,5)这个坐标时,我们访问周围的一圈8个黄色位置,统计周围雷的个数是1 

遇到的问题:

第一,统计的个数是1放在哪呢?如果放在(2,5)这个位置,会产生歧义,1到底是排查出的雷,还是(2,5)自己是雷

为了解决这件事,我们我们专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。

这样就互不⼲扰了,把雷布置到 mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期排查参考。 同时为了保持神秘,show数组开始时初始化为字符 '*',为了保持两个数组的类型⼀致,可以使⽤同⼀ 套函数处理,mine数组最开始也初始化为字符'0',布置雷改成'1'。

第二:假如我们排查(8,6)这个坐标,我们访问周围一圈八个位置,统计周围雷的个数时,最下面的三个坐标就会越界,为了防止越界,给数组扩大一圈,雷还是布置在9*9的坐标上,周围一圈不去布置雷就OK了,这样就解决了越界的问题。所以我们将存放数据的数组创建成11*11是比较合适。

2.如何去实现 

  •  创建文件进行分布操作 
  1. test.c: //文件中写游戏的测试逻辑
  2. game.c//文件中写游戏中函数的实现
  3. game.h//文件中写游戏需要的数据类型和函数声明

//mine数组中存放布置好的雷的信息 

//show数组中存放的是排查出的雷的信息

 

 其中为了方便后续的引用,我在game.h文件中重定义了行(ROW,ROWS)、列(COL,COLS)、和要排的雷的个数(EASY_COUNT):

  •  页面设计
void menu()
{
	printf("***************************\n");
	printf("******* 1.play  ***********\n");
	printf("******* 0.exit  ***********\n");
	printf("***************************\n");
}

void test()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);//1 0 x
		switch (input)
		{
		case 1:
			game();
			/*printf("扫雷\n");*/
			break;
		case 0:
			printf("游戏结束,退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
}

 在test.c中写入,要用到循环,这些还是比较简单的。

  • 函数的实现

1.初始化棋盘 initboard(用于存储雷的信息‘0’与‘1’,‘0’表示无雷,‘1’表示有雷,用‘*’掩盖雷的信息)

game.c中实现下列函数

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

 test.c中写入下列函数

 2.打印棋盘给用户看

game.c写入

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	//打印列好
	printf("------扫雷游戏-----\n");
	for (i = 0; i <= col; i++)
	{
		printf("%2d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%2d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%2c ", arr[i][j]);
		}
		printf("\n");
	}
}

 test.c写入(前面谈到了,我们是要用两个棋盘,打印只需要一个给用户,另外一个是调试用的,验证是否我们的代码是否正确)

3.布置雷的函数(用随机数生成,将是‘0’的数组中的元素布置为‘1’,用count计数,count=EASY_COUNT 也就是10,每布置完一个雷就让count减一)

game.c写入

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

test.c 写入

4.排查雷的函数(设置变量x,y,用于表示要输入的坐标,win表示排雷的过程,如果xin=row*col-EASY_COUNT,说明除了雷的位置都已经排除,剩下的都是雷,也就是排雷成功,如果输入的坐标刚好是‘1’的位置,那么就说明排雷失败,打印输出“你被炸死了”,如果排雷的坐标不存在,就显示输入错误,并重新输入)

game.c写入

第一个函数主要为Findmind函数作用,所以不需要写入到game.h,我们可以加入static进行限制。

static int Get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		int j = 0;
		for (j = y - 1; j <= y + 1; j++)
		{
			count += (mine[i][y] - '0');
		}
	}
	return count;
}
void FindMind(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-EASY_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf("%d %d", &x, &y);
		//判断坐标的有效性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了\n");
					DisplayBoard(mine, ROW, COL);
					break;
				}
				else
				{
					//该坐标不是雷,就得统计坐标周围有几个雷
					int count = Get_mine_count(mine, x, y);
					show[x][y] = count + '0';
					DisplayBoard(show, ROW, COL);
					win++;
				}
			}
			else
			{
				printf("该坐标已经被排查了,重新输入坐标\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

test.c写入 

 

  • 主函数声明函数 
  • game.h声明函数

3.扫雷游戏的扩展

可以自己去尝试实现如下扩展的内容。

4.最终代码

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 InitBoard(char arr[ROWS][COLS], int rows, int cols,char set);

//打印棋盘
void DisplayBoard(char arr[ROWS][COLS], int row, int col);

//布置雷
void SetMine(char arr[ROWS][COLS],int row,int col);

//排查雷
void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row,int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

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

void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	//打印列好
	printf("------扫雷游戏-----\n");
	for (i = 0; i <= col; i++)
	{
		printf("%2d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%2d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%2c ", arr[i][j]);
		}
		printf("\n");
	}
}

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

//static int Get_mine_count(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';
//}

static int Get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		int j = 0;
		for (j = y - 1; j <= y + 1; j++)
		{
			count += (mine[i][y] - '0');
		}
	}
	return count;
}

void FindMind(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-EASY_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf("%d %d", &x, &y);
		//判断坐标的有效性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了\n");
					DisplayBoard(mine, ROW, COL);
					break;
				}
				else
				{
					//该坐标不是雷,就得统计坐标周围有几个雷
					int count = Get_mine_count(mine, x, y);
					show[x][y] = count + '0';
					DisplayBoard(show, ROW, COL);
					win++;
				}
			}
			else
			{
				printf("该坐标已经被排查了,重新输入坐标\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"game.h"
void menu()
{
	printf("***************************\n");
	printf("******* 1.play  ***********\n");
	printf("******* 0.exit  ***********\n");
	printf("***************************\n");
}

void game()
{
	//完成扫雷游戏
	//mine数组中存放布置好的雷的信息
	char mine[ROWS][COLS] = { 0 };//数组全部初始化为‘0’,写‘0’不能全部初始化,只能初始化一部分

	//show数组中存放的是排查出的雷的信息
	char show[ROWS][COLS] = { 0 };//数组全部初始化为‘*’
	//初始化棋盘
	InitBoard(mine,ROWS,COLS,'0');//二维数组传参
	InitBoard(show, ROWS, COLS, '*');
	
	//布置雷
	//就是在9*9的棋盘上随机布置10个雷
	SetMine(mine,ROW,COL);
	/*DisplayBoard(mine, ROW, COL);*/

	//打印棋盘(考虑用户体验)
	/*DisplayBoard(mine, ROW, COL);*/
	DisplayBoard(show, ROW, COL);

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

void test()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);//1 0 x
		switch (input)
		{
		case 1:
			game();
			/*printf("扫雷\n");*/
			break;
		case 0:
			printf("游戏结束,退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}

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

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

相关文章

蓝桥杯练习题总结(二)dfs题、飞机降落、全球变暖

一、飞机降落 问题描述&#xff1a; N架飞机准备降落到某个只有一条跑道的机场。其中第 i 架飞机在 时刻到达机场上空&#xff0c;到达时它的剩余油料还可以继续盘旋 个单位时间&#xff0c;即它最早可以于 1, 时刻开始降落&#xff0c;最晚可以于时刻开始降落。降落过程需要个…

【TB作品】MSP430,单片机,Proteus仿真,数字音乐盒,蜂鸣器音乐仿真

文章目录 题目要求如何根据简谱编曲仿真图代码介绍宏定义部分全局变量部分LCD 控制函数按键检测和处理函数蜂鸣器控制函数主函数部分 获取代码和仿真 题目要求 86 数字音乐盒的制作 1 设计要求 制作一个数字音乐盒,盒内存有3首乐曲,每首不少于30s。采用LCD显示乐曲信息, 开机时…

Word2vec学习笔记

&#xff08;1&#xff09;NNLM模型&#xff08;神经网络语言模型&#xff09; 语言模型是一个单纯的、统一的、抽象的形式系统&#xff0c;语言客观事实经过语言模型的描述&#xff0c;比较适合于电子计算机进行自动处理&#xff0c;因而语言模型对于自然语言的信息处理具有重…

TnT-LLM: Text Mining at Scale with Large Language Models

TnT-LLM: Text Mining at Scale with Large Language Models 相关链接&#xff1a;arxiv 关键字&#xff1a;Large Language Models (LLMs)、Text Mining、Label Taxonomy、Text Classification、Prompt-based Interface 摘要 文本挖掘是将非结构化文本转换为结构化和有意义的…

分布式锁中的王者方案 - Redission

文章目录 5.1 分布式锁-redission功能介绍5.2 分布式锁-Redission快速入门5.3 分布式锁-redission可重入锁原理5.4 分布式锁-redission锁重试和WatchDog机制5.5 分布式锁-redission锁的MutiLock原理 5.1 分布式锁-redission功能介绍 基于setnx实现的分布式锁存在下面的问题&am…

JVM垃圾收集器你会选择吗?

目录 一、Serial收集器 二、ParNew收集器 三、Paralle Scavenge 四、Serial Old 五、Parallel Old 六、CMS收集器 6.1 CMS对处理器资源非常敏感 6.2 CMS容易出现浮动垃圾 6.3 产生内存碎片 七、G1 收集器 八、如何选择合适的垃圾收集器 JVM 垃圾收集器是Java虚…

CSS3新属性(学习笔记)

一、. 圆角 border-radius:; 可以取1-4个值&#xff08;规则同margin&#xff09; 可以取px和% 一般用像素&#xff0c;画圆的时候用百分比&#xff1a;border-radius:50%; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&q…

Axure RP 9 for Mac中文激活版:原型设计工具

Axure RP 9 for Mac是一款值得设计师信赖的原型设计工具。它以其卓越的性能和稳定的运行赢得了广大用户的赞誉。 软件下载&#xff1a;Axure RP 9 for Mac中文激活版下载 在Axure RP 9中&#xff0c;您可以尽情发挥自己的设计才华&#xff0c;创造出独一无二的原型作品。无论是…

MySQL5.6.11安装步骤(Windows7 64位)

MySQL5.6.11安装步骤&#xff08;Windows7 64位&#xff09; 1. 下载MySQL Community Server 5.6.21&#xff0c;注意选择系统类型&#xff08;32位/64位&#xff09; 2. 解压MySQL压缩包 将以下载的MySQL压缩包解压到自定义目录下。 3. 添加环境变量 变量名&#xff1a;MYS…

重大机遇,腾讯云优惠券免费领取入口整理,千元代金券一键搞定

腾讯云代金券领取渠道有哪些&#xff1f;腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券&#xff0c;大家也可以在腾讯云百科蹲守代金券&#xff0c;因为腾讯云代金券领取渠道比较分散&#xff0c;腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

蓝桥杯刷题|03普及-真题

[蓝桥杯 2017 省 B] k 倍区间 题目描述 给定一个长度为 N 的数列&#xff0c;​,,⋯&#xff0c;如果其中一段连续的子序列 ​,,⋯ (i≤j) 之和是 K 的倍数&#xff0c;我们就称这个区间 [i,j] 是 K 倍区间。 你能求出数列中总共有多少个 K 倍区间吗&#xff1f; 输入格式 …

算法设计与分析-动态规划算法的应用——沐雨先生

一、实验目的 1&#xff0e; 掌握动态规划算法的基本思想&#xff0c;包括最优子结构性质和基于表格的最优值计算方法。 2&#xff0e;熟练掌握分阶段的和递推的最优子结构分析方法。 3&#xff0e; 学会利用动态规划算法解决实际问题 。 二、实验内容 1. 问题描述 &#…

Linux之缓冲区与C库IO函数简单模拟

缓冲区 首先, 我们对缓冲区最基本的理解, 是一块内存, 用户提供的缓冲区就是用户缓冲区, C标准库提供的就是C标准库提供的缓冲区, 操作系统提供的就是操作系统缓冲区, 它们都是一块内存. 为什么要有缓冲区? 先举个生活中的例子, 我们寄快递的时候往往是去驿站寄快递, 而不是…

4 个多月的蓝猫吃什么猫粮发腮快?

亲爱的猫友们&#xff0c;你们是不是也在为蓝猫的发腮问题而苦恼呢&#xff1f;&#x1f431; 四个多月的蓝猫正处于生长发育的关键时期&#xff0c;选择合适的猫粮对于它们的健康与美丽至关重要。 &#x1f50d; 在选择猫粮时&#xff0c;我们要关注几个关键点&#xff1a;高…

Elasticsearch从入门到精通-06ES统计分析语法

Elasticsearch从入门到精通-06ES统计分析语法 bucket和metric概念简介 bucket就是一个聚合搜索时的数据分组。如&#xff1a;销售部门有员工张三和李四&#xff0c;开发部门有员工王五和赵六。那么根据部门分组聚合得到结果就是两个bucket。销售部门bucket中有张三和李四&…

window下安装并使用nvm(含卸载node、卸载nvm、全局安装npm)

window下安装并使用nvm&#xff08;含卸载node、卸载nvm、全局安装npm&#xff09; 一、卸载node二、安装nvm三、配置路径和下载源四、使用nvm安装node五、nvm常用命令六、卸载nvm七、全局安装npm、cnpm八、遇到的问题 nvm 全名 node.js version management&#xff0c;顾名思义…

远程桌面安卓版下载 安卓远程控制免费版

远程桌面安卓版下载与安卓远程控制免费版的应用解析 随着移动互联网的快速发展&#xff0c;远程桌面应用逐渐成为了许多用户、特别是技术爱好者和商务人士的必备工具。它们不仅可以在电脑上实现远程控制&#xff0c;还能将这种功能延伸到移动设备上&#xff0c;如安卓手机和平…

Acwing.167 木棒(回溯)

题目 乔治拿来一组等长的木棒&#xff0c;将它们随机地砍断&#xff0c;使得每一节木棍的长度都不超过 50 个长度单位。 然后他又想把这些木棍恢复到为裁截前的状态&#xff0c;但忘记了初始时有多少木棒以及木棒的初始长度。 请你设计一个程序&#xff0c;帮助乔治计算木棒…

年度告警分类统计

1、打开前端Vue项目kongguan_web&#xff0c;完成前端src/components/echart/YearWarningChart.vue页面设计 在YearWarningChart.vue页面添加div设计 <template><div class"home"><div style"margin: 0px auto;height: 100%"><div …

金蝶云星空——单据附件上传

文章目录 概要技术要点代码实现小结 概要 单据附件上传 技术要点 单据附件上传金蝶是有提供标准的上传接口&#xff1a; http://[IP]/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.AttachmentUpLoad.common.kdsvc 参数说明 参数类型必填说明FileName字符是…