JavaScript-day44

Day44 扫雷

1. HTML
有选择难度的下拉列表
开始按钮
重新加载按钮
画板(显示的小方格)
标题提示文字

<body>
    <select name="" id="set_num">
        <option value="0">初级</option>
        <option value="1">中级</option>
        <option value="2">高级</option>
    </select>
    <button id="start">开始游戏</button>
    <span id="refresh">重新加载游戏</span>
    <div id="content">
        <!-- 先写好小格子,通过css设置完样式化,即可删除,因为每个小格子都是js动态生成的 -->
        <!-- 写出这几个div 只是为了方便我们进行css样式设置,确定设置无误后,可删除 -->
        <div class="tile">默认</div>
        <div class="showed">已点击</div>
        <div class="boom">雷</div>
        <div class="tile current">鼠标移入</div>
        <div class="tile tag">小红旗</div>
    </div>
    <h1 id='title'>选择难度并点击确定,开始游戏<br> 右键可以标记小红旗哦~</h1>
</body>

#set_num 是选择难度
#start 是开始游戏
#refresh 是重新加载
#content 画板
.tile默认样式
.showed 已点击样式
.boom 雷的样式
.tile current 鼠标移入样式
.tile tag 右键小红旗样式
#title 友情提示

2. CSS

布局

*{
    margin: 0;
    padding: 0;
}
body{
    text-align: center;
    font-size: 15px;
    font-family: '楷体';
}
#content{
    /* border: 1px solid; */
    /* width: 200px; */
    margin: 0 auto;
}
/* 重新加载 */
#refresh{
    /* 设置行内块,否则不能设置宽高 */
    display: inline-block;
    width: 100px;
    height: 30px;
    /* 行高和高度一致,则内容垂直居中 */
    line-height: 30px;
    border: 1px solid gray;
    /* 圆角边 */
    border-radius: 5px;
    /* 小手状 */
    cursor: pointer;
    color: white;
    background-color: rgb(143,122,102);
}

/* 每一个div小格子 */
/* 默认 */
#content div{
    width: 49px;
    height: 49px;
    border: 1px solid black;
    text-align: center;
    font-size: 20px;
    line-height: 49px;
    cursor: pointer;
    float: left;
}
.tile{
    background: url(../img/ba.png);
}

/* 已点击 */
.showed{
    
    background: rgb(195,206,228);
}
/* 雷 */
.boom{
    
    background: url(../img/Minesmall.png);
}
/* 移入 */
.current{
    
    background: url(../img/baq.png);
}
/* 小红旗 */
.tag{
    /* 第一个是前景,第二个是背景 */
    background: url(../img/hq.png),url(../img/ba.png);
}

3. JS

