用js制作游戏:扫雷,源代码

扫雷要求

  1. 游戏的区域:
    9*9的区域
  2. 方格可以打开与标记
    左键打开,显示数字,为周围格子的地雷数,右键标记
  3. 地雷
    地雷随机分布
  4. 踩到地雷时,游戏结束
    所有的地雷显示出来
  5. 连锁开大空方格
  6. 剩余地雷数与计时器
  7. 游戏胜利条件
    所有的方格除了地雷都被打开了,则游戏胜利
  • 一个方格所包含的信息:
    坐标 x y
    是否是一个地雷
    周围的地雷数 = 9
    二维数组中存储的是周围的地雷数
    在这里插入图片描述

html格式代码

<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="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>

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);
}

js代码块

//打开空格数量
var clearMineNum = 0;
//列
var col = 9
    //行
var row = 9
    //地雷数
var num = 10
    //表示游戏是否结束  false表示未结束  true表示结束
var gg = false
    /**
     * 
     *  r 行数
     *  c 列数
     *  num 地雷数
     */
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]++
                }
            }
        }
        //随机写入地雷的位置, 9表示地雷
    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
}

function writeHtml(map) {
    //先通过x轴数量写入ul,再讲过y轴的属性写入li
    var gameBox = document.querySelector(".gameBox");
    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() {
    var rows = document.querySelectorAll(".row")
    for (var i = 0; i < rows.length; i++) {
        //ele = ul
        var element = rows[i];
        element.onclick = function(event) {
                // el  表示当前点击的元素
                var el = event.target;
                if (el.nodeName != "LI") {
                    return;
                }
                //TODO 判断是否被翻开了以及被标记了
                if (el.style.background == "white" || !el.children[1].classList.contains("hide")) {
                    return;
                }

                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);
                    }
                    el.style.background = "white";
                    el.children[0].style.display = "inline"
                    clearMineNum++
                    //todo 是否胜利
                    judgeVictory()

                } else if (mineNum == "9") {
                    //  踩到地雷,游戏结束
                    clearInterval(stopTime);
                    el.classList.add("boom");
                    alert("这数都不会算?去玩连连看吧")
                    gg = true;
                    //所有的地雷都显示
                    var all = document.querySelectorAll(".col");
                    //放置所有的地雷
                    var ff = [];
                    var allnum = 0;
                    //遍历所有的方格
                    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;
            }
            //如果点击不是li,则直接返回
            console.log(el.nodeName);
            if (el.nodeName != "LI") {
                return;
            }
            var classList = el.children[1].classList;
            var residue = document.querySelector(".residue");
            var mineNum = parseInt(residue.innerHTML);
            //如果没有旗子3,同时也没有被点开,则可以插旗子
            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 === "") {
                            console.log(1);
                            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 = 99
            init(row, col, num)
            break;
        default:
            row = 9;
            col = 9
            num = 10
            init(row, col, num)
            break;
    }
}
init(row, col, num)

图片是地雷和小旗可以直接放到文件夹中:
图片样式可以直接粘贴。

