在 第三章 中我们基本完成了雷区的绘制和布雷相关接口功能,我们留下了一个未完成的功能,“一次性打开连续的空格”。在开始编写主要游戏流程前,我们先把这里完成。
打开连续的空格(递归、边界条件)
打开连续空格这个过程,大概可以描述为:
如果当前要打开的格子,是空格,打开当前各自周围的其他格子。
打开其他格子时,采用 1 中的逻辑。
上面这种反复使用同样逻辑,并有“逐级深入”表现的程序一般就可以称作“递归”。简单说,如果某个函数的功能实现中还会出现调用自身的情况,就造成了“递归”。
我们先用递归方式实现“打开连续空格子”这个功能(将 minesweeper-field.js 文件中 openCell() 函数调整为如下内容):
// 打开指定的格子
function openCell($cell) {
if(!$cell || $cell.find(".mask").prop("hidden")) { // 连续打开的停止边界条件
return;
// 1. 当前格子不存在(向周围寻找时超出了雷区范围)
// 2. 遇到了已经打开的格子
}
// 当前格子是整个雷区的左上角,那么它的左上等元素都是不存在
// 打开当前格子
$cell.find(".mask").prop("hidden", true) // !!!! 隐藏遮罩层 !!!!
// 从当前格子元素读取其坐标,便于找到周围元素
var x = $cell.data("x"), y = $cell.data("y");
if(nums[x+":"+y] === 0) { // 如果当前格子是空格
// 打开当前格子周围的格子
// 我们给打开周围格子,加入适当的延迟
// 这样能够看到一种类似波浪的动画效果
setTimeout(openCell, 10, cells[(x-1)+":"+(y-1)]) // 左上
setTimeout(openCell, 20, cells[( x )+":"+(y-1)]) // 上
setTimeout(openCell, 30, cells[(x+1)+":"+(y-1)]) // 右上
setTimeout(openCell, 40, cells[(x-1)+":"+( y )]) // 左
setTimeout(openCell, 50, cells[(x+1)+":"+( y )]) // 右
setTimeout(openCell, 60, cells[(x-1)+":"+(y+1)]) // 左下
setTimeout(openCell, 70, cells[( x )+":"+(y+1)]) // 下
setTimeout(openCell, 80, cells[(x+1)+":"+(y+1)]) // 右下
}
}
细心的各位可能又发现,我们把上一章“隐藏遮罩层”