// 使用闭包,解决$命名冲突问题
(function ($) {
    /**
     * 对外提供的接口
     * 
     * 必须传递 行 row,列 column,雷的个数 mine_num,显示画板的位置 obj 盒子的ID值
     */
    $.fn.mineClearance = function (options) {
        // console.log(options);

        // var obj1 = {name:'张三',age:16};
        // var obj2 = {name:'李四',addr:'石家庄'}
        // 合并两个对象,如果有相同的属性,则使用后者替换前者
        // 所以前者适合做默认值,后者适合做参数传递
        // var obj3 = $.extend(obj1,obj2);
        // console.log(obj3);
        var settings = $.extend({
            // 默认列
            column: 10,
            // 默认行
            row: 10,
            // 默认雷个数
            mine_num: 20,
            // 默认画板ID
            obj: "#content",
            // 每一个div盒子,默认是空数组
            tiles: [],
            // 周边8个元素
            arr: [],
            // 判断游戏是否是第一点击,如果是第一次就初始化雷,true表示第一次点击
            flag: true
        }, options || {});
        // 生成画板
        buildTiles();
        /**
         * 生成画板
         */
        function buildTiles() {
            // 判断行和列是否合法
            if (settings.column <= 0 || settings.row <= 0) {
                alert('行和列必须大于 0 哦~');
                return;
            }
            // 判断雷
            if (settings.mine_num <= 0) {
                alert("没雷你玩啥?");
                return;
            }
            if (settings.mine_num >= (settings.column * settings.row)) {
                alert("全是雷");
                return;
            }
            // 到这里说明数据没啥问题
            // 获取画板的DOM对象
            var obj = $(settings.obj)[0];
            // 设置画板的宽高
            // 每个盒子宽高是49,边框都是1,所以实际宽高为 51
            // 画板的宽度 = 列数 * 51
            // obj.style.width = 51 * settings.column + "px";
            // obj.style.height = 51 * settings.row + "px";
            obj.width(51 * settings.column);
            obj.height(51 * settings.row);

            // 对div添加索引,0,1,2,3,.....
            // 方便我们操作,我们能够根据点击的是谁,获取它和周边8个元素
            // 比如 3行4列,  我们点的是第6个,索引就是 5
            // 5 % 列数 = 1 
            // (5-1) / 列数 = 1
            var indexOfdiv = 0;
            // 根据行和列 生成div 并设置索引
            for (var i = 0; i < settings.row; i++) {
                for (var j = 0; j < settings.column; j++) {
                    // 创建div标签
                    var tile = document.createElement("div");
                    // var tile = $('<div class="tile"></div>')
                    // 设置class属性值为 tile
                    tile.className = 'tile';
                    // 添加索引
                    // tile.setAttribute('index',indexOfdiv);
                    tile.index = indexOfdiv;
                    // 把div保存到 settings.tiles数组中,方便我们后续操作
                    settings.tiles[indexOfdiv] = tile;
                    indexOfdiv++;
                    // 把div添加到 画板中
                    obj.appendChild(tile);
                }
            }
            // 绑定事件
            event();
        }
        /**
         * 对div绑定事件
         */
        function event() {
            // 获取画板对象
            var obj = $(settings.obj)[0];
            // 对画板绑定事件,通过事件源,找到真正触发的这个小div即可

            // 移入
            obj.onmouseover = function (e) {
                // 如果class属性值不是tile ,
                // 说明要么你移动到已经点击过的div
                // 要么你移动到边框上,就是画板了
                // 我们只对未点击过的div做移入事件
                if (e.target.className == 'tile') {
                    e.target.className = 'tile current';
                }
            }
            // 移出
            obj.onmouseout = function (e) {
                // 如果class属性值不是tile ,
                // 说明要么你移动到已经点击过的div
                // 要么你移动到边框上,就是画板了
                // 我们只对未点击过的div做移入事件
                if (e.target.className == 'tile current') {
                    e.target.className = 'tile';
                }
            }
            // 右键事件,添加小红旗
            obj.oncontextmenu = function (e) {
                // 当右键的时候,如果不是雷,不是已点击的,就可以添加红旗
                // 因为如果是boom雷的时候,说明游戏已经结束
                if (e.target.className != 'boom' && e.target.className != 'showed') {
                    // e.target.className = 'tile';
                    // console.log(e.target.className);
                    // if(e.target.className.split(' ').length == 3){
                    //     e.target.className = 'tile current'
                    // }else{
                    //     e.target.className = 'tile current tag'
                    // }
                    $(e.target).toggleClass('tag');
                }
                return false;
            }

            // 点击事件
            obj.onclick = function (e) {
                // console.log(22);
                if (e.target.nodeName == 'DIV') {
                    // 获取事件源索引
                    var index = e.target.index;
                    // console.log(index);
                    // 判断点击的是否含有小红旗
                    // class属性是否包含 tag
                    // console.log(e.target.classList.contains('tag'));
                    if (e.target.classList.contains('tag')) {
                        alert("请先右键取消小红旗");
                        return;
                    }
                }
                // 到这里 说明点击的不是小红旗
                // 初始化所有div , 生成雷,判断周边几个雷
                changeStyle(e.target, index);
            }
        }
        /**
         * 生成雷,统计周围雷的个数等
         * 
         * 第一个参数 : 点击的元素
         * 第二个参数 : 该元素的index索引
         */
        function changeStyle(obj, num_index) {
            // 判断是否是第一次点击
            if (settings.flag) {
                // 是的话,生成雷等信息
                // 获取周围八个元素
                // store(num_index);
                // 生成雷,val 表示,1是雷,0不是雷
                setMineCraft();
                settings.flag = false;
            }
            /**
             * 初始化操作已完成
             */

            //  雷和周边雷个数 已完成,需判断点击之后,是否是雷,是否游戏结束(胜利和失败),不是雷就需要进行扩散显示
            // 不是就判断点击的是否是雷
            // 判断游戏是否结束 - 胜利, 失败  
            if (!obj.getAttribute('val')) {
                // 设置为已点击状态
                obj.className = 'showed';
                // 显示周围几个雷
                let value = obj.getAttribute('value');
                obj.innerHTML = value == 0 ? '' : value;
                // 扩散显示
                showAll(obj.index);
            }
            // 判断游戏是否结束,如果结束,显示所有div信息
            // 比如 是雷的 就替换成雷的图片,周围有几个雷 就显示几
            if (over(obj)) {
                // 进来说明游戏结束
                // 显示所有div信息
                show();
            }
        }
        /**
         * 游戏结束 重置div,所有信息都显示
         */
        function show() {
            // 思路 : 遍历所有div 判断val是1是0 是 设置class为 boom 是0 设置class为 showed
            for (var i = 0; i < settings.tiles.length; i++) {
                settings.tiles[i].className = settings.tiles[i].getAttribute('val') == 1 ? 'boom' : 'showed';
                // 如果不是雷 就要显示周边几个雷
                if (settings.tiles[i].className != 'boom') {
                    var value = settings.tiles[i].getAttribute('value');
                    settings.tiles[i].innerHTML = value == 0 ? '' : value;
                }
            }
            // 取消事件
            $(settings.obj)[0].onclick = null;
        }
        /**
         * 游戏结束判断
         * 
         * @param {点击的元素} obj 
         */
        function over(obj) {
            // true说明结束,false说明没有结束
            var flag = false;
            // 如何算游戏胜利 : 已点击的 + 雷的个数 = 总div个数
            // 获取已点击的元素
            var showed = document.getElementsByClassName('showed');
            // div总个数 减去 雷的个数,得到剩余div个数
            var num = settings.tiles.length - settings.mine_num;
            if (num == showed.length) {
                alert("恭喜你获得成功~");
                flag = true;
                // 如何算失败 : 点到雷就失败  val == 1
            } else if (obj.getAttribute('val') == 1) {
                alert('被炸死,游戏结束!');
                flag = true;
            }
            // 没结束 就返回false,继续游戏
            return flag;
        }
        /**
         * 判断周围是否是雷,如果不是雷,就全部显示
         * 
         * 如果周围有雷,就不再进行遍历
         * 
         * @param {点击元素的索引} num 
         */
        function showAll(num) {
            // 判断 周围是否有雷
            // 如果有 终止
            // 如果没有,遍历周边元素的周边元素,依次判断
            if (settings.tiles[num].className == 'showed' && settings.tiles[num].getAttribute('value') == 0) {
                // 获取周边8个(settings.arr)
                store(num);
                // 如果递归,会更改arr的值,所以保存为局部变量
                var arr2 = settings.arr;
                // 非showed 
                for (var i = 0; i < arr2.length; i++) {
                    // 如果添加小红旗标识 就跳过该次循环
                    if (arr2[i].classList.contains('tag')) {
                        continue;
                    }
                    if (arr2[i].className != 'showed') {
                        // value == 0
                        // 判断周边8个是否有雷,没有就显示并递归
                        if (arr2[i].getAttribute('value') == 0) {
                            //  true     递归
                            arr2[i].className = 'showed';
                            showAll(arr2[i].index);
                        } else {
                            //  false 设置为showed并显示value
                            arr2[i].className = 'showed';
                            arr2[i].innerHTML = arr2[i].getAttribute('value');
                        }
                    }
                }

            }
        }
        /**
         * 生成雷,val 表示,1是雷,0不是雷
         */
        function setMineCraft() {
            // 雷的个数
            var num = settings.mine_num;
            // 遍历所有div 设置不是雷
            // for (var i = 0; i < settings.tiles.length; i++) {
            //     settings.tiles[i].setAttribute('val', 0);
            // }
            // 随机生成雷
            for (var i = 0; i < num; i++) {
                // 随机的雷的索引
                var index_Mine = Math.floor(Math.random() * settings.tiles.length);
                // 判断生成的索引 是否生产过雷
                // console.log(settings.tiles[index_Mine].getAttribute("val"));
                if (!settings.tiles[index_Mine].getAttribute("val")) {
                    // 没有 就设置为 雷
                    settings.tiles[index_Mine].setAttribute('val', 1);
                } else {
                    // 如果生产过 就不搭理,但是 i要-1  否则 最终雷的个数就会少
                    i--;
                }
            }
            // 设置value值,点击之后 显示周围有几个雷
            showValue();
        }
        /**
         * 设置value值,点击之后 显示周围有几个雷
         * 
         * 比如周围8个有一个类 就显示1 
         */
        function showValue() {
            // 1 对所有不是雷的元素 设置内容
            // 2 获取每个非雷元素的周边8个盒子
            // console.log(settings.tiles.length);
            for (var i = 0; i < settings.tiles.length; i++) {
                // 判断是否是雷,是就跳过
                if (settings.tiles[i].getAttribute('val') == 1) {
                    continue;
                }
                // 如果不是雷,就获取周边8个元素,传递当前元素的索引 index
                store(settings.tiles[i].index);
                // console.log(settings.arr);
                // 3 遍历8个盒子,对雷的个数进行计数 arr
                var count = 0;
                for (var j = 0; j < settings.arr.length; j++) {
                    if (settings.arr[j].getAttribute('val') == 1) {
                        count++;
                    }
                }
                // 4 把计数结果 设置到 当前div的内容当中 
                // if (count != 0) {
                // settings.tiles[i].innerHTML = count;
                settings.tiles[i].setAttribute('value', count);
                // }
            }
        }
        /**
         *  获取周围八个元素
         * @param {点击的元素的索引} num 
         */
        function store(num) {
            /**
             * settings.tiles 转换为二维数组,方便查找周边八个元素
             */
            // var tiles_2d = [];
            // 当做 settings.tiles的下标
            // var indexs = 0;
            // 遍历settings.tiles 封装到二维数组中
            // for (var i = 0; i < settings.row; i++) {
            //     // 二维数组中 添加一个空的一维数组
            //     tiles_2d.push([]);
            //     for (var j = 0; j < settings.column; j++) {
            //         tiles_2d[i].push(settings.tiles[indexs]);
            //         indexs++;
            //     }
            // }
            // 根据点击的元素的索引 获取在二维数组中的下标
            // var j = num % settings.column;
            // var i = (num - j) / settings.column;
            // 对settings.arr 初始化
            settings.arr = [];
            var index = num;
            var c = settings.column;
            var r = settings.row;
            // 左上
            if (index % c > 0 && index - c >= 0) {
                settings.arr.push(settings.tiles[index - c - 1]);
            }
            // 正上
            if (index - c >= 0) {
                settings.arr.push(settings.tiles[index - c]);
            }
            // 右上
            if (index - c >= 0 && index % c < c - 1) {
                settings.arr.push(settings.tiles[index - c + 1]);
            }
            // 左边
            if (index % c > 0) {
                settings.arr.push(settings.tiles[index - 1]);
            }
            // 右边
            if (index % c < c - 1) {
                settings.arr.push(settings.tiles[index + 1]);
            }
            // 左下
            if (index % c > 0 && index + c < c * r) {
                settings.arr.push(settings.tiles[index + c - 1]);
            }
            // 正下
            if (index + c < c * r) {
                settings.arr.push(settings.tiles[index + c]);
            }
            // 右下
            if (index % c < c - 1 && index + c < c * r) {
                settings.arr.push(settings.tiles[index + c + 1]);
            }
            // console.log(settings.arr);
        }
    }

})(jQuery);