地雷图片的代码格式:
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#FF6600;}
	.st1{fill:#3366CC;}
</style>
<path class="st0" d="M80.2,42l-9.8,15.8l21.4,1.6l15.9,6.6V48.5"/>
<path class="st0" d="M109.2,66.6c23.7,14.1,36.5,42.6,29.5,70.8c-8.6,34.5-43.4,55.5-77.9,46.9c-34.5-8.6-55.5-43.4-46.9-77.9
	C20.5,79.6,43,61,68.8,58c7.4-0.9,15.2-0.4,22.9,1.5C97.9,61,103.7,63.4,109.2,66.6z"/>
<path class="st1" d="M76.3,190.6c-5.6,0-11.2-0.7-16.6-2C23,179.4,0.5,142.1,9.6,105.3C13,91.5,20.5,79.3,31.3,70
	c10.5-9.1,23.3-14.7,37.1-16.3c8.1-0.9,16.4-0.4,24.4,1.6c6.6,1.6,12.8,4.2,18.6,7.7c12.4,7.4,22.4,18.8,28,32.1
	c5.9,13.8,7.1,28.8,3.4,43.4C135.3,169.1,107.9,190.6,76.3,190.6L76.3,190.6z M76.2,61.9c-2.3,0-4.6,0.1-6.9,0.4
	c-24.7,2.9-45.3,21-51.3,45.1c-8,32.1,11.7,64.7,43.7,72.6c4.7,1.2,9.6,1.8,14.5,1.8c27.6,0,51.5-18.7,58.1-45.5
	c6.3-25.4-5-52.6-27.5-65.9c-5.1-3-10.5-5.3-16.3-6.7C86,62.5,81.1,61.9,76.2,61.9L76.2,61.9z M178,72.9c-17.7,0-32.1-14.4-32.2-32
	c0-2.4,1.9-4.4,4.4-4.4c0,0,0,0,0,0h0c2.4,0,4.4,1.9,4.4,4.4c0,12.9,10.5,23.3,23.4,23.3h0.1c2.4,0,4.4,2,4.4,4.4
	c0,2.4-2,4.4-4.4,4.4L178,72.9L178,72.9z"/>
<path class="st1" d="M94.3,46.5c-2.4,0-4.4-2-4.4-4.4V42c0-17.7,14.4-32.1,32-32.2h0.1c17.7,0,32.1,14.4,32.2,32
	c0,2.4-1.9,4.4-4.4,4.4c0,0,0,0,0,0h0c-2.4,0-4.4-1.9-4.4-4.4c0-12.9-10.6-23.4-23.5-23.3c-12.9,0-23.3,10.5-23.3,23.4v0.1
	C98.7,44.5,96.8,46.5,94.3,46.5z M175.4,112.3c-2.4,0-4.4-2-4.4-4.4c0-1.3,0.6-2.5,1.5-3.3c1.2-1,2.4-2.2,3.3-3.5
	c6.8-8.7,6.5-21.1-0.6-29.5c-1.6-1.8-1.3-4.6,0.5-6.2c1.8-1.6,4.6-1.3,6.2,0.5l0,0c9.8,11.6,10.1,28.6,0.8,40.5
	c-1.4,1.8-2.9,3.4-4.6,4.8C177.4,111.9,176.4,112.3,175.4,112.3z"/>
<path class="st1" d="M109.2,70.9c-2.2,0-4.1-1.7-4.3-3.9l-1.6-15.2l-22.5-5.6l-8.5,12.7c-1.3,2-4.1,2.5-6.1,1.2
	c-2-1.3-2.5-4.1-1.2-6.1l10.2-15.3c1-1.5,2.9-2.3,4.7-1.8l28.4,7.1c1.8,0.4,3.1,2,3.3,3.8l1.9,18.3c0.2,2.4-1.5,4.5-3.9,4.8
	C109.5,70.9,109.4,70.9,109.2,70.9L109.2,70.9z M35.6,100.7c-2.4,0-4.4-2-4.4-4.4c0-0.8,0.2-1.6,0.6-2.2c1.6-2.6,3.3-5,5.3-7.3
	c1.6-1.8,4.4-2,6.2-0.4c1.8,1.6,2,4.4,0.4,6.2c-1.6,1.9-3.1,3.9-4.4,6C38.5,99.8,37.1,100.7,35.6,100.7z M63.6,168.1
	c-0.4,0-0.7,0-1.1-0.1c-12.9-3.2-23.8-11.2-30.7-22.6c-6.9-11.4-8.9-24.8-5.7-37.7c0.6-2.3,2.9-3.8,5.3-3.2l0,0
	c2.3,0.6,3.8,3,3.2,5.3c0,0,0,0,0,0c-2.6,10.6-1,21.7,4.7,31.1c5.7,9.4,14.6,16,25.3,18.7c2.3,0.6,3.8,2.9,3.2,5.3
	C67.4,166.7,65.7,168.1,63.6,168.1L63.6,168.1z M190.6,116.7c1.6,0.8,2.4,2.6,2.1,4.3c-0.3,1.7-1.8,3.1-3.5,3.2l-3.7,0.4l1.7,3.3
	c0.8,1.6,0.4,3.5-0.8,4.7c-1.3,1.2-3.2,1.4-4.8,0.5l-3.2-1.9l-0.6,3.7c-0.3,1.9-2,3.4-3.9,3.4c-1.6,0-3-0.9-3.7-2.4l-1.5-3.4
	l-2.7,2.6c-1.3,1.3-3.2,1.5-4.8,0.7c-1.6-0.9-2.4-2.6-2-4.4l0.8-3.7l-3.7,0.6c-1.8,0.3-3.5-0.7-4.2-2.3c-0.8-1.6-0.4-3.5,1-4.7
	l2.8-2.5l-3.3-1.7c-1.6-0.8-2.4-2.6-2.1-4.3c0.3-1.7,1.8-3.1,3.6-3.2l3.7-0.4L156,106c-0.8-1.6-0.5-3.5,0.8-4.7
	c1.3-1.2,3.2-1.4,4.8-0.5l3.2,1.9l0.6-3.7c0.4-2.2,2.4-3.7,4.6-3.3c1.3,0.2,2.5,1.1,3,2.3l1.5,3.4l2.7-2.6c1.3-1.2,3.2-1.5,4.7-0.7
	c1.6,0.8,2.4,2.6,2,4.4l-0.8,3.7l3.7-0.6c1.8-0.3,3.5,0.7,4.2,2.3c0.8,1.6,0.4,3.5-1,4.7l-2.8,2.5L190.6,116.7L190.6,116.7z
	 M176.9,118c-0.3-0.5-0.5-1-0.6-1.6c-0.1-0.6,0-1.2,0.2-1.7c-0.5-0.2-1-0.5-1.4-1c-0.4-0.4-0.7-0.9-0.9-1.5c-0.5,0.1-1.1,0.2-1.7,0
	c-0.6-0.1-1.1-0.3-1.6-0.7c-0.4,0.4-0.8,0.8-1.4,1c-0.5,0.3-1.1,0.4-1.7,0.4c0,0.6-0.2,1.1-0.5,1.6c-0.3,0.5-0.7,1-1.1,1.3
	c0.3,0.5,0.5,1,0.6,1.6c0.1,0.6,0,1.2-0.2,1.7c0.5,0.2,1,0.5,1.4,1c0.4,0.4,0.7,0.9,0.9,1.5c0.3-0.1,0.6-0.1,0.9-0.1
	c0.3,0,0.5,0,0.8,0.1c0.6,0.1,1.1,0.3,1.6,0.7c0.4-0.4,0.8-0.8,1.4-1c0.5-0.3,1.1-0.4,1.7-0.4C175.4,119.7,176,118.7,176.9,118
	L176.9,118z"/>
<path class="st0" d="M176.3,116.4c0.1,0.6,0.3,1.1,0.6,1.6c-0.9,0.7-1.5,1.8-1.6,2.9c-0.6,0-1.1,0.1-1.7,0.4c-0.5,0.3-1,0.6-1.4,1
	c-0.5-0.3-1-0.6-1.6-0.7c-0.3,0-0.5-0.1-0.8-0.1c-0.3,0-0.6,0-0.9,0.1c-0.2-0.5-0.5-1-0.9-1.5c-0.4-0.4-0.9-0.8-1.4-1
	c0.2-0.5,0.2-1.1,0.2-1.7c-0.1-0.6-0.3-1.1-0.6-1.6c0.5-0.3,0.8-0.8,1.1-1.3c0.3-0.5,0.4-1.1,0.5-1.6c0.6,0,1.1-0.1,1.7-0.4
	c0.5-0.3,1-0.6,1.4-1c0.5,0.3,1,0.6,1.6,0.7c0.6,0.1,1.2,0.1,1.7,0c0.2,0.5,0.5,1,0.9,1.5c0.4,0.4,0.9,0.8,1.4,1
	C176.3,115.2,176.2,115.8,176.3,116.4L176.3,116.4z"/>
</svg>

旗子的代码格式:
在这里插入图片描述

<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1521894384315" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="643" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<defs>
<style type="text/css">
</style>
</defs>
<path d="M299.1 79.8v863.7" fill="#73D8A5" p-id="644">
</path>
<path d="M299.1 959.5c-8.8 0-16-7.2-16-16V79.9c0-8.8 7.2-16 16-16s16 7.2 16 16v863.6c0 8.8-7.2 16-16 16z" fill="#4C4848" p-id="645"></path>
<path d="M726 326.3L299.1 572.8v-493z" fill="#EE655F" p-id="646"></path>
<path d="M299.1 588.8c-2.8 0-5.5-0.7-8-2.1-5-2.9-8-8.1-8-13.9v-493c0-5.7 3-11 8-13.9 4.9-2.8 11.1-2.8 16 0L734 312.5c5 2.9 8 8.1 8 13.9s-3 11-8 13.9L307.1 586.7c-2.5 1.4-5.3 2.1-8 2.1z m16-481.2v437.6l379-218.8-379-218.8z" fill="#4C4848" p-id="647">
</path>
</svg>

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值