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 xswitch (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 xswitch (input){case 1:game();/*printf("扫雷\n");*/break;case 0:printf("游戏结束,退出游戏\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);
}
int main()
{test();return 0;
}

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

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

相关文章

项目文章|真菌ChIP-seq+RNA-seq解析脱落酸生物合成的调控机制

组蛋白翻译后修饰是表观遗传调控的主要机制之一&#xff0c;已被证明在基因表达的调控中发挥重要作用&#xff0c;参与真菌发育、感染相关的形态发生、环境应激反应、次级代谢产物的生物合成和致病性。我们分享过不少真菌组蛋白修饰的文章&#xff0c;今天接着带来一篇利用ChIP…

Anaconda安装proplot库

看了一下Anaconda中的环境&#xff0c;现在我有4个&#xff0c;其中gee是一个虚拟环境 因此一般在prompt中装库时要先进入其中一个虚拟环境 conda activate geepip install proplot --no-deps下完了之后&#xff0c;发现版本不对应 conda install matplotlib3.4.3

软件开发项目管理/研发项目管理软件:国产EDA工具厂商行芯科技上线奥博思PowerProject项目管理软件平台

国内领先的EDA工具链提供商杭州行芯科技有限公司&#xff08;以下简称&#xff1a;行芯科技&#xff09;与北京奥博思软件技术有限公司达成战略合作&#xff0c;奥博思软件将基于PowerProject项目管理系统助力行芯科技实现研发项目的全生命周期管理&#xff0c;提升管理效能&am…

论文阅读:Face Deblurring using Dual Camera Fusion on Mobile Phones

今天介绍一篇发表在 ACM SIGGRAPH 上的文章&#xff0c;是用手机的双摄系统来做人脸去模糊的工作。这也是谷歌计算摄影研究组的工作。 快速运动物体的运动模糊在摄影中是一个一直以来的难题&#xff0c;在手机摄影中也是非常常见的问题&#xff0c;尤其在光照不足&#xff0c;…

jasypt加解密

项目中经常遇到jasypt加解密的配置文件&#xff0c;尤其是项目不是自己创建的时候&#xff0c;压根不知道加密的内容是什么&#xff0c;而配置文件中一般加密的也都是数据库或其他非结构型数据库的账号或密码&#xff0c;这时候想要看一下db的内容就非常的头疼&#xff0c;除了…

【爬虫】– 抓取原创力文档数据

使用RPA工具&#xff0c;实现针对于原创力中不可下载文档的抓取&#xff0c;可延用于其他类似文库 1 使用工具、环境 影刀RPA、WPS Office、谷歌浏览器&#xff08;非指定&#xff09; 2 代码流程 3 关键点 此方案只适合抓取非VIP即可预览全文的文档&#xff0c;抓取下来的数…

B007-springcloud alibaba 消息驱动 Rocketmq

目录 MQ简介什么是MQMQ的应用场景异步解耦流量削峰 常见的MQ产品 RocketMQ入门RocketMQ环境搭建环境准备安装RocketMQ启动RocketMQ测试RocketMQ关闭RocketMQ RocketMQ的架构及概念RocketMQ控制台安装 消息发送和接收演示发送消息接收消息 案例订单微服务发送消息用户微服务订阅…

(done) 解释 python3 torch.utils.data DataLoader

特别注意&#xff1a;DataLoader 返回的迭代器是无尽的&#xff0c;依据如下 (CHATGPT3.5) DataLoader 返回的迭代器默认情况下是无尽的&#xff0c;因为它会无限地循环遍历数据集&#xff0c;以提供批量的数据。在训练神经网络时&#xff0c;通常会使用无尽的迭代器来循环遍历…

LEETCODE 100255. 成为 K 特殊字符串需要删除的最少字符数

整体思路: 1.可以看到这道题是要求是最小的&#xff0c;那么可以想到遍历所有情况 2.把题干已知条件转换为一个数组&#xff0c;那么只需要以数组每个元素为开头遍历所有情况即可。 3.对于一个数考虑其后面的情况&#xff0c;其后每个数等于这个数k和数本身的最小值(遍历累计求…

参数高效微调(PEFT)技术概览

参数高效微调&#xff08;PEFT&#xff09;技术概览 在大型语言模型&#xff08;LLMs&#xff09;的世界里&#xff0c;参数量庞大&#xff0c;通常在70亿至700亿之间。这些模型的自监着训练成本高昂&#xff0c;对公司可能意味着高达1亿美元的支出。而对于资源相对有限的研究…

Codeforces Round 934 (Div. 2) --- C. MEX Game 1 --- 题解

C. MEX Game 1&#xff1a; 题目大意&#xff1a; 思路解析&#xff1a; 重要的是那种只有一个的数字&#xff0c;因为如果这个数字有两个及以上&#xff0c;那么我可以再鲍勃删除之后&#xff0c;再拿&#xff0c;也一定能拿得到&#xff0c;所以瓶颈是只有一个的数字&#x…

爬虫3_爬取翻页URL不变的网站

之前实现了对大学排数据爬取&#xff1a;爬虫2_2019年549所中国大学排名. 近期复现代码&#xff0c;发现原网站升级&#xff0c;在翻页时&#xff0c;发现URL不改变&#xff0c;修改代码&#xff0c;使用网页自动化工具selenium实现对该类网站数据获取。 #-*- coding: UTF-8 -…

活动图高阶讲解-06

31 00:01:52,300 --> 00:02:04,300 刚才讲了&#xff0c;活动里面是动作 32 00:02:04,300 --> 00:02:06,300 这个动作 33 00:02:06,300 --> 00:02:09,300 就可以看作活动的一个 34 00:02:09,300 --> 00:02:13,300 里面的实现的一个行为了 35 00:02:16,300 --&g…

vue项目跳转html页面

1. 把html页面以及相关文件放到public文件夹下&#xff08;目的和index.html同级&#xff09; 2.在vue项目中正常写跳转事件&#xff0c;只是路径写法需要注意

【理解指针(三)】

文章目录 一、数组名的理解&#xff08;1&#xff09;数组的地址与数组首元素地址的区别 二、使用指针访问数组&#xff08;1&#xff09;一维数组传参的本质 三、冒泡排序&#xff08;1&#xff09;什么是冒泡排序&#xff08;2&#xff09;写冒泡排序 四、结束语 一、数组名的…

堆排序(向下调整法,向上调整法详解)

目录 一、 二叉树的顺序结构 二、 堆的概念及结构 三、数组存储、顺序存储的规律 此处可能会有疑问&#xff0c;左右孩子的父节点计算为什么可以归纳为一个结论了&#xff1f; 四、大小堆解释 五、大小堆的实现&#xff08;向上和向下调整法&#xff09; 5.11向上调整法…

Unity Timeline学习笔记(1) - 创建TL和添加动画片段

Timeline在刚出的时候学习了一下&#xff0c;但是因为一些原因一直都没用在工作中使用。 版本也迭代了很久不用都不会用了&#xff0c;抽时间回顾和复习一下&#xff0c;做一个笔记后面可以翻出来看。 创建Timeline 首先我们创建一个场景&#xff0c;放入一个Plane地板&#…

Linux操作系统-08-常用的网络相关命令

1、ping命令 在linux下ping的话会一直ping下去&#xff0c;在windows下的话它会只ping四次就结束&#xff0c; [rootbastion ~]# ping 192.168.0.102 PING 192.168.0.102 (192.168.0.102) 56(84) bytes of data. 64 bytes from 192.168.0.102: icmp_seq1 ttl64 time0.571 ms…

Linux - 线程互斥和互斥锁

文章目录 前言一、为什么要线程互斥原子性 二、互斥锁互斥锁的创建与销毁互斥锁进行互斥 前言 前几节课&#xff0c;我们学习了多线程的基础概念&#xff0c;这节课&#xff0c;我们来对线程互斥和互斥锁的内容进行学习。 一、为什么要线程互斥 首先我们要明白&#xff0c;对…

悲观锁(Pessimistic Locking)是一种数据库锁定机制

悲观锁&#xff08;Pessimistic Locking&#xff09;是一种数据库锁定机制&#xff0c;用于防止多个事务同时修改同一数据记录。以下是关于悲观锁的一些详细信息&#xff1a; 锁定数据&#xff1a;当事务对一条记录进行操作时&#xff0c;悲观锁会阻止其他事务对这条记录进行修…