修改后代码(jQuery)

在这里插入图片描述

html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入资源 -->
    <script src="../resources/js/jquery-1.11.1.min.js"></script>
    <script src="../resources/js/sl.js"></script>
    <script src="../resources/js/test.js"></script>
    <link rel="stylesheet" href="../resources/css/sl.css">
    <script>
        $(function () {
            // 画板对象
            var content = $("#content");
            // 雷的格式,初级 10,中级  40 , 高级 200
            var arr = [10, 40, 200];
            // 行和列,默认是方形
            var arr_type = [10, 16, 24];
            //对自定义输入框进行隐藏
            $('.input').hide();
            /*
            *自定义选择难度
            */
            var ar, w_h;
            $('#set_num').change(function () {
                //通过下拉列表获取难度value值
                var val = $("#set_num").val();
                //根据获取val 值分别设置行列 和 雷数

                //不是自定义
                if (val != 3) {
                    $('.input').hide();//隐藏自定义输入框
                    ar = arr[val];
                    w_h = arr_type[val];
                } else if (val == 3) {
                    $('.input').show();//是自定义就显示输入框

                }
            });
            /**
             * 开始游戏
             */
            $("#start").click(function () {
                // 判断游戏是否开始
                // 画板中,有盒子的时候说明开始了
                // console.log(content.children().length);
                if (content.children().length != 0) {
                    var c = confirm("游戏已经开始,确定需要重新开始吗?");
                    if (c) {
                        // 清空内容
                        content.html("");
                        // 重新开始游戏
                        start();
                    }
                } else {
                    // 开始游戏
                    start();
                }
            });

            /**
             * 开始游戏
             */
            function start() {
                // 1 隐藏title
                $("#title").hide();
                // 2 获取选择的难度
                var val = $("#set_num").val();
                // 3 根据难度获取对应的雷个数和行列
                if (val != 3) {
                    // TODO 调用插件,传入数据
                    $.fn.mineClearance({
                        row: w_h,
                        column: w_h,
                        mine_num: ar,
                        obj: '#content'
                    });
                }else if(val == 3){
                    $.fn.mineClearance({
                        row: $('.row').val(),
                        column: $('.col').val(),
                        mine_num: $('.mine').val(),
                        obj: '#content'
                    });
                }

               
            }

            /**
             * 重新加载页面
             */
            $("#refresh").click(function () {
                // 重新加载页面
                window.location.reload();
            });
            /**
             * 字体闪烁
             */
            function changeColor() {
                var r = Math.floor(Math.random() * 256);
                var g = Math.floor(Math.random() * 256);
                var b = Math.floor(Math.random() * 256);
                var color = 'rgb(' + r + ',' + g + ',' + b + ')';
                $("#title").css("color", color);
                $(".showed").css("color", color);
            }
            // 定时器
            setInterval(changeColor, 200);

        });
    </script>
