App下載

使用JavaScript實(shí)現(xiàn)掃雷小游戲!附加源碼!

廢話輸出機(jī)器 2021-11-26 10:51:13 瀏覽數(shù) (4196)
反饋

12

上面是今天小編來(lái)為大家分享一個(gè)使用JavaScript實(shí)現(xiàn)的掃雷小游戲的效果截圖,那么下面我們來(lái)看看我們步驟吧!這邊我們使用的是HBuilder X 編輯器,大家可以使用自己喜歡的編輯器進(jìn)行編輯。

首先我們創(chuàng)建我們需要的文件(截圖如下所示):

23

1、編輯inde.html文件:

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

<head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" href="jin.css">
</head>

<body>
    <div class="level">
        <button type="button" name="button" class="choice-level">初級(jí)</button>
        <button type="button" name="button" class="choice-level">中級(jí)</button>
        <button type="button" name="button" class="choice-level">高級(jí)</button>
        <button type="button" name="button" class="restart">重新開始</button>
    </div>
    <div class="gameBox"></div>
    <div class="info">
        <p class="">
            剩余雷數(shù) :
            <span class="residue"></span>
        </p>
        <p>
            TIME :
            <span class="tick"></span> S
        </p>
    </div>
    <script src="jin.js" charset="utf-8"></script>
</body>

</html>

2、jin.css文件內(nèi)容填入:

body {
    text-align: center;
    position: relative;
}

.level {
    margin-top: 30px;
    font-size: 18px;
}

.level button {
    padding: 3px 8px;
    background: rgb(67, 183, 189);
    /* border: 1px solid rgb(129, 129, 129); */
    border: none;
    color: white;
    border-radius: 3px;
    outline: none;
    cursor:pointer;
}
.level button:hover {
    background: rgb(23, 132, 138);
}
.row {
    margin: 0;
    padding: 0;
    overflow: hidden;
    letter-spacing: -8px;
}
.col {
    display: inline-block;
    background: rgba(32, 226, 255, 0.41);
    border: 1px solid rgb(129, 129, 129);
    margin: 1.5px;
    width: 23px;
    height: 23px;
    letter-spacing: normal;
    position: relative;
}

.col span {
    display: inline-block;
    position: relative;
    top: 2px;
    opacity: 0;
    font-weight: bold;
    /* 標(biāo)準(zhǔn)箭頭 */
    cursor:default;
}

.col:hover {
    background: blue;
}

.gameBox {
    margin-top: 30px;
}

.img-flag {
    position: absolute;
    top: 3px;
    left: 3.5px;
    width: 18px;
    height: 18px;
}

.hide {
    display: none;
}

.boom {
    background: url('boom.svg') no-repeat 2.5px 2px;
    background-size: 18px 18px;
}

.div-boom {
    font-size: 30px;
    position: fixed;
    top: 50px;
    left: 50%;
}

.info {
    margin-top: 30px;
}
.info p {
    display: inline-block;
    width: 130px;
    margin: 0 10px;
}
.info p span {
    color: rgb(67, 183, 189);
}
.num-1 {
    color: rgb(8, 153, 235);
}
.num-2 {
    color: rgb(255, 45, 178);
}
.num-3 {
    color: rgb(109, 224, 176);
}
.num-4 {
    color: rgb(8, 153, 235);
}
.num-5 {
    color: rgb(255, 167, 45);
}
.num-6 {
    color: rgb(49, 140, 102);
}
.num-7 {
    color: rgb(168, 55, 237);
}

.num-8 {
    color: rgb(15, 254, 154);
}

3、jin.js文件:

