(玩梗)
请注意,本文使用了与默认原创版权协议不一致的协议,本文适用的协议以末尾注明的为准。
扫雷,(Minesweeper,港台称为“踩地雷”)想必大多数人都玩过。它的实现也不困难。下面是利用Javascript扫雷的例子。
主文件
主要的程序只在一个文件中,这里把它叫做 game.js。
作为一个合格的扫雷游戏,它需要满足以下功能:
* 左键点击方块将其打开;
* 右键点击方块将其标记;
* 若点开的方块是地雷则游戏结束;
* 若点开的方块不是地雷则显示其周围8个方块中格子的数量;
* 若打开的方块周围无地雷则自动打开周围的地雷;
* 若一个打开的方块周围标记的方块数量等于它本身显示的数字相同,则可以自动打开剩余的方块;
* 第一下不是雷,且雷阵随机;
* 当所有的非雷方块都打开时,游戏胜利。
一项一项来解决它们。
准备工作
首先定义一些常量
const fieldWidth = 40; //定义区域的宽度
const fieldHeight = 18; //定义区域的高度
const mineDensity = 0.12; //定义雷的密度
之后是一些内部的数据
var fieldBlocks = new Array(); //记录着每个方块的id
var fieldData = new Array(); //记录着每个方块是不是雷
var fieldOpened = new Array(); //记录着每个方块是不是已经被打开
var fieldFlagged = new Array(); //记录着每个方块是不是被标记为雷
var fieldSurroundingMines = Array(); //记录着每个方块周围有多少个雷
var fieldSurroundingFlags = Array(); //记录着每个方块周围有多少个被标记的方块
以及一些不好分类但是又必须需要的变量
var firstClick = true; //是不是第一次点击?
var alreadyCleared = false; //是不是已经胜利了……我也有点搞不懂为什么要这个变量
以及通过id来查找所在位置的坐标的两个函数
//获取X坐标,遍历比较,找到就返回X坐标,找不到就返回-1
function getX(ID)
{
for (var y = 0; y <= fieldHeight + 1; y++)
{
for (var x = 0; x <= fieldWidth + 1; x++)
{
if ( (x == 0) || (x == fieldWidth + 1) || (y == 0) || (y == fieldHeight + 1) ) continue;
if (fieldBlocks[y][x] == ID) return x;
}
}
return -1;
}
//获取Y坐标,遍历比较,找到就返回Y坐标,找不到就返回-1
function getY(ID)
{
for (var y = 0; y <= fieldHeight + 1; y++)
{
for (var x = 0; x <= fieldWidth + 1; x++)
{
if ( (x == 0) || (x == fieldWidth + 1) || (y == 0) || (y == fieldHeight + 1) ) continue;
if (fieldBlocks[y][x] == ID) return y;
}
}
return -1;
}
创建场景
内部数据的变量事实上都是二维数组……
为了在之后的操作中不需要考虑边界方块的四周方块数量不足八个的问题,特意在场地的上下左右边界外添加了一行/一列。
首先在UI层面下手
function create()
{
var count =