</head>

<body>
    <select name="" id="set_num">
        <option value="0">初级</option>
        <option value="1">中级</option>
        <option value="2">高级</option>
        <option value="3">自定义</option>
    </select>
    <div class="input">
        行数:<input type="text" class='row'>
        列数:<input type="text" class="col">
        雷数:<input type="text" class="mine">
    </div>
    <button id="start">开始游戏</button>
    <span id="refresh">重新加载游戏</span>
    <div id="content"></div>
    <audio id="move" src="../resources/mp3/move.mp3" controls="controls" hidden></audio>
    <audio id="gameover" src="../resources/mp3/gameOver.mp3" controls="controls" hidden></audio>
    <audio id="boom" src="../resources/mp3/boom.mp3" controls="controls" hidden></audio>
    <audio id="click" src="../resources/mp3/click.mp3" controls="controls" hidden></audio>
    <audio id="victory" src="../resources/mp3/victory.mp3" controls="controls" hidden></audio>
    <h1 id='title'>选择难度并点击确定,开始游戏<br> 右键可以标记小红旗哦~</h1>
</body>

</html>

CSS

*{
    margin: 0;
    padding: 0;
}
body{
    text-align: center;
    font-size: 15px;
    font-family: '楷体';
}
#content{
    /* border: 1px solid; */
    /* width: 200px; */
    margin: 0 auto;
}
/* 重新加载 */
#refresh{
    /* 设置行内块,否则不能设置宽高 */
    display: inline-block;
    width: 100px;
    height: 30px;
    /* 行高和高度一致,则内容垂直居中 */
    line-height: 30px;
    border: 1px solid gray;
    /* 圆角边 */
    border-radius: 5px;
    /* 小手状 */
    cursor: pointer;
    color: white;
    background-color: rgb(143,122,102);
}