// 1,成一張雷的地圖
var mineSweepingMap = function (r, c, num) {
    var map = []
    // 給行數(shù),生成一個(gè) 1 維數(shù)組
    var row = function (r) {
        for (var i = 0; i < r; i++) {
            map[i] = new Array()
        }
    }
    // 給列數(shù),生成一個(gè) 2 維數(shù)組
    var column = function (col) {
        for (var i = 0; i < map.length; i++) {
            for (var j = 0; j < col; j++) {
                map[i][j] = 0
            }
        }
    }
    // 給列數(shù)和行數(shù)生成空地圖
    var blankMap = function (r, col) {
        row(r)
        column(col)
    }

    // 給出地雷數(shù)量讓后隨機(jī)寫入地雷
    var writeInMine = function (num) {
        // 隨機(jī)位置寫入
        var randomLocation = function () {
            var x = Math.floor(Math.random() * r)
            var y = Math.floor(Math.random() * c)
            // console.log( ':', x, y);
            if (map[x][y] !== 9) {
                map[x][y] = 9
            } else {
                randomLocation()
            }
        }
        for (var i = 0; i < num; i++) {
            randomLocation()
        }
    }

    // 使用循環(huán)給雷的邊上所有數(shù) +1 , 已經(jīng)是雷的除外
    var plus = function (array, x, y) {
        if (x >= 0 && x < r && y >= 0 && y < c) {
            if (array[x][y] !== 9) {
                array[x][y] += 1
            }
        }
    }
    var writeInHint = function () {
        for (var x = 0; x < map.length; x++) {
            for (var y = 0; y < map[0].length; y++) {
                if (map[x][y] === 9) {
                    // 上下 6 個(gè)
                    for (var i = -1; i < 2; i++) {
                        plus(map, x - 1, y + i)
                        plus(map, x + 1, y + i)
                    }
                    // 左右 2 個(gè)
                    plus(map, x, y + 1)
                    plus(map, x, y - 1)
                }
            }
        }
    }

    blankMap(r, c)
    writeInMine(num)
    writeInHint()
    return map
}

// 2,將雷寫入頁(yè)面
var writeHtml = function (map) {
    // 先通過(guò) y軸數(shù)量寫入 ul,然后通過(guò) x軸上的數(shù)量寫入 li
    var x = document.querySelector('.gameBox')
    for (var i = 0; i < map.length; i++) {
        x.innerHTML = x.innerHTML + `<ul class="row x-${i}" data-x="${i}"></ul>`
    }

    var z = document.querySelectorAll('.row')
    for (var i = 0; i < z.length; i++) {
        for (var j = 0; j < map[0].length; j++) {
            var m = map[i][j]
            if (m === 0) {
                m = ''
            }
            z[i].innerHTML = z[i].innerHTML + `
                <li class="col y-${j} num-${m}" data-y="${j}">
                    <span>${m}</span>
                    <img src="flag.svg" class="img-flag hide">
                </li>`
        }
    }
}

// 判斷是否勝利
var changeClearMineNum = function (clearMineNum) {
    // console.log('zmzmzmzm');
    // console.log('zz', zz);
    if (clearMineNum === ((col * row) - 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 = 210
            // var b = Math.floor(Math.random() * 256)
            all[allNum].children[0].style.opacity = `0`
            all[allNum].children[1].style.opacity = '0'
            all[allNum].style.background = `rgba(${r},${g},$,0.6)`
            allNum++
            if (allNum === all.length) {
                clearInterval(stop)
                if (zz === 0) {
                    alert('你成功啦~??!晚上吃肉~~!')
                    initializeGame(row, col, num)
                }
                initializeGame(row, col, num)
            }
        }, 20)
    }
}

