likes
comments
collection
share

小时候玩的经典扫雷游戏你还记得吗?

作者站长头像
站长
· 阅读数 8

小时候玩的经典扫雷游戏你还记得吗?

小时候玩的经典扫雷游戏你还记得吗?

一、游戏设定

可以通过游戏设置来设置扫雷区域的大小和埋雷的数量。

游戏规则比较灵活,可以比谁先扫到第一颗雷,也可以比谁先找出所有的雷。

先睹为快:

二、逻辑实现

核心的逻辑是扫雷区域中雷的随机摆放,实现这个逻辑有这么几步。

  1. 随机生成雷的坐标

注意判断不能超出区域。

createRandPosition() {
    let x = Math.round(Math.random() * (this.size - 1));
    let y = Math.round(Math.random() * (this.size - 1));
    return [x, y];
}
  1. 保存所有雷的坐标

注意判断不能出现重复。

setMinePosition() {
    let position = this.createRandPosition();
    let hasPosition = false;
    for (let p = 0; p < this.minePosition.length; p++) {
        if (this.minePosition[p].toString() == position.toString()) {
            hasPosition = true;
        }
    }
    if (!hasPosition && this.minePosition.length < this.mineSize) {
        this.minePosition.push(position);
    }
    if (this.minePosition.length < this.mineSize) {
        this.setMinePosition();
    }
}
  1. 初始化区域并布雷

这里的思路是使用 HTML table 生成指定大小的表格,先以行开始,再输出列,这样就会有交叉点,交叉点刚好可以对应雷的位置,比如其中某个雷的位置是 [2, 3] ,那么在渲染 table 的第三行第四列(索引从 0 开始)时就应该布下这个雷。

小时候玩的经典扫雷游戏你还记得吗?

小时候玩的经典扫雷游戏你还记得吗?

setArea() {
    // 循环行 
    for (let i = 0; i < this.size; i++) {
        // 此行的列
        let td = [];
        for (let j = 0; j < this.size; j++) {
            // 列属性
            var tdItems = {};
            // 是否是雷,默认不是
            tdItems.ismine = 0;
            // 循环所有雷的坐标
            for (let n = 0; n < this.minePosition.length; n++) {
                // 是否符合当前行和当前列
                if (this.minePosition[n][0] == i && this.minePosition[n][1] == j) {
                    // 如果符合,则设为雷
                    tdItems.ismine = 1;
                }
            }
            // 此点的消除状态,默认未消除
            tdItems.isClear = 0;
            td.push(tdItems);
        }
        this.tableData.push(td);
    }
}
<table cellspacing="1">
    <tr v-for="(tr, trIndex) in tableData">
        <td v-for="(td, tdIndex) in tr" 
            :data-ismine="td.ismine" 
            :data-isClear="td.isClear" 
            @click="doClear($event, trIndex, tdIndex)" 
            :class=" td.isClear == 0 ? 'td-normal' : 'td-clear' ">
            <div class="boom" v-if="td.ismine == 1"></div>
        </td>
    </tr>
</table>

开始扫雷,扫雷就是一个一个的点击事件,点击到这个单元格的时候,通过判断其属性是否是雷即可,然后做相应的数据修改。

// 扫雷事件
doClear(e, trIndex, tdIndex) {
    // 当前点击的块是否已经清除
    let clearStatus = e.target.dataset.isclear;
    // 当前点击的块是否是雷
    let clickResult = e.target.dataset.ismine;
    // 将当前点击的块的清除状态改为已清除
    this.tableData[trIndex][tdIndex].isClear = 1;
    // 如果点击的块是未清除状态
    if (clearStatus == 0) {
        // 如果已清除数量小于总数量,则清除数量加 1
        if (this.clearNum < this.size * this.size) {
            this.clearNum++;
        }
        // 如果点到的是雷
        if (clickResult == 1) {
            // 如果已清除的雷数小于总雷数
            if (this.clearMineNum < this.mineSize) {
                this.clearMineNum++;
            }
            alert('你遇到了一颗雷!');
            return false;
        }
        // 如果总数量减去雷的数量等于已清除数量
        if (this.size * this.size - this.mineSize == this.clearNum) {
            alert('你避开了所有的雷!');
            return false;
        }
    }
}

其它逻辑比较简单,可以参考代码片段。