这个Python自动扫雷算法写完了,估计看懂的人十不存一了吧

效果

 

        闲来无事,打开虚拟机上的扫雷玩了玩,觉得自己计算很浪费时间,还容易遗漏,就做了个自动扫雷。
        简单模式下很容易通关,困难的就看脸了,感兴趣的可以拿去运行一下。
自动化处理核心代码段在 168~273行。

        次日,发现自动扫雷算法并不完整,上次的代码仅对单个数字周围进行判断。
但在一些情况下,单个数字无法判断,要综合一片小区域确定某些方块是否一定是炸弹,或者一定安全。
        暂且称为高级算法。(并不是算法有多高级,本质上还是取集合(区域),进行大量的判断,难在复杂判断的逻辑关系以及集合、字典的操作上)。
通过半天的归纳总结,找到规律后开始设计代码。

**本次修改还优化了输出格式,使得在大区域下更容易确定方块的坐标。**

  • 【代码中一些重复的地方可以提取出来作为单独的方法,通过改变参数位置来实现相同的功能,让代码看上去更精简】
  • 【但长时间的修改代码,随着变量、变量类型、数据结构嵌套和逻辑关系的不断增加,有点被搞得头晕了】
  • 【所以既然运行上没有错误,多次试验也没有发现毛病,就不去管它了。说不定也是靠着什么bug运行起来了呢】
  • 【事实上最初写出来的高级算法代码还多了一个子模块,这个模块在一次高级算法结束之后进行进一步处理】
  • 【在设计算法的时候,考虑到这样能减少遍历游戏窗口的次数,加快运行速度,并且可以确定更多的更复杂的坐标及操作】
  • 【虽然写好代码之后第一次运行全自动困难模式顺利通关,但在后来的几次测试中总会错把炸弹点开😭】
  • 【而且计算出的坐标我实在是看不懂根据什么条件算出来的,修改多次无果,想着是不是算法最初处理的时候就是错误的】
  • 【把这段代码注释掉之后,多次测试,没有任何错误,而且计算出来的坐标和操作都是正确的!计算不出来的时候,我看着也是无法确定哪个方块安全】
  • 【这种情况下只能靠运气随机选择。所以上文说到,说不定是靠着什么bug运行起来的呢。】

教学时间:


咱都上榜一了,咋能不出个教学呢。
(绿色底为算法讲解,蓝色底为举例说明,无色底、算是旁白或设计算法的过程吧。)

首先介绍下扫雷的冷知识:


        扫雷上面数字的意思是该方块周围八格方块中的雷的个数。


        有时候点一下会开一大片。是因为点到了数字0。0周围没有方块,游戏会自动向四周扩散,直到有数字的方块停止。(0向四周扩散是不可能遇到雷的)


        这段“点到0向四周扩散”的代码在141~150行,通过126-128行进入。通过非常简单的递归实现的,遍历一遍0方块周围的方块,是数字就显示数字,是0就再次调用该方法,传入该位置。这段代码可以优化,但重点是自动扫雷。

生成一局扫雷的方法:(对应代码43 ~ 63行)


        先生成指定大小(m×n)的空间。我在这里用了二维数组表示,初始化全为0,程序中变量名为game_space, 然后随机k(k个雷)个不同坐标,用’*‘表示雷,记录在数组中。
然后遍历一下每个雷的周围八个格子,如果不是字符’*‘,则+1。生成完成。(可以验证,数字与周围雷的数量都是匹配的)


        可能有同学会质疑,既然game_space列表已经记录了雷的位置,那还有啥扫的?  
实际上,扫雷游戏就是提前生成好的游戏棋盘数据,然后在每个格子上都盖上盖子而已。这里表示顶层盖子的列表是show_list。


        所有的操作都在show_list列表上,game_space列表仅用于点击show_list列表时进行数据补充。相当于掀开了外层的盖子,露出了里面的内容。

自动扫雷:


        自动扫雷就是一个模拟玩家扫雷的过程。你开一局扫雷,第一个肯定是要随便点的。如果运气爆棚,是可以直接点到雷结束该局游戏的。


        点到数字一般也不会是8。一般都是从点到0开始才能判断哪里是雷,哪里是安全的。
这里开一局“简单”模式的扫雷,8*8大小,10个雷。用于举例说明。(顺带一提,我写的输出格式在pycharm里输出是整齐的。没有在IDLE里测试过。这里粘贴过来■就比数字宽些)
随机选择【4, 3】点开

Game Over!               
1│ ■  ■  ■  ■  ■  ■  ■  ■  
2│ ■  ■  ■  ■  ■  ■  ■  ■  
3│ ■  ■  ■  ■  ■  ■  ■  ■  
4│ ■  ■  *  ■  ■  ■  ■  ■   
5│ ■  ■  ■  ■  ■  ■  ■  ■  
6│ ■  ■  ■  ■  ■  ■  ■  ■  
7│ ■  ■  ■  ■  ■  ■  ■  ■  
8│ ■  ■  ■  ■  ■  ■  ■  ■  
运气爆棚,一发入魂。 再开一局。
再开N局。
无法确定位置,随机选择【2, 1】点开
无法确定位置,随机选择【4, 8】点开

1│ ■  ■  ■  ■  ■  ■   1   0  
2│ 1   ■  ■  ■  ■  ■   1   0  
3│ ■  ■  ■  ■  ■   1   1   0  
4│ ■  ■  ■  ■  ■   1   0   0  
5│ ■  ■  ■  ■  ■   3   1   1  
6│ ■  ■  ■  ■  ■  ■  ■  ■  
7│ ■  ■  ■  ■  ■  ■  ■  ■  
8│ ■  ■  ■  ■  ■  ■  ■  ■  
        这里我们可以通过【行3列7】(以下使用形如【3,7】表示)确定【2,6】是雷,因为【3,7】周围只有【2,6】没有点开,而【3,7】周围只有一个雷。
        给【2,6】插上旗子之后,又可以通过【1,7】判断【1,6】是安全的,可以点开;可以通过【3,6】判断【2,5】【3,5】【4,5】是安全的。
      【2,5】【3,5】【4,5】点开后 又可以通过【4,6】判断【5,5】是雷。

自动算法说明:(该段代码在174-198行)


        扫雷棋盘使用二维数组表示,首先通过两层循环遍历,找到一个大于0的数字,使用一个变量’z‘记录这个数字。
        再遍历一下该数字周围的八格格子,这里我又使用了两层循环实现。(代码在178-180行,要确保坐标不超界)。
        在遍历过程中,若发现插了旗子‘□’的格子,则让z - 1,表示z周围已经确定了1个雷,所以还剩z - 1个雷。
        如果发现了还没有点开过的格子’■‘,则记录该坐标。(代码中用类变量coordinate_list列表记录)

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值