// 3,掃雷過(guò)程
var clearMine = function (row, col, num) {
    var clearMineNum = 0
    var makeWhite = function (x, y) {
        if (x < row && y < col && x >= 0 && y >= 0) {
            var el = document.querySelector(`.x-${x}`).children[y]
            // 需要注意這個(gè) !== 'white' ,如果不加這個(gè)就會(huì)進(jìn)入無(wú)限循環(huán)
            if (el.style.background !== 'white') {
                el.style.background = 'white'
                el.children[0].style.opacity = '1'
                el.children[1].classList.add('hide')
                clearMineNum++
                // console.log(clearMineNum, 'clearMineNum');
                changeClearMineNum(clearMineNum)
                if (el.innerText === '') {
                    showNoMine(x, y)
                }
            }
        }
    }
    // 智能掃雷
    var showNoMine = function (x, y) {
        // console.log(x, y, 'x,y');
        makeWhite(x - 1, y + 1)
        makeWhite(x - 1, y - 1)
        makeWhite(x - 1, y)
        makeWhite(x + 1, y + 1)
        makeWhite(x + 1, y - 1)
        makeWhite(x + 1, y)
        makeWhite(x, y + 1)
        makeWhite(x, y - 1)
    }

    // 給所有方塊綁定點(diǎn)擊事件,點(diǎn)擊顯示數(shù)字,或者 boom
    var show = function () {
        // var x = document.querySelectorAll('.col')
        var x = document.querySelectorAll('.row')
        for (var i = 0; i < x.length; i++) {
            x[i].addEventListener('click', function (event) {
                var el = event.target
                if (el.tagName != 'LI') {
                    // 因?yàn)槭录械脑?                    // 如果點(diǎn)擊到了 span 上面,那么就會(huì)出現(xiàn) bug
                    // 所以如果點(diǎn)擊到 span 上面,那么 el 就等于 span 的父節(jié)點(diǎn)
                    el = event.target.parentElement
                }
                // 已經(jīng)被標(biāo)記的不能點(diǎn)擊
                var flag = el.children[1].classList.contains('hide')
                if (el.tagName === 'LI' && flag) {
                    if (el.children[0].innerText !== '9' && el.style.background !== 'white') {
                        el.children[0].style.opacity = '1'
                        el.style.background = 'white'
                        clearMineNum++
                        changeClearMineNum(clearMineNum)
                        // console.log(clearMineNum, 'clearMineNum');
                    } else if (el.children[0].innerText === '9') {
                        // el.children[0].style.opacity = '1'
                        zz = 1
                        el.classList.add('boom')
                        alert('游戲失敗')
                        var all = document.querySelectorAll('.col')
                        var ff = []
                        var allNum = 0
                        // 這里做了個(gè)小動(dòng)畫,失敗的時(shí)候慢慢的顯示雷的位置
                        for (var i = 0; i < all.length; i++) {
                            if (all[i].children[0].innerText === '9') {
                                // all[i].style.background = 'red'
                                ff[allNum] = all[i]
                                allNum++
                            }
                        }
                        allNum = 0
                        var time = 60
                        if (num > 50) {
                            time = 10
                        } else if (num > 10) {
                            time = 25
                        }
                        var stop = setInterval(function () {
                            ff[allNum].classList.add('boom')
                            allNum++
                            if (allNum === ff.length) {
                                clearInterval(stop)
                                // console.log('stop');
                            }
                        }, time)
                        // var box = document.querySelector('.gameBox')
                        // box.innerHTML = ''
                        // var level = event.target.innerHTML
                        // var body = document.querySelector('body')
                        // initializeGame(row, col, num)
                    }
                    // 如果點(diǎn)擊的方格為空(什么有沒(méi)有),那么周圍沒(méi)有點(diǎn)開的空方格都會(huì)被點(diǎn)開
                    if (el.children[0].innerText === '') {
                        // 獲取到位置
                        var x = parseInt(el.parentElement.dataset.x)
                        var y = parseInt(el.dataset.y)
                        // console.log(x,y, 'data');
                        // 背景變成白色
                        showNoMine(x, y)
                    }
                }
            })
        }
        for (var i = 0; i < x.length; i++) {
            var mineNum = num
            x[i].addEventListener('contextmenu', function (event) {
                event.preventDefault();
                var btnNum = event.button
                var el = event.target
                if (el.tagName != 'LI') {
                    // 因?yàn)槭录械脑?                    // 如果點(diǎn)擊到了 span 上面,那么就會(huì)出現(xiàn) bug
                    // 所以如果點(diǎn)擊到 span 上面,那么 el 就等于 span 的父節(jié)點(diǎn)
                    el = event.target.parentElement
                }
                if (el.tagName === 'LI') {
                    var classList = el.children[1].classList
                    // 已經(jīng)被點(diǎn)擊過(guò)的地方不能標(biāo)記
                    if (classList.contains('hide') && el.style.background !== 'white') {
                        var residue = document.querySelector('.residue')
                        if (mineNum !== 0) {
                            mineNum--
                        }
                        residue.innerText = `${mineNum}`
                        classList.remove('hide')
                    } else if (el.style.background !== 'white') {
                        classList.add('hide')
                    }
                }
            })
        }
    }
    show()
}

