基于JS的扫雷-附源码

前言

还是js小游戏系列,这次带来扫雷小游戏的开发思路

功能说明

仿照以前windows上自带的扫雷小游戏
设置棋盘大小,地雷密度等
包含计时器(单位:秒)

  • 鼠标左键 - - 掀开一块区域
  • 左键双击 - - 掀开周边8个区域
  • 鼠标右键 - - 标记一个区域
  • 数字代表周边8个区域包含的地雷数
  • 胜利条件:将所有地雷全都标记出来
  • 失败条件:掀开了地雷区域

操作截图

在这里插入图片描述

关键方法及设计思路

1.定义了两个区域:信息区,扫雷区
2.初始化方法:

设置棋盘大小,地雷密度,
随机设置地雷,
计算地雷预警数字
3.鼠标左键单击操作
如果掀开是空白区域,需要向周边扩散掀开其他区域,直到掀开数字为止
4.鼠标左键双击操作
需要计算周边8个区域的坐标,调用单击方法
5.鼠标右键单击操作
设置地雷标记,需要注意屏蔽浏览器默认的右键菜单
6.设置地雷的随机算法
将棋盘从二维转换成了单数组,获取相对应的随机数,再转换成二维坐标.

其它

相对来说,设计的复杂程度要比俄罗斯方块少很多.
后续可以对随机算法进行改进,比如在第一次单击操作时才对雷区进行初始化,避免第一步就爆雷的情况出现

详细代码

<html>
<style>

    select{
        width: 120px;
    }

    td {
        width: 28px;
        height: 28px;
        margin: 1px;
        background: #0C0C0C;
        align-content: center;
    }

    #info td{
        color: white;
    }

    #table td{
        /*color: #2135ff;*/
        text-align:center
    }

</style>
<body id="body">
<table id="info">
    <tr>
        <td>
            <label>LEVEL:</label>
        </td>
        <td>
            <select id="level">
                <option value="10">easy</option>
                <option value="7">normal</option>
                <option value="5">hard</option>
                <option value="3">crazy</option>
            </select>
        </td>
    </tr>
    <tr>
        <td>
            <label>Field:</label>
        </td>
        <td>
            <select id="field">
                <option value="10_10">min(10*10)</option>
                <option value="15_15">normal(15*15)</option>
                <option value="20_20">max(20*20)</option>
            </select>
        </td>
    </tr>
    <tr>
        <td>
            <label>BoomCount:</label>
        </td>
        <td>
            <p id="boomCount">0</p>
        </td>
    </tr>
    <tr>
        <td>
            <label>Time:</label>
        </td>
        <td>
            <p id="time">0</p>
        </td>
    </tr>
    <tr>
        <td colspan="2" style="text-align:center">
            <button onclick="refresh()" style="width: 120px;">Play</button>
        </td>
    </tr>
