很早就曾尝试利用scratch写一个扫雷游戏,但点击后展开非雷区的效果实现的不是很理想,于是就无限期的搁置了下来,前几天学习到c++的宽度搜索,一边将所有可能的数据逐一放入队列,一边推进队头重新搜索新产生的可能数据,发现同曾经的盲目尝试有点儿异曲同工。于是重新拾起了信心,来完成这个搁置许久的项目。
完整的扫雷游戏应该具备多个难度,对应不同大小的雷区,因为博主仅追求验证可行性,所以就将行列写成固定的数字了,这里规定行数为12行,列数为18列,总计216个格子。同样,点击后生成雷区是更为人性化的方法,为了程序看起来逻辑更清晰(偷懒就偷懒呗),这里也暂时不实现这个效果了。
设置一个列表map,设置一个变量minecount,首先为列表填充216次,填充数值为0,0代表周边8个格子内没有地雷,后续我们可以根据表中216个数据不同的值,我们让216个克隆体演员展现不同的造型。变量minecount是一个统计地雷个数的计数器,这一块自定义积木允许输入一个参数,这个参数代表最大的地雷个数,我们将minecount初始设置为1,每次成功随机投放一颗地雷后自增1,当minecount自增到大于给定雷数时,布雷环节结束。前面的0值代表周边无雷,这里用数字10代表该格内有地雷一颗。
列表类似一个一维的数组,但在游戏中我们实际展示它们是是二维的,所以我们需要用计算的方式获取到它们之间的位置关系。对于一个上述3列的表格,当前单元格的上方单元格,应该是当前单元格的编号减去列数,比如当前单元格是列表中的第5个格子,要找到它头顶的格子,只需要用5减去列数3,即第2号的格子会在5的上方,后续的数据处理我们需要统计一个地雷周边的8个单元格,这8个单元格的相对位置如上图右侧所示。
我们可以遍历一下map列表,当找到项目值为10的格子10,我们利用上述相对位置,将其周边8个格子的值都提升1,当两个雷的位置接近时,如上图右侧,第一颗雷提升了自己的周边值,接着第二颗雷又提升了一下,于是夹在他们中间的这些格子总计被提升了两次,所以最终值会变为2。(之所以用10代表地雷,是因为极端情况下,一个空格周边都是地雷的时候,这个空格最终的值会是8。所以0~8这几个值都可能会被占用。)
提升周边单元格值的时候会遇到很多限制,比如旁边并不是空格,而是一颗地雷,所以我们一边检测一边做提升值的操作,如果周边的某一格是地雷,那么不处理,如果单元格的坐标值(根据上方提供的位置公式)小于1或值大于216,那么超出了列表范围,从图形上看是上下超限了,那么也不处理,还有一种更为复杂的情况,左右超限。因为实际显示界面为18x12的方阵,从左至右依次排列,判断靠左的单元格,我们可以判断其位置求余18后等于1,而靠右的单元格,求余18后等于0的那一波就是了。靠左的单元格不能再求更左边的值,靠右的单元格不再求更右边的值,举个例子,19求余18等于1,靠左,如果再去提升其左边的值,会把18提升为1,但18号格子实际上是第一排的最后一个,位于最右侧。
我们先实现一个方向数组的自定义积木,要求一个参数,该参数填写需要的列数,博主将填写的数字是18,因为这个实例是一个18x12的方阵。填充完方向数组,我们来实现数据处理的自定义积木,这里需要增加两个变量direction和filter,direction用来遍历方向数组,filter用来过滤一些不允许提升值的情况程序逻辑如下,
获取到当前地雷的位置,这个可以在生成地雷的同时获取到
通过direction遍历方向数组
设置filter的值为0
根据方向数组当前值定位周边单元格
该单元格值为10时改变filter为1,最后通过filter判断是否需要提升值,过滤地雷
判断该单元格坐标是否在1到216之间,否则filter为1,过滤上下边界
判断当前地雷是否靠左,如果靠左且方向值为-19,filter为1
判断当前地雷是否靠左,如果靠左且方向值为-1,filter为1
判断当前地雷是否靠左,如果靠左且方向值为+17,filter为1
判断当前地雷是否靠右,如果靠右且方向值为+19,filter为1
判断当前地雷是否靠右,如果靠右且方向值为+1,filter为1
判断当前地雷是否靠右,如果靠右且方向值为-17,filter为1
经过九九八十一难,filter仍旧为0的情况,提升该周边单元格的值
direction变量自增1
数据处理用的积木命名为了过滤器,完整程序如下,因条件较多,看不清图片的可以放大一些。
回到最初生成数据的自定义积木,在每完成一次布雷操作后用过滤器处理一下数据。
现在还没办法显示在屏幕上,我们可以点击一下map列表,可以看到数据已经被正确生成了。
实例下载
实际中包含了页面布局展现的内容,具体教程请参见下一篇博文:
《用scratch做一个扫雷游戏(中)-造型编号与数据展现》