// 4,清除畫面,然后寫入新的畫面
var stopTime
var initializeGame = function (row, col, num) {
    var residue = document.querySelector('.residue')
    residue.innerText = `${num}`
    var time = document.querySelector('.tick')
    time.innerText = `0`
    var i = 1
    clearInterval(stopTime)
    stopTime = setInterval(function () {
        time.innerText = `${i++}`
    }, 1000)
    // zz
    zz = 0
    // 首先清除原來(lái)的地圖,然后重新初始化
    var box = document.querySelector('.gameBox')
    box.innerHTML = ''
    var body = document.querySelector('body')
    body.style.minWidth = `${27 * col}px`
    var map = mineSweepingMap(row, col, num)
    writeHtml(map)
    clearMine(row, col, num)
}

// 5,選擇游戲等級(jí),給按鈕綁定功能
var Btn = function () {
    var level = document.querySelectorAll('.choice-level')
    for (var i = 0; i < level.length; i++) {
        level[i].addEventListener('click', function (event) {
            var level = event.target.innerHTML
            if (level === '初級(jí)') {
                row = 9
                col = 9
                num = 10
                initializeGame(row, col, num)
            } else if (level === '中級(jí)') {
                row = 16
                col = 16
                num = 40
                initializeGame(row, col, num)
            } else if (level === '高級(jí)') {
                row = 16
                col = 30
                num = 99
                initializeGame(row, col, num)
            }
        })
    }
    var restart = document.querySelector('.restart')
    restart.addEventListener('click', function (event) {
        initializeGame(row, col, num)
    })
}
Btn()

// 6,初始數(shù)據(jù)
// zz 用來(lái)確定是否已經(jīng)點(diǎn)到地雷
var zz = 0
var row = 16
var col = 16
var num = 40
initializeGame(row, col, num)

// 給一個(gè)坐標(biāo),把四周變成白色

// 根據(jù)
// 綁定鼠標(biāo)右擊事件,右擊鼠標(biāo)的時(shí)候進(jìn)行標(biāo)記,
    // 這個(gè)時(shí)候要進(jìn)行 css 的變化
// 當(dāng)所有地雷被標(biāo)記,或者說(shuō)所有數(shù)組中只剩 9,游戲成功。

// 選擇游戲難度

那么以上的話就是我們有關(guān)于JavaScript原生游戲的相關(guān)代碼;更多有關(guān)于JavaScript這方面的學(xué)習(xí)大家可以在下面小編分享的相關(guān)課程和教程中進(jìn)行學(xué)習(xí)。

教程:

JavaScript 教程

HTML 教程

CSS 教程

微課:

JavaScript 入門課程

JavaScript 基礎(chǔ)實(shí)戰(zhàn)

JavaScript 函數(shù)式編程

HTML入門課程

HTML + CSS 基礎(chǔ)實(shí)戰(zhàn)

HTML+CSS響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)

視頻課:

HTML5+CSS3零基礎(chǔ)快速入門

JavaScript零基礎(chǔ)入門


1 人點(diǎn)贊