原生js制作扫雷-自定义难度

news/2024/7/19 12:56:49 标签: 游戏, js

游戏功能:

1、有四个难度

2、可以自定难度

1、html相关代码

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>扫雷</title>
    <script src="js/mine.js"></script>
    <link rel="stylesheet" href="./css/mine.css">
</head>
<!-- 
需求分析:
        1.游戏的区域:
            9*9的区域
        2.方格可以打开与标记
            左键打开,显示数字,为周围格子的地雷数,右键标记
        3.地雷
            地雷随机分布
        4.踩到地雷时,游戏结束
            所有的地雷显示出来
        5.连锁开大空方格
        6.剩余地雷数与计时器
        7.游戏胜利条件
            所有的方格除了地雷都被打开了,则游戏胜利

        一个方格所包含的信息:
            坐标 x y
            是否是一个地雷
            周围的地雷数 = 9
            二维数组中存储的是周围的地雷数
     -->

<body>
    <div class="level">
        <button type="button" name="button" class="choice-level">自定义</button>
        <button type="button" name="button" class="choice-level">初级</button>
        <button type="button" name="button" class="choice-level">中级</button>
        <button type="button" name="button" class="choice-level">高级</button>
        <button type="button" name="button" class="choice-level">魔鬼级</button>
        <button type="button" name="button" class="restart">重新开始</button>
    </div>
    <div class="gameBox"></div>
    <div class="info">
        <p>剩余雷数:
            <span class="residue"></span>
        </p>
        <p>
            TIME:
            <span class="tick"></span>S
        </p>

    </div>
</body>


</html>

2、css样式

*{
    margin: 0;
    padding: 0;
}
.gameBox{
    margin-top: 30px;
}
body{
    font-size: 0;
}
ul{
    list-style: none;
    text-align: center;
    overflow: hidden;
}
.col{
    display: inline-block;
    width: 22px;
    height: 22px;
    line-height: 22px;
    background-color: rgba(32, 226, 255, 0.4);
    border: 1px solid rgb(129, 129, 129);
    font-size: 16px;
    margin: 1.5px;
    vertical-align: top;
    position: relative;
}
.col:hover{
    background-color: #0af;
}
.col span{
    cursor: default;
}
.hide{
    display: none;
}
.boom{
    background: url("../img/boom.svg") no-repeat 2.5px 2px;
    background-size: 18px 18px;
}
.num-1{
    color: rgb(8, 153, 235);
}
.num-2{
    color: rgb(255, 45, 178);
}
.num-3{
    color:#16a085;
}
.num-4{
    color: #8e44ad;
}
.num-5{
    color: rgb(255, 167, 45);
}
.num-6{
    color:  rgb(8, 126, 176);
}
.num-7{
    color: #e67e22;
}
.num-8{
    color: #c0392b;
}
.img-flag{
    width: 18px;
    height: 18px;
    position: absolute;
    top: 3px;
    left: 3px;
}
.level{
    margin-top: 30px;
    font-size: 20px;
    text-align: center;
}
.level button{
    padding: 5px 8px;
    background-color: rgb(67, 183, 189);
    border: none;
    outline: none;
    border-radius: 3px;
    cursor: pointer;
    color: #fff;
}
.level button:hover{
    background-color: rgb(23, 132, 138);
}
.info{
    margin-top: 30px;
    font-size: 16px;
    text-align: center;
}
.info p{
    display: inline-block;
    width: 130px;
    margin: 0 auto;
}
.info p span{
    color: rgb(67, 183, 189);
}

3、js代码