/* 每一个div小格子 */
/* 默认 */
#content div{
    width: 48px;
    height: 49px;
    border: 1px solid black;
    text-align: center;
    font-size: 20px;
    line-height: 49px;
    cursor: pointer;
    float: left;
}
.tile{
    background: url(../img/ba.png);
}

/* 已点击 */
.showed{
    
    background: rgb(195,206,228);
    /* background-color: red; */
}
/* 雷 */
.boom{
    background: rgb(195,206,228) url(../img/Minesmall.png);
}
/* 移入 */
.current{
    
    background: url(../img/baq.png);
}
/* 小红旗 */
.tag{
    /* 第一个是前景,第二个是背景 */
    background: url(../img/hq.png),url(../img/ba.png);
}

JS

// 使用闭包,解决$命名冲突问题

(function ($) {
    /**
       * 
       */
    function change() {
        
    }
    /**
     * 对外提供的接口
     * 
     * 必须传递 行 row,列 column,雷的个数 mine_num,显示画板的位置 obj 盒子的ID值
     */
    $.fn.mineClearance = function (options) {
        // console.log(options);

        // var obj1 = {name:'张三',age:16};
        // var obj2 = {name:'李四',addr:'石家庄'}
        // 合并两个对象,如果有相同的属性,则使用后者替换前者
        // 所以前者适合做默认值,后者适合做参数传递
        // var obj3 = $.extend(obj1,obj2);
        // console.log(obj3);
        var settings = $.extend({
            // 默认列
            column: 10,
            // 默认行
            row: 10,
            // 默认雷个数
            mine_num: 20,
            // 默认画板ID
            obj: "#content",
            // 每一个div盒子,默认是空数组
            tiles: [],
            // 周边8个元素
            arr: [],
            // 判断游戏是否是第一点击,如果是第一次就初始化雷,true表示第一次点击
            flag: true
        }, options || {});
        // 生成画板
        buildTiles();
        /**
         * 生成画板
         */
        function buildTiles() {
            // 判断行和列是否合法
            if (settings.column <= 0 || settings.row <= 0) {
                alert('行和列必须大于 0 哦~');
                return;
            }
            // 判断雷
            if (settings.mine_num <= 0) {
                alert("没雷你玩啥?");
                return;
            }
            if (settings.mine_num >= (settings.column * settings.row)) {
                alert("全是雷");
                return;
            }
            // 到这里说明数据没啥问题
            // 获取画板的DOM对象
            var obj = $(settings.obj);
            // 设置画板的宽高
            // 每个盒子宽高是49,边框都是1,所以实际宽高为 51
            // 画板的宽度 = 列数 * 51
            // obj.style.width = 51 * settings.column + "px";
            // obj.style.height = 51 * settings.row + "px";
            obj.width(51 * settings.column);
            obj.height(51 * settings.row);

            // 对div添加索引,0,1,2,3,.....
            // 方便我们操作,我们能够根据点击的是谁,获取它和周边8个元素
            // 比如 3行4列,  我们点的是第6个,索引就是 5
            // 5 % 列数 = 1 
            // (5-1) / 列数 = 1
            var indexOfdiv = 0;
            // 根据行和列 生成div 并设置索引
            for (var i = 0; i < settings.row; i++) {
                for (var j = 0; j < settings.column; j++) {
                    // 创建div标签
                    // var tile = document.createElement("div");
                    var tile = $('<div class="tile"></div>');


                    // 设置class属性值为 tile
                    // tile.className = 'tile';

                    // 添加索引
                    // tile.setAttribute('index',indexOfdiv);
                    tile.attr('index', indexOfdiv);
                    // 把div保存到 settings.tiles数组中,方便我们后续操作
                    settings.tiles[indexOfdiv] = $(tile);
                    indexOfdiv++;
                    // 把div添加到 画板中
                    // obj.appendChild(tile);
                    obj.append(tile);
                }
            }
            //清空事件,避免叠加事件
            obj.unbind();
            // 绑定事件
            event();

        }

        /**
         * 对div绑定事件
         */
        function event() {
            // 获取画板对象
            var obj = $(settings.obj);
            // 对画板绑定事件,通过事件源,找到真正触发的这个小div即可

            // 移入
            obj.mouseover(function (e) {
                // 如果class属性值不是tile ,
                // 说明要么你移动到已经点击过的div
                // 要么你移动到边框上,就是画板了
                // 我们只对未点击过的div做移入事件
                if ($(e.target).attr('class') == 'tile') {
                    $(e.target).attr('class','tile current') ;
                    //添加音乐
                    $('#move')[0].play();
                }
            });
            // 移出
            obj.mouseout(function (e) {
                // 如果class属性值不是tile ,
                // 说明要么你移动到已经点击过的div
                // 要么你移动到边框上,就是画板了
                // 我们只对未点击过的div做移入事件
                if ($(e.target).attr('class') == 'tile current') {
                    $(e.target).attr('class','tile') ;
                    //取消音乐
                    $('#move')[0].pause();
                }
            });
            // 右键事件,添加小红旗
            obj.contextmenu(function (e) {
                // 当右键的时候,如果不是雷,不是已点击的,就可以添加红旗
                // 因为如果是boom雷的时候,说明游戏已经结束
                if ($(e.target).attr('class') != 'boom' && $(e.target).attr('class') != 'showed') {
                    // e.target.className = 'tile';
                    // console.log(e.target.className);
                    // if(e.target.className.split(' ').length == 3){
                    //     e.target.className = 'tile current'
                    // }else{
                    //     e.target.className = 'tile current tag'
                    // }
                    $(e.target).toggleClass('tag');
                }
                return false;
            });

            // 点击事件
            obj.click(function (e) {
                // alert(22);
                if ($(e.target).hasClass('tile')) {
                    // 获取事件源索引
                    // var index = e.target.index;
                    var index = $(e.target).index();
                    // console.log(index);
                    // 判断点击的是否含有小红旗
                    // class属性是否包含 tag
                    // console.log(e.target.classList.contains('tag'));
                    if ($(e.target).hasClass('tag')) {
                        alert("请先右键取消小红旗");
                        return;
                    }
                }
                $('#click')[0].play();
                // 到这里 说明点击的不是小红旗
                // 初始化所有div , 生成雷,判断周边几个雷
                changeStyle($(e.target), index);
            });
        }
        /**
         * 生成雷,统计周围雷的个数等
         * 
         * 第一个参数 : 点击的元素
         * 第二个参数 : 该元素的index索引
         */
        function changeStyle(obj, num_index) {
            // 判断是否是第一次点击
            if (settings.flag) {
                // 是的话,生成雷等信息
                // 获取周围八个元素
                // store(num_index);
                // 生成雷,val 表示,1是雷,0不是雷
                setMineCraft();
                settings.flag = false;
            }
            /**
             * 初始化操作已完成
             */

            //  雷和周边雷个数 已完成,需判断点击之后,是否是雷,是否游戏结束(胜利和失败),不是雷就需要进行扩散显示
            // 不是就判断点击的是否是雷
            // 判断游戏是否结束 - 胜利, 失败  
            if (!obj.attr('val')) {
                // 设置为已点击状态
                // obj.className = 'showed';
                obj.attr('class', 'showed');
                // 显示周围几个雷
                // let value = obj.getAttribute('value');
                let value = obj.attr('value');
                obj.html(value) == 0 ? '' : value;
                // 扩散显示
                showAll(obj.index());
            }
            // 判断游戏是否结束,如果结束,显示所有div信息
            // 比如 是雷的 就替换成雷的图片,周围有几个雷 就显示几
            if (over(obj)) {
                // 进来说明游戏结束
                // 显示所有div信息
                show();
            }
        }
        /**
         * 游戏结束 重置div,所有信息都显示
         */
        function show() {
            // 思路 : 遍历所有div 判断val是1是0 是 设置class为 boom 是0 设置class为 showed
            for (var i = 0; i < settings.tiles.length; i++) {
                // settings.tiles[i].className = settings.tiles[i].getAttribute('val') == 1 ? 'boom' : 'showed';
                // console.log($(settings.tiles[i].addClass('val')));
                // $(settings.tiles[i]).addClass($(settings.tiles[i]).attr('val') ==1 ? 'boom' : 'showed') ;
                $(settings.tiles[i]).attr('class', $(settings.tiles[i]).attr('val') == 1 ? 'boom' : 'showed')

                // 如果不是雷 就要显示周边几个雷
                if ($(settings.tiles[i]).attr('class') != 'boom') {
                    var value = $(settings.tiles[i]).attr('value');
                    $(settings.tiles[i]).html(value) == 0 ? '' : value;
                }
            }
            // 取消事件
            $(settings.obj).unbind('click');
            
        }
        /**
         * 游戏结束判断
         * 
         * @param {点击的元素} obj 
         */
        function over(obj) {
            // true说明结束,false说明没有结束
            var flag = false;
            // 如何算游戏胜利 : 已点击的 + 雷的个数 = 总div个数
            // 获取已点击的元素
            var showed = $('.showed');
            // div总个数 减去 雷的个数,得到剩余div个数
            var num = settings.tiles.length - settings.mine_num;
            if (num == showed.length) {
                $('#victory')[0].play();
                alert("恭喜你获得成功~");
                flag = true;
                
                // 如何算失败 : 点到雷就失败  val == 1
            } else if (obj.attr('val') == 1) {
                $('#boom')[0].play();
                alert('被炸死,游戏结束!');
                $('#gameover')[0].play();
                flag = true;
            }
            // 没结束 就返回false,继续游戏
            return flag;
        }
        /**
         * 判断周围是否是雷,如果不是雷,就全部显示
         * 
         * 如果周围有雷,就不再进行遍历
         * 
         * @param {点击元素的索引} num 
         */
        function showAll(num) {
            // 判断 周围是否有雷
            // 如果有 终止
            // 如果没有,遍历周边元素的周边元素,依次判断
            // console.log($(settings.tiles[num]).attr('class') == 'showed'==$(settings.tiles[num]).attr('value'));

            if ($(settings.tiles[num]).attr('class') == 'showed' && $(settings.tiles[num]).attr('value') == 0) {
                // 获取周边8个(settings.arr)
                store(num);
                // 如果递归,会更改arr的值,所以保存为局部变量
                var arr2 = settings.arr;
                // 非showed 
                for (var i = 0; i < arr2.length; i++) {
                    // 如果添加小红旗标识 就跳过该次循环
                    // console.log($(arr2[i]).hasClass('tag'));
                    if ($(arr2[i]).hasClass('tag')) {
                        continue;
                    }
                    if ($(arr2[i]).attr('class') != 'showed') {
                        // value == 0
                        // 判断周边8个是否有雷,没有就显示并递归

                        if ($(arr2[i]).attr('value') == 0) {
                            //  true     递归
                            // arr2[i].className = 'showed';
                            $(arr2[i]).attr('class', 'showed');
                            // console.log($(arr2[i]).index());
                            showAll($(arr2[i]).attr('value'));
                        } else {
                            //  false 设置为showed并显示value
                            // arr2[i].className = 'showed';

                            $(arr2[i]).attr('class', 'showed');
                            // arr2[i].innerHTML = arr2[i].getAttribute('value');
                            $(arr2[i]).html($(arr2[i]).attr('value'));
                        }
                    }
                }

            }
        }
        /**
         * 生成雷,val 表示,1是雷,0不是雷
         */
        function setMineCraft() {
            // 雷的个数
            var num = settings.mine_num;
            // 遍历所有div 设置不是雷
            // for (var i = 0; i < settings.tiles.length; i++) {
            //     settings.tiles[i].setAttribute('val', 0);
            // }
            // 随机生成雷
            for (var i = 0; i < num; i++) {
                // 随机的雷的索引
                var index_Mine = Math.floor(Math.random() * settings.tiles.length);
                // 判断生成的索引 是否生产过雷
                // console.log(settings.tiles[index_Mine].getAttribute("val"));
                if (!$(settings.tiles[index_Mine]).attr("val")) {
                    // 没有 就设置为 雷
                    $(settings.tiles[index_Mine]).attr('val', 1);
                } else {
                    // 如果生产过 就不搭理,但是 i要-1  否则 最终雷的个数就会少
                    i--;
                }
            }
            // 设置value值,点击之后 显示周围有几个雷
            showValue();
        }
        /**
         * 设置value值,点击之后 显示周围有几个雷
         * 
         * 比如周围8个有一个类 就显示1 
         */
        function showValue() {
            // 1 对所有不是雷的元素 设置内容
            // 2 获取每个非雷元素的周边8个盒子
            // console.log(settings.tiles.length);
            for (var i = 0; i < settings.tiles.length; i++) {
                // 判断是否是雷,是就跳过
                if ($(settings.tiles[i]).attr('val') == 1) {
                    continue;
                }
                // 如果不是雷,就获取周边8个元素,传递当前元素的索引 index
                store($(settings.tiles[i]).index());
                // console.log(settings.arr);
                // 3 遍历8个盒子,对雷的个数进行计数 arr
                var count = 0;
                for (var j = 0; j < settings.arr.length; j++) {
                    if ($(settings.arr[j]).attr('val') == 1) {
                        count++;
                    }
                }
                // 4 把计数结果 设置到 当前div的内容当中 
                // if (count != 0) {
                // settings.tiles[i].innerHTML = count;
                // settings.tiles[i].setAttribute('value', count);
                $(settings.tiles[i]).attr('value', count);
                // }
            }
        }
        /**
         *  获取周围八个元素
         * @param {点击的元素的索引} num 
         */
        function store(num) {
            /**
             * settings.tiles 转换为二维数组,方便查找周边八个元素
             */
            // var tiles_2d = [];
            // 当做 settings.tiles的下标
            // var indexs = 0;
            // 遍历settings.tiles 封装到二维数组中
            // for (var i = 0; i < settings.row; i++) {
            //     // 二维数组中 添加一个空的一维数组
            //     tiles_2d.push([]);
            //     for (var j = 0; j < settings.column; j++) {
            //         tiles_2d[i].push(settings.tiles[indexs]);
            //         indexs++;
            //     }
            // }
            // 根据点击的元素的索引 获取在二维数组中的下标
            // var j = num % settings.column;
            // var i = (num - j) / settings.column;
            // 对settings.arr 初始化
            settings.arr = [];
            var index = num;
            var c = settings.column;
            var r = settings.row;
            // 左上
            if (index % c > 0 && index - c >= 0) {
                settings.arr.push(settings.tiles[index - c - 1]);
            }
            // 正上
            if (index - c >= 0) {
                settings.arr.push(settings.tiles[index - c]);
            }
            // 右上
            if (index - c >= 0 && index % c < c - 1) {
                settings.arr.push(settings.tiles[index - c + 1]);
            }
            // 左边
            if (index % c > 0) {
                settings.arr.push(settings.tiles[index - 1]);
            }
            // 右边
            if (index % c < c - 1) {
                settings.arr.push(settings.tiles[index + 1]);
            }
            // 左下
            if (index % c > 0 && index + c < c * r) {
                settings.arr.push(settings.tiles[index + c - 1]);
            }
            // 正下
            if (index + c < c * r) {
                settings.arr.push(settings.tiles[index + c]);
            }
            // 右下
            if (index % c < c - 1 && index + c < c * r) {
                settings.arr.push(settings.tiles[index + c + 1]);
            }
            // console.log(settings.arr);
        }
    }

})(jQuery);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值