c语言实现扫雷

目录

棋盘创建

布置雷盘

菜单创建

打印棋盘

排查雷区

大体实现

统计周围雷的个数

​编辑  整体实现

 扩展

递归展开

 第一下一定不是雷

插旗操作


棋盘创建


1.对于扫雷游戏,我们首先应该思考一下扫雷可能是怎么实现的,我们在网页上玩的扫雷,我们对某一个坐标进行排查,如果这个坐标后面是雷,那么游戏失败,而如果不是雷,那么就会展开。那么,我们就可以想到,这里可能会用到两个棋盘,一个是展示给我们看的游戏棋盘,一个是棋盘背后的雷区。这里我们就可以想到,这个游戏我们最基本的应该创建两个棋盘,一个用来展示,一个用来判断是否触发了雷。 

 2.然后,我们要想,我们应该怎么创建这两个棋盘,其次,创建完这两个棋盘之后要做什么。怎么创建这两个棋盘? 我们回过头去看网页版扫雷,附图:

从这里我们大概可以想到,或许可以使用二维数组来实现棋盘。我们不妨假设就使用二维数组来进行棋盘的实现。这里是我创建的两个棋盘。 

这里应使用宏常量。便于后续的改进与调试。而且这里创建的两个棋盘都是11 * 11的棋盘,但实际上,棋盘周围的一圈都只是为了进行排查时方便;我们真正的棋盘只是排除周围一圈后中间的部分。这些后续会讲,这里不做赘述; 

布置雷盘


那么,棋盘创建完毕后,我们做什么呢。那么,雷盘是不是应该有雷。而我们的棋盘创建的是11 * 11的,去掉周围一圈就是9 * 9的棋盘,我们需要对中间的那部分雷盘进行布置雷。而布置雷是随机的。这就要用到rand函数。布置如图:

菜单创建


布置完雷后,游戏自身基本实现。接下来将目标转向用户。我们首先需要一个菜单,供用户进行操作。如图:

 只要用户选择1,那么我们就开始游戏。用户选择0,那么就退出游戏。而用户如果输入了一些其他的数字,那么输入就是不符合规矩的。是非法的。这里显然是类似于开关的操作。如果if进行判断,就显得冗余。而用户每进行完毕一场游戏后,不应该程序自己退出,应该返回菜单界面,用户自己来选择是否退出游戏。那么这里就需要用到循环。这里的逻辑关系应该是:用户输入0-->退出循环;用户输入1-->开始游戏-->游戏结束-->进入循环;用户输入非法-->重新进入循环;则大致应该产生以下的程序段:

        int input = 1;

        while(input != 0)

        {

                scanf("%d", input);

                switch(input)

                {

                        ........//游戏,推出,或者非法输入;

                }

                

        }

下图为本人创建的菜单:

  

打印棋盘


开始游戏后,首先第一件事情应该是打印棋盘;打印棋盘同样的,我们只打印中间的部分,而不是打印全部的棋盘。如图:

现在我们来看一下运行效果: 

  

排查雷区


大体实现


打印实现之后就是进行排雷;这里我们要思考一个问题:假如,我们排查的坐标已经被排查过,那么,这一次的输入就应该无效。而且,我们应该怎么判定游戏获胜。判断游戏获胜,我们可以创建一个类似于计时器的变量。这个变量的作用是代表非雷的坐标的个数,当个数为零时,游戏成功。而且这个过程还是个循环;所以,这里分为这么几种情况:

坐标已经被排查过-->输入非法,重新输入;

坐标没有被排查过-->触发雷-->游戏失败;

坐标没有被排查过-->没有触发雷-->对周围的雷进行统计,将雷的个数赋值给当前坐标;并且非雷个数减一;

统计周围雷的个数

现在我们回过头去看开始定义棋盘时为什么要多定义一圈。我们再看对周围的雷进行统计的过程。假如,我们没有多定义这一圈,我们在对棋盘边缘的坐标进行周围雷的个数排查时,就会发生越界访问。我们的程序就可能崩溃。但是,我们可能会想到,进行判断不行吗?当坐标是棋盘边缘时,我们就让它不要将周围的坐标全部遍历访问。这个问题如果仔细想的话,是很难实现的,因为如果要去进行判断的话,那样情况太多。不谈四个棋盘角落的地方。单单只考虑棋盘的四个边,就要用到四个不同的判断语句,而考虑上四个角落的地方,那样情况就会更多。过于复杂。所以不可取。那么我们就可以多定义这么一圈。让我们更好的进行雷的统计。下图为我的雷的个数统计的实现:

 
 整体实现

到这里,扫雷游戏基本就实现了。下面来看一下效果: 

扫雷就基本完成了。

 扩展

递归展开

接下来我们来讨论扩展,首先是递归展开。我们平常玩的扫雷游戏,经常遇到第一下就展开许多坐标的情况。如图 

这里的规则就是,假如我们排查的坐标周围没有,那么游戏就会自动展开周围的坐标。直到遇到一个坐标且该坐标周围有雷 。那么就会停止展开。我们在上面已经设计了函数计算坐标周围雷的个数。也就是说,只要我们该函数的计算结果为0。那么程序自己就会排查周围的坐标。这个过程需要用到递归。这里我将我的代码重新改动,将"坐标没有被排查过-->没有触发雷-->对周围的雷进行统计,将雷的个数赋值给当前坐标;并且非雷个数减一;"这种情况封装成为了一个函数如图:

需要思考的是这里的递归的限制条件一定要选择正确,并且注意什么时候进行非雷个数减一。先说递归条件。需要明确的是,在递归的过程中不应该出现对同意坐标多次排查的情况。我们假设在一次完整递归过程中多进行了n次多余的排查。那么计数器由于只要发现不是雷就减一,只要发现不是雷就减一,最后就会导致计数器不准,出现问题。所以。递归的过程是不能重复的。判断*就可以避免出现重复的状况。因为只要我们或者递归排查了该坐标。那么这个坐标就会被改变为数字,或者空格。

 第一下一定不是雷

对于这个处理。我们需要做到的是:假如玩家第一下碰到了雷,那么这个雷就会消失,转移到其他非雷的坐标处。这里需要思考判断条件。怎么来判断玩家是第一次排查坐标?怎么来判断被转移坐标不是雷?第二个问题比较简单,只要雷盘上被转移坐标不是雷,就埋雷;否则就重新判断。然后分析第一个问题,我们是不是同样可以看*,可以,但很麻烦。需要遍历整个内部棋盘。统计*的个数,假如是第一下,那么*的个数就 == row * col; 这里有一个更简单的方法,那就是使用计数器;假如玩家进行排雷时计数器为 row * col - 雷的个数; 那么就是第一次排查。这此排查玩家不能排查到雷(如果是雷,将雷转移)下面是代码的实现;

接下来看一下效果: 

插旗操作

插旗操作只要指定特定的操做作为开始插旗的标志即可。值得注意的是插完棋子需要重新开始一轮循环。下面为代码图: 

  • 56
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值