window.onload = function() {
    var row = 4;
    var col = 4;
    var num = 1;
    // 判断踩雷之后不能胜利
    var gg = false;
    // 生成地图
    function mineMap(r, c, num) {
        // 定义行
        var map = [];
        //给行数,生成二维数组
        for (var i = 0; i < r; i++) {
            map[i] = new Array()
        }
        // 赋值
        for (var i = 0; i < map.length; i++) {
            for (var j = 0; j < c; j++) {
                // //周围的地雷数
                map[i][j] = 0;
            }
        }
        var plus = function(array, x, y) {
            if (x >= 0 && x < r && y >= 0 && y < c) {
                if (array[x][y] !== 9) {
                    array[x][y]++
                }
            }
        }
        for (var i = 0; i < num; i++) {
            var x = Math.floor(Math.random() * r)
            var y = Math.floor(Math.random() * c)
            if (map[x][y] != 9) {
                map[x][y] = 9
                    //上下6个 +1
                for (var j = -1; j < 2; j++) {
                    //上三个
                    plus(map, x - 1, y + j)
                        //下三个
                    plus(map, x + 1, y + j)
                }
                //左右2个 +1
                plus(map, x, y - 1)
                plus(map, x, y + 1)
            } else {
                //重新随机
                num++
            }
        }
        return map;
    }
    //先通过x轴数量写入ul,再讲过y轴的属性写入li
    function writeHtml(map) {
        // 获取盒子
        var gameBox = document.querySelector(".gameBox");
        // 声明空字符串,存放生成的ul、li
        var gridHTML = "";
        for (var i = 0; i < map.length; i++) {
            gridHTML += '<ul class = "row" data-x="' + i + '">';
            //生成li
            for (var j = 0; j < map[0].length; j++) {
                var m = map[i][j]
                if (m == 0) {
                    m = "";
                }
                gridHTML += "<li class='col' data-y=" + j + ">" +
                    "<span class='hide num-" + m + "'>" + m + "</span>" +
                    "<img src='img/flag.svg' class='img-flag hide'>" +
                    "</li>"
            }
            gridHTML += '</ul>'
            gameBox.innerHTML = gridHTML;
        }
    }

    //给方格绑定事件, 点开数字 地雷  右键标记
    function show() {
        // 获取行ul
        var rows = document.querySelectorAll(".row");
        // 遍历所有ul
        for (var i = 0; i < rows.length; i++) {
            var element = rows[i];
            // 添加点击事件
            element.onclick = function(event) {
                    // 当前点击元素
                    var el = event.target;
                    // 判断是否为li
                    if (el.nodeName != "LI") {
                        return;
                    }
                    //todo 判断是否被打开以及标记了
                    if (el.style.background == "white" || !el.children[1].classList.contains("hide")) {
                        return;
                    }
                    // 获取span标签内容
                    var mineNum = el.children[0].innerHTML;
                    if (mineNum !== "9" && el.style.background !== "white") {
                        // 空白连锁打开
                        if (mineNum == "") {
                            var x = parseInt(el.parentNode.dataset.x);
                            var y = parseInt(el.dataset.y);
                            showNoMine(x, y);
                        }
                        // li背景变白色;span显示
                        el.style.background = "white";
                        el.children[0].style.display = "inline";
                        // 判断打开数量
                        clearMineNum++;
                        // 胜利函数
                        judgeVictory()

                    } else if (mineNum == "9") {
                        // 清除胜利计时器
                        clearInterval(stopTime);
                        // li添加类名
                        el.classList.add("boom");
                        alert("你真菜!")
                        gg = true;
                        // 显示所有地雷,获取所有li
                        var all = document.querySelectorAll(".col");
                        // 放置所有的地雷
                        var ff = [];
                        var allnum = 0;
                        // 遍历所有li
                        for (var i = 0; i < all.length; i++) {
                            if (all[i].children[0].innerHTML == "9") {
                                // 雷赋值给数组
                                ff[allnum] = all[i];
                                allnum++;
                            }
                        }
                        // 设置一个计时器一个一个打开雷
                        allnum = 0;
                        var stop = setInterval(function() {
                            ff[allnum].classList.add("boom")
                            allnum++;
                            // 判断结束条件
                            if (allnum == ff.length) {
                                // 清除计时器
                                clearInterval(stop);
                            }
                        }, 30)

                    }
                }
                // 右键标记地雷
            element.oncontextmenu = function(event) {
                // 阻止右键菜单
                event.preventDefault();
                // 获取当前点击节点
                var el = event.target;
                // 判断是否是
                if (el.parentNode.nodeName == "LI") {
                    el = el.parentNode;
                }
                if (el.nodeName != "LI") {
                    return;
                }
                // 获取img
                var classList = el.children[1].classList;
                // 剩余雷数
                var residue = document.querySelector(".residue");
                var mineNum = parseInt(residue.innerHTML);
                // 如果没有旗子,没有被点开,可以插旗子
                if (classList.contains("hide") && el.style.background != "white") {
                    // 移除隐藏
                    classList.remove("hide");
                    // 获取雷数
                    mineNum--;
                } else if (el.style.background != "white") {
                    classList.add("hide");
                    // 判断雷数
                    if (mineNum < num) {
                        mineNum++;
                    }
                }
                // 剩余雷数
                residue.innerHTML = mineNum;
            }
        }
    }

    function judgeVictory() {
        //游戏胜利
        if (clearMineNum === (row * col - num)) {
            //做一个小动画
            var all = document.querySelectorAll(".col");
            var allNum = 0;
            var stop = setInterval(function() {
                var r = Math.floor(Math.random() * 256)
                var g = Math.floor(Math.random() * 256)
                var b = Math.floor(Math.random() * 256)
                all[allNum].style.background = "rgba(" + r + "," + g + "," + b + ",0.6)";
                //将旗子和span都隐藏
                all[allNum].children[0].style.display = "none"
                all[allNum].children[1].style.display = "none"
                allNum++
                if (allNum === all.length) {
                    clearInterval(stop)
                    if (!gg) {
                        alert("大吉大利,今晚吃鸡")
                        init(row, col, num)
                    }
                }
            }, 20)
        }
    }
    //自动打开空格
    function showNoMine(x, y) {
        for (var i = -1; i <= 1; i++) {
            if (x + i >= 0 && x + i < row) {
                // 获取当前行
                var rowElement = document.querySelectorAll(".row")[x + i];
                for (var j = -1; j <= 1; j++) {
                    if (y + j >= 0 && y + j < col) {
                        //获取当前单元格
                        var el = rowElement.children[y + j]
                            //自动打开必须是未打开的方格
                        if (el.style.background != "white") {
                            el.style.background = "white"
                            el.children[0].style.display = "inline"
                                //打开方格数量+1
                            clearMineNum++
                            //判断游戏是否胜利
                            judgeVictory(clearMineNum)

                            if (el.children[0].innerText === "") {
                                showNoMine(x + i, y + j)
                            }
                        }
                    }
                }
            }
            // if (x + i >= 0 && x + i < row) {
            //     //   获取当前行
            //     var rowElement = document.querySelectorAll(".row")[x + i];
            //     for (var j = -1; j <= 1; j++ && y + j < col) {
            //         // 获取当前单元格
            //         var el = rowElement.children[y + j];
            //         if (el.style.background !== "white") {
            //             el.style.background = "white";
            //             el.children[0].style.display = "inline";
            //             // 打开放格数量加1
            //             clearMineNum++;
            //             // 判断游戏是否胜利
            //             judgeVictory(clearMineNum);
            //             // 判断打开周围的放格周围是否为空
            //             if (el.children[0].innerHTML === "") {
            //                 showNoMine(x + i, y + j)
            //             }
            //         }
            //     }
            // }
        }

    }
    //初始化方法
    var stopTime;

    function init(row, col, num) {
        //数据初始化
        clearMineNum = 0
        gg = false;
        //清除原来的地图,生成新的地图
        var box = document.querySelector(".gameBox")
        box.innerHTML = "";
        var map = mineMap(row, col, num);
        // 新建地图
        writeHtml(map);
        show()
            //将雷数写入html中
        var residue = document.querySelector(".residue")
        residue.innerHTML = num
            // 获取计时
        var tick = document.querySelector(".tick");
        var i = 0;
        // 初始化
        tick.innerHTML = i;
        // 清除计时
        clearInterval(stopTime);
        // 时间计时器
        stopTime = setInterval(function() {
            tick.innerHTML = ++i
        }, 1000)
    }
    // 重置
    var restart = document.querySelector(".restart");
    restart.onclick = function(event) {
            //阻止冒泡
            event.stopPropagation()
            init(row, col, num)
        }
        // 自定义
    var level = document.querySelector(".level")
    level.onclick = function(event) {
        var el = event.target;
        switch (el.innerHTML) {
            case "初级":
                row = 9;
                col = 9;
                num = 10;
                init(row, col, num)
                break;
            case "中级":
                row = 16;
                col = 16;
                num = 40;
                init(row, col, num)
                break;
            case "高级":
                row = 16;
                col = 30;
                num = 479;
                init(row, col, num)
                break;
            case "魔鬼级":
                row = 40;
                col = 50;
                num = 300;
                init(row, col, num)
                break;
            case "自定义":
                row = prompt("请输入列数!");
                col = prompt("请输入行数!");
                num = prompt("请输入你想要的雷数,(请慎重选择)");
                init(row, col, num);
                break;
            default:
                row = 9;
                col = 9;
                num = 10;
                init(row, col, num)
                break;
        }
    }
    init(row, col, num)
}

 

 