</table>
</body>
<html>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>


    /**
     * 指定背景和初始化操作
     * @param w  宽(格字数)
     * @param h  高(格字数)
     * @constructor
     */
    function Field(w, h, boomRate) {
        //清除所有
        $("#table").remove();
        //默认宽10格
        this.width = w ? w : 10;
        //默认高10格
        this.height = h ? h : 10;
        //密度系数
        this.boomRate = boomRate ? boomRate : 10;
        //地雷总数
        this.boomCount = parseInt(this.width * this.height / this.boomRate);
        $("#boomCount")[0].innerText=this.boomCount;
        //标记数
        this.signCount = 0;

        //显示
        this.show = function () {
            //创建信息区
            $("#body").append("<div id='info'></div>");

            //创建雷区table
            $("#body").append("<table id='table'></table>");
            var table = $("#table");
            for (var i = 1; i <= this.height; i++) {
                $(table).append("<tr id='tr_" + i + "'></tr>");
                var tr = $("#tr_" + i);
                for (var j = 1; j <= this.width; j++) {
                    $(tr).append("<td id='tr_" + i + "td_" + j + "' x='" + j + "' y='" + i + "'></td>");
                    $("#tr_" + i + "td_" + j);
                }
                $(table).append(tr);
            }
            //初始化地雷
            this.boom();
            //初始化td上的单击事件
            $("#table td").click(function () {
                if(over) return;
                f.check(this);
            });
            //初始化td上的双击事件
            $("#table td").dblclick(function () {
                if(over) return;
                f.dbClick(this);
            });
            //初始化td上的右击事件
            $("#table td").mousedown(function (e) {
                //已结束的直接返回
                if(over) return;
                //已掀开的直接返回
                var status = $(this).attr("status");
                if (status == "open") {
                    return;
                }
                //右键为3
                if (3 == e.which) {
                    //判断当前状态
                    var boomSign = $(this).attr("boomSign");
                    if (boomSign != null) {
                        //取消标记
                        $(this).css("background", "#0C0C0C");
                        $(this).removeAttr("boomSign");
                        f.signCount--;
                    } else {
                        if (f.signCount < f.boomCount) {
                            f.signCount++
                            //打上标记
                            $(this).css("background", "#0070c0");
                            $(this).attr("boomSign", "boomSign");
                            //胜利判定
                            if (f.signCount == f.boomCount) {
                                if ($('td[boomSign="boomSign"],[boom="boom"]').length == f.boomCount) {
                                    alert("YOU WIN!")
                                }
                            }
                        } else {
                            //没有多余的标记了
                            alert("too many sign!");
                        }
                    }

                }
            });
        };

        //初始化地雷
        this.boom = function () {
            //初始化地雷
            var randoms = [];
            while (true) {
                var isExists = false;
                // 获取一个1–100范围的数
                var random = parseInt(1 + (this.width * this.height) * (Math.random()));
                // 判断当前随机数是否已经存在
                for (var i = 0; i < randoms.length; i++) {
                    if (random === randoms[i]) {
                        isExists = true;
                        break;
                    }
                }
                // 如果不存在,则添加进去
                if (!isExists)
                    randoms.push(random);
                // 如果有10位随机数了,就跳出
                if (randoms.length === this.boomCount)
                    break;
            }
            //计算地雷坐标
            var boomXY = [];
            for (var i = 0; i < randoms.length; i++) {
                var value = randoms[i];
                var x = parseInt(value / this.width) + 1;
                var y = value % this.width + 1;
                boomXY[i] = {"x": x, "y": y};
                $("#tr_" + y + "td_" + x).attr("boom", "boom");
            }
            //计算地雷周围数字
            $("#table td").each(function () {
                var td = this;
                //地雷标志
                var boom = $(td).attr("boom") == null ? false : true;
                //不是地雷时,计算周围地雷数量
                var scanCount = 0;
                if (!boom) {
                    //寻找四周坐标
                    var around = f.around(td);
                    //遍历查询地雷
                    for (var i = 0; i < around.length; i++) {
                        var scanTd = $("#tr_" + around[i].y + "td_" + around[i].x);
                        var boomFlag = $(scanTd).attr("boom") == null ? false : true;
                        if (boomFlag) {
                            scanCount++;
                        }
                    }
                }
                if (scanCount > 0) {
                    $(td).attr("scanCount", scanCount);
                }
            })
        };

        //判断单击后的事件
        this.check = function (td) {
            //判断是否已经掀开
            var status = $(td).attr("status");
            if (status == "open") {
                return;
            }
            //已标记的不能掀开
            var boomSign = $(td).attr("boomSign");
            if (boomSign != null) {
                return;
            }
            //判断是否是雷
            var boom = $(td).attr("boom") == null ? false : true;
            if (boom) {
                //踩中地雷,则失败,掀开所有地雷
                $("td[boom='boom']").css("background", "#ff0000");
                //锁定页面和时间
                clearInterval(timer);
                over=true;
                alert("Boom~~~");

            } else {
                //赋值表示已经掀开
                $(td).attr("status", "open");
                //获取周边雷数
                var scanCount = $(td).attr("scanCount");
                //雷数全空,则向四周自动展开
                if (scanCount == null || scanCount == "") {
                    //空白则直接掀开
                    $(td).css("background", "#dffed7");
                    //向周围八个方向蔓延
                    //寻找四周坐标
                    var around = f.around(td);
                    //遍历查询地雷
                    for (var i = 0; i < around.length; i++) {
                        var scanTd = $("#tr_" + around[i].y + "td_" + around[i].x);
                        $(scanTd).click();
                    }
                } else {
                    //雷数不为空,显示底部的数字
                    $(td).css("background", "#dffed7")[0].innerText = scanCount;
                }
            }

        };

        //如果当前对象是数字,触发周边范围的单击事件
        this.dbClick = function (td) {
            //判断是不是数字
            var scanCount = $(td).attr("scanCount");
            if(scanCount!=null&&scanCount!=""){
                //寻找四周坐标
                var around = f.around(td);
                //遍历查询地雷
                for (var i = 0; i < around.length; i++) {
                    var scanTd = $("#tr_" + around[i].y + "td_" + around[i].x);
                    $(scanTd).click();
                }
            }
        };


        //获得周圈坐标
        this.around = function (td) {
            //自我坐标
            var x = parseInt($(td).attr("x"));
            var y = parseInt($(td).attr("y"));
            //返回结果集
            var around = [];
            if (y > 1) {
                //左上
                if (x > 1) {
                    around.push({"x": x - 1, "y": y - 1});
                }
                //上
                around.push({"x": x, "y": y - 1});
                //右上
                if (x < this.width) {
                    around.push({"x": x + 1, "y": y - 1});
                }
            }
            //左
            if (x > 1) {
                around.push({"x": x - 1, "y": y});
            }
            //右
            if (x < this.width) {
                around.push({"x": x + 1, "y": y});
            }
            if (y < this.height) {
                //左下
                if (x > 1) {
                    around.push({"x": x - 1, "y": y + 1});
                }
                //下
                around.push({"x": x, "y": y + 1});
                //右下
                if (x < this.width) {
                    around.push({"x": x + 1, "y": y + 1});
                }
            }
            return around;
        };
    }

    /**
     * 初始化雷区
     */
    function refresh() {
        over=false;
        //获取雷区大小
        var area = $("#field").val().split("_");
        var w = parseInt(area[0]);
        var h = parseInt(area[1]);
        //获取雷区密度
        var level = parseInt($("#level").val());
        //重置雷区
        f = new Field(w, h, level);
        f.show();
        //重置计时器
        $("#time")[0].innerText = 0;
        clearInterval(timer);
        timer = window.setInterval("var time = parseInt($('#time')[0].innerText);time++;$('#time')[0].innerText=time;", 1000);
    }


    //定义雷区
    var f;
    //定义计时器
    var timer;
    //结束标志
    var over=false;

    //屏蔽页面系统右键
    document.oncontextmenu = function () {
        return false;
    }

</script>
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值