JS:扫雷

1. 目标:完成扫雷操作

2. 效果:

3. 思路:

        (1) html创建基本框架、CSS为其添加样式

        (2) 扫雷盒子中的方块由js创建

        (3) js完成扫雷基本操作

4. 代码实现

  • html
 <div class="box">
        <div id="mine">
        </div>
        <div class="footer">
            <div id="time">
                <div class="circle">
                    <img src="jpg/time.svg" alt="">
                </div>
                <div class="rect" id="time_box"></div>
            </div>
            <div id="remain">
                <div class="rect" id="boomnum">2</div>
                <div class="circle">
                    <img src="jpg/peng.svg" alt="">
                </div>
            </div>
        </div>
    </div>
  • css
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            width: 100vw;
            height: 100vh;
            background: url('http://43.138.24.196/old/mine2/imgs/bg.jpg');
            background-size: 100%;
            background-repeat: no-repeat;
        }

        .box {
            width: 700px;
            height: 500px;
            background-color: rgb(255, 255, 255, 0.6);
            box-shadow: 0 0 10px rgb(0, 0, 0, 0.6);
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            margin: auto;
            display: flex;
            flex-direction: column;
        }

        #mine {
            width: 600px;
            cursor: pointer;
            display: flex;
            flex-wrap: wrap;
            align-content: center;
            justify-content: center;
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            margin: auto;
        }

        .footer {
            width: 100%;
            position: absolute;
            bottom: 20px;
            display: flex;
            align-items: center;
            justify-content: space-around;
        }

        #time,
        #remain {
            width: 150px;
            height: 25px;
            display: flex;
            align-items: center;
            justify-content: space-evenly;
        }

        .circle {
            width: 30px;
            height: 100%;
            border-radius: 50%;
            overflow: hidden;
        }

        .circle img {
            width: 100%;
            height: 100%;
        }

        .rect {
            width: 80px;
            height: 100%;
            margin: 0 10px;
            font-size: 14px;
            color: #13651b;
            border-radius: 10%;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 5px 5px 25px 2px #2aa913;
        }

        .item {
            width: 20px;
            height: 20px;
            background: url('http://43.138.24.196/old/mine2/imgs/kuai.png');
            background-repeat: no-repeat;
            background-size: 110%;
            border: 1px solid black;
            font-size: 15px;
            font-weight: bold;
            text-align: center;
            line-height: 20px;
        }

        .item:hover {
            background: url('http://43.138.24.196/old/mine2/imgs/kuai_hover.png');
            background-size: 120%;
        }
  •  JS
//声明变量   
    var boomsum = 0; //雷总数
    var time = 0; //所用时间
  • 循环给id为mine的盒子添加子元素(行16个列30个)
    • 通过创建document.createElement('')产生div,并为其加item类,和id,便于后续函数操作
    • 利用Math.random()产生随机数,随机为div添加boom类
    • appendChild()函数为id为mine的盒子追加div元素
    • 将生成的boom类个数作为炸弹总数显示
  • 代码中函数使用
    • document.createElement('')
      • 在html中创建一个元素
      • 传入html的标签名
      • 返回值是 Element
    • Math.random() 
      • 产生[0,1)的随机数
      • 可以通过调整 Math.random() > 0.8数值去调整炸弹数量
    • e.classList.add()
      • 为元素添加类名
    • e.appendChild(el)
      • 向e追加子元素e
      • 如果el已在html中存在,调用此函数是将el移动到e最后一个子元素