http://www.niftyadmin.cn/n/1381180.html

相关文章

pytorch例子学习——NEURAL TRANSFER USING PYTORCH神经迁移

参考&#xff1a;https://pytorch.org/tutorials/advanced/neural_style_tutorial.html 具体的理论就不解释了&#xff0c;这里主要是解释代码&#xff1a; ⚠️使用的是python2.7 1.导入包和选择设备 下面是需要用来实现神经迁移的包列表&#xff1a; torch, torch.nn, numpy …

Linux磁盘及文件系统管理

设备类别&#xff1a;块(block)&#xff1a;随机访问&#xff0c;数据交换单位为“块”字符(character)&#xff1a;线性&#xff0c;数据交换单位为字符设备文件&#xff1a;FHS(LSB)/dev/: 设备 #[主设备号]&#xff0c;#[次设备号]设备文件&#xff0c;关联至设备的驱动程…

Servlet传递数据方式

Servlet传递数据方式 基本概述 Servlet传递数据的方式有很多&#xff0c;这里提供五种方式&#xff1a; 1、静态变量 2、HttpServletResponse的sendRedirect()方法 3、HttpServletRequest的getRequestDispatch()方法 4、HttpServletRequest的getSession()方法 5、HttpServletRe…

MySQLDB类工具的封装