for (var i = 0; i < 16; i++) {
        for (var j = 0; j < 30; j++) {
            var div = document.createElement('div');
            div.classList.add('item');
            div.id = '_' + i + '_' + j;
            //随机加炸弹
            if (Math.random() > 0.8) {
                div.classList.add('boom');
                boomsum++;
            }
            mine.appendChild(div);
        }
        boomnum.textContent = boomsum;
    }
  • 页面炸弹总数和时间显示
    • setInterval() 显示当前时间,函数会每秒执行一次函数,类似手表
 //返回炸弹总数
    function display_boomsum() {
        boomnum.textContent = boomsum;
        return boomsum;
    }
    //显示时间
    var display_timesum = function () {
        time++;
        timebox.textContent = time;
    }
    var timesum = setInterval(display_timesum, 1000);
  •  处理鼠标交互事件
    • 元素的buttons属性使用前测试一下浏览器,左右键的值
      • 1为左,2为右
    • flag为右键点击出现的旗帜、q为疑问标识
    • open 打开盒子函数
    • check()检查此时标识到的旗帜是否都为boom
  • 代码中的函数
    • e.classList.contains('')
      • 检查e的类中有无括号中的
      • 返回值是布尔值
    • e.classList.remove('')
      • 移除e中括号中的类
      • 返回值是布尔值
    • clearInterval()
      • 可取消由 setInterval() 函数设定的定时执行操作
      • clearInterval() 方法的参数必须是由 setInterval() 返回的 ID 值
      • 要使用 clearInterval() 方法, 在创建执行定时操作时要使用全局变量
 var itemList = document.querySelectorAll('.item');

    for (var i = 0; i < itemList.length; i++) {

        //处理交互事件
        itemList[i].onmousedown = function (e) {
            if (e.buttons == 1) {
                if (this.classList.contains('flag') || this.classList.contains('q'))
                    return;
                if (this.classList.contains('boom')) {
                    alert('game over!');
                    clearInterval(timesum);
                }
                else
                    // this
                    open(this.id)
            }
            else if (e.buttons == 2) {
                if (this.classList.contains('q')) {
                    this.classList.remove('q');
                    return;
                }
                else if (this.classList.contains('flag')) {
                    this.classList.remove('flag');
                    this.classList.add('q');
                    boomsum++;
                    display_boomsum();
                    return;
                }
                else if (!this.classList.contains('open')) {
                    this.classList.add('flag');
                    boomsum--;
                    display_boomsum();
                    if (boomsum <= 0) {
                        if (check()) {
                            alert('win');
                            clearInterval(timesum);
                        } else {
                            alert('lose');
                            clearInterval(timesum);

                        }
                    }
                }
            }
        }
        //禁用鼠标右键的默认行为
        itemList[i].oncontextmenu = function () {
            return false
        }
    }
  •  open
    • “打开盒子” 如果为除0以外的数字就显示其周围的炸弹数(cal函数),并改变字体颜色
      • 如果为0,则不显示数字并递归打开周边的盒子

!!进行安全检查

  • 注意
    • open传递的值为id值,不需要拼字符串时加上#
      • #是选择器,不要混
    • id是字符串类型(在递归时需要进行拼接,需要将取处理的值强转为Number)
      • 取id值时两种方法
        • 直接取,如果id值标识行列都为个位数时,显示正常,如果有两位数表示时,会导致取行/列取不全
          •  例如:

                        let temp = "_9_8";
                        var x = Number(temp[1]); //9
                        var y = Number(temp[3]); //8
                        let temp = "_9_10";
                        var x = Number(temp[1]); //9
                        var y = Number(temp[3]); //1
        • 使用split(),将id切去不需要的,转为数组呈现
          • 例如:
                        id = '_9_10'          
                        let temp = id.split('_');//temp = ['','9','10']
                        var x = Number(temp[1]);//9
                        var y = Number(temp[2]);//10
    //open 
    var open = function (id) {
        var el = document.getElementById(id);
        if (!el)
            return;
        else if (el.classList.contains('open'))
            return;
        else if (el.classList.contains('flag') || el.classList.contains('q'))
            return;
        //显示它周围的雷数
        var num = cal(id);
        el.classList.add('open');
        el.textContent = num;

        var colors = ['#414fbc', '#226301', '#ae0107', '#050085', '#050085', '#050085', '#050085', '#050085'];
        el.style.color = colors[num - 1];

        if (num == 0) {
            el.textContent = '';
            let temp = id.split('_');
            var x = Number(temp[1]);
            var y = Number(temp[2]);
            for (var i = -1; i < 2; i++) {
                for (var j = -1; j < 2; j++) {
                    // 不加#
                    open('_' + (x + i) + '_' + (y + j));
                }
            }

        }
    }
  • cal函数 显示周围的炸弹数
    • document.querySelector('#_' + (x + i) + '_' + (y + j))?.classList.contains('boom')
      • 通过函数document.querySelector()查询选择器为括号中的值,返回值是e
        • 此时因为是选择器,所以需要#
      • ?三目运算符,解决处于边角的盒子,周围有些方向的盒子没有的问题
//显示它周围的雷
    var cal = function (id) {
        var total = 0;
        var temp = id.split('_');
        var x = Number(temp[1]);
        var y = Number(temp[2]);
        for (var i = -1; i < 2; i++) {
            for (var j = -1; j < 2; j++) {
                if (document.querySelector('#_' + (x + i) + '_' + (y + j))?.classList.contains('boom'))
                    total++;
            }
        }
        return total;

    }
  • check()检查
 //检查flag是否全是boom
    var check = function () {
        var result = true;
        let flagList = document.querySelectorAll('.flag')
        for (let i = 0; i < flags.length; i++) {
            if (!flagList[i].classList.contains('boom')) {
                result = false
            }
        }
        return result;
    }

5. 趣味效果

                                                                                                                                                    共勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值