面向对象编程的过程中&#xff0c;经常要用到动态数据来填充静态网页&#xff0c;而动态数据往往来自于数据库&#xff0c;为了不用每此创建一个脚本都要重新打一遍连接数据库以及其它的获取资源结果集的代码&#xff0c;因此封装一个数据库的工具类文件就显得尤为重要了。 数据…

送女朋友-css动画制作立方体相册

图片可以换成女朋友照片~ 直接上代码&#xff01; 嵌套立方体相册 ​<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"…

上海瀚示电子货位标签系统与手持PDA应用

一、产品介绍项目核心产品为自主知识产权的智能电子货位标签系统&#xff08;包含硬件产品、软件系统及增值服务&#xff09;。系一组安装在货架储位等载体上的电子设备&#xff0c;包含显示屏和信号灯按钮。此标签可彩屏显示、信号灯按钮提示等操作&#xff0c;可通过亮灯拣货…

关于php的一些小知识!

浏览目录&#xff1a; 一、PHP的背景和优势&#xff1b; 二、PHP原理简介&#xff1b; 三、PHP运行环境配置&#xff1b; 四、编写简单的PHP代码以及测试。 一、PHP的背景和优势 1.1 什么是PHP&#xff1f; PHP是能让你生成动态网页的工具之一。PHP代表&#xff1a;超文本预处…

JS 图片放大镜

需求&#xff1a; 1.小遮罩可以随鼠标在小盒子上移动 2.遮罩层有自己的移动范围 3.鼠标在遮罩层的中心 4.大盒子默认是隐藏的。 5.当鼠标停留在小盒子上时&#xff0c;大盒子显示 6.当鼠标在小盒子上移动时&#xff0c;按比例移动。 效果图&#xff1a; 上代码&#xff01; &…