一步步教你使用JavaScript打造一個(gè)掃雷游戲
前言
掃雷大家都玩過(guò),今天我們就是用JavaScript來(lái)打造掃雷游戲。廢話不多說(shuō),直接看下效果;
上圖是失敗后的結(jié)果。
一、思路分析
我們新建一個(gè)首頁(yè),在首頁(yè)放置一個(gè)點(diǎn)擊開(kāi)始游戲的按鈕,動(dòng)態(tài)生成100個(gè)小格,即100div;然后通過(guò)點(diǎn)擊div進(jìn)行掃雷操作,然后掃雷成功或者失敗顯示對(duì)應(yīng)的結(jié)果;
二、靜態(tài)頁(yè)面搭建
2.1 結(jié)構(gòu)層
<body> <div class="wrapper"> <div class="btn" id="btn"></div> <!-- 開(kāi)始游戲按鈕--> <div class="box" id="box"></div> <!-- 存放小雷的div--> <div class="flagBox" id="flagBox"> <!-- 游戲結(jié)束才顯示的當(dāng)前雷數(shù)的div--> 當(dāng)前剩余雷數(shù): <span id="score">10</span> </div> <div class="alertBox" id="alertBox"> <!-- Game over彈出的框(窗口)--> <div class="alertImg" id="alertImg"> <div class="close" id="close"></div> </div> </div> </div> </body>
2.2 樣式層
清楚默認(rèn)邊距
*{ margin:0; padding:0; }
頁(yè)面最大div
.wrapper { width:100%; height:1000px; position: fixed; top:0; left:0; background-image: url('img/bg.jpg'); background-size: 100% 100%; }
效果如下:
開(kāi)始游戲按鈕
.btn{ height:140px; width:170px; position:absolute; left:50px; background-image: url('img/startGame.png'); background-size: 100% 100%; cursor: pointer; }
儲(chǔ)存雷的大div
.box{ height:500px; width:500px; transform: perspective(800px) rotateX(45deg); margin:20px auto; border-top:1px solid #B25F27; border-left:1px solid #B25F27; box-shadow: 5px 5px 5px rgba(0,0,0,0.3); display:none; /* 先設(shè)置為none,開(kāi)始游戲后顯示block */ }
每一個(gè)方塊的小div(一共100個(gè))
.block{ width:49px; height:49px; border-right:1px solid #B25F27; border-bottom:1px solid #B25F27; box-shadow: 0 0 4px #333 inset; background-image: url('img/cao.jpg'); float: left; }
當(dāng)前所剩雷數(shù)
.flagBox{ position:absolute; top:50px; left:50%; width:200px; height:50px; margin-left:-100px; color:#333; font-size:20px; font-weight: bolder; display:none; /* 先設(shè)置為none,開(kāi)始游戲后顯示block */ }
Game Over
.alertBox{ display:none; /* 先設(shè)置為none,開(kāi)始結(jié)束顯示block */ position:absolute; width:100%; height:100%; left:0; top:0; background-color: rgba(0,0,0,0.2); }
游戲結(jié)束彈出窗口右上角的X
.close{ position:absolute; right:0; top:0; height:40px; width:40px; background-image: url('img/closeBtn.png'); background-size: 100% 100%; cursor: pointer; ???????}
三、js頁(yè)面交互
3.1 獲取元素及變量初始化
var startBtn = document.getElementById('btn'); var box = document.getElementById('box'); var flagBox = document.getElementById('flagBox'); var alertBox = document.getElementById('alertBox'); var alertImg = document.getElementById('alertImg'); var closeBtn = document.getElementById('close'); var score = document.getElementById('score'); // 先聲明變量,但是不初始化 var minesNum; var mineOver; var block; var mineMap = []; var startGameBool = true;
3.2 10個(gè)雷的初始化設(shè)置
function init() { minesNum = 10; mineOver = 10; score.innerHTML = mineOver; for (var i = 0; i < 10; i++) { // 雙層循環(huán) 10 * 10 個(gè)div for (var j = 0; j < 10; j++) { var con = document.createElement('div'); con.classList.add('block'); // 給創(chuàng)建出來(lái)的div添加類(lèi)名 block con.setAttribute('id', i + '-' + j); box.appendChild(con); mineMap.push({ mine: 0 }); } } block = document.getElementsByClassName('block'); while (minesNum) { // 創(chuàng)建一個(gè)10次的循環(huán),即設(shè)置10個(gè)雷 var mineIndex = Math.floor(Math.random() * 100); if (mineMap[mineIndex].mine === 0) { mineMap[mineIndex].mine = 1; block[mineIndex].classList.add('isLei'); // 10個(gè)雷有小div的block類(lèi)屬性,還有自己的屬性,isLei minesNum--; } } }
3.3 游戲開(kāi)始事件封裝
function bindEvent() { startBtn.onclick = function () { // 開(kāi)始按鈕點(diǎn)擊事件 if(startGameBool){ box.style.display = 'block'; flagBox.style.display = 'block'; init(); startGameBool = false; } } box.oncontextmenu = function () { return false; } box.onmousedown = function (e) { // 小div鼠標(biāo)按下事件封裝 var event = e.target; if (e.which == 1) { //Netscape/Firefox/Opera中不支持 window.event.keyCode,需要用event.which代替 leftClick(event); } else if (e.which == 3) { rightClick(event); } } closeBtn.onclick = function () { // 游戲結(jié)束,彈出game over窗口的關(guān)閉按鈕事件封裝 alertBox.style.display = 'none'; flagBox.style.display = 'none'; box.style.display = 'none'; box.innerHTML = ''; startGameBool = true; } }
3.4 核心事件函數(shù)封裝
leftClick 沒(méi)有雷 --> 顯示數(shù)字(代表以當(dāng)前小格為中心周?chē)?個(gè)格的雷數(shù))擴(kuò)散(當(dāng)前周?chē)藗€(gè)格沒(méi)有雷) 有雷 --> game Over
function leftClick(dom) { if(dom.classList.contains('flag')){ return; } var isLei = document.getElementsByClassName('isLei'); // 獲得前面的10個(gè)雷的div if (dom && dom.classList.contains('isLei')) { // 判斷是不是雷塊 for (var i = 0; i < isLei.length; i++) { isLei[i].classList.add('show'); // 顯示地雷背景圖 } setTimeout(function () { alertBox.style.display = 'block'; alertImg.style.backgroundImage = 'url("img/over.jpg")'; // 上面顯示雷,標(biāo)志游戲結(jié)束 }, 800) } else { // 否則繼續(xù)掃雷 var n = 0; var posArr = dom && dom.getAttribute('id').split('-'); var posX = posArr && +posArr[0]; var posY = posArr && +posArr[1]; dom && dom.classList.add('num'); for (var i = posX - 1; i <= posX + 1; i++) { for (var j = posY - 1; j <= posY + 1; j++) { var aroundBox = document.getElementById(i + '-' + j); if (aroundBox && aroundBox.classList.contains('isLei')) { n++; } } } dom && (dom.innerHTML = n); if (n == 0) { for (var i = posX - 1; i <= posX + 1; i++) { for (var j = posY - 1; j <= posY + 1; j++) { var nearBox = document.getElementById(i + '-' + j); if (nearBox && nearBox.length != 0) { if (!nearBox.classList.contains('check')) { nearBox.classList.add('check'); leftClick(nearBox); } } } } } } }
rightClick 沒(méi)有標(biāo)記并且沒(méi)有數(shù)字 --> 進(jìn)行標(biāo)記;
有標(biāo)記 --> 取消標(biāo)記 --> 標(biāo)記是否正確,10個(gè)都正確標(biāo)記,提示成功;
如果已經(jīng)出現(xiàn),則點(diǎn)擊無(wú)效果;
function rightClick(dom){ if(dom.classList.contains('num')){ // 如果已經(jīng)出現(xiàn),則點(diǎn)擊無(wú)效果 return; } dom.classList.toggle('flag'); // 在元素中切換類(lèi)名,切換為flag類(lèi)名,顯示紅旗背景圖;此處的雷被掃除了 if(dom.classList.contains('isLei') && dom.classList.contains('flag')){ mineOver --; // 雷數(shù)減一 } if(dom.classList.contains('isLei') && !dom.classList.contains('flag')){ mineOver ++; } score.innerHTML = mineOver; if(mineOver == 0){ // 掃完雷,標(biāo)志雷數(shù)量為0 alertBox.style.display = 'block'; alertImg.style.backgroundImage = 'url("img/success.png")'; // 游戲勝利 } }
3.5 游戲開(kāi)始
bindEvent()
四、總結(jié)
本文我們通過(guò)JavaScript打造了簡(jiǎn)單的掃雷游戲,首先是設(shè)計(jì)下簡(jiǎn)單的界面樣式,然后通過(guò)掃雷的邏輯動(dòng)態(tài)構(gòu)建雷塊的位置,通過(guò)點(diǎn)擊小方塊進(jìn)行掃雷,感興趣的小伙伴可以去試一下。
到此這篇關(guān)于如何使用JavaScript打造一個(gè)掃雷游戲的文章就介紹到這了,更多相關(guān)JavaScript打造掃雷游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何解決日期函數(shù)new Date()瀏覽器兼容性問(wèn)題
這篇文章主要介紹了如何解決日期函數(shù)new Date()瀏覽器兼容性問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09javascript 模擬JQuery的Ready方法實(shí)現(xiàn)并出現(xiàn)的問(wèn)題
今天在閱讀網(wǎng)上一些模擬Jq的ready方法時(shí),發(fā)現(xiàn)一些小細(xì)節(jié),就是網(wǎng)上的ready事件大部分都是在onload事件執(zhí)行后加載,而jquery確能在onload加載前。2009-12-12Javascript實(shí)現(xiàn)基本運(yùn)算器
這篇文章主要為大家詳細(xì)介紹了Javascript實(shí)現(xiàn)基本運(yùn)算器的相關(guān)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07小程序?qū)崿F(xiàn)列表倒計(jì)時(shí)功能
這篇文章主要為大家詳細(xì)介紹了小程序?qū)崿F(xiàn)列表倒計(jì)時(shí)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01JavaScript中callee和caller的區(qū)別與用法實(shí)例分析
這篇文章主要介紹了JavaScript中callee和caller的區(qū)別與用法,結(jié)合實(shí)例形式分析了javascript中callee和caller的功能、區(qū)別、用法及操作注意事項(xiàng),需要的朋友可以參考下2019-06-06基于Bootstrap實(shí)現(xiàn)的下拉菜單手機(jī)端不能選擇菜單項(xiàng)的原因附解決辦法
小編使用bootstrap做的下拉菜單在電腦瀏覽器中可以正常使用,在手機(jī)瀏覽器中能彈出下拉列表卻不能選擇列表中的菜單項(xiàng),怎么回事,如何解決呢?下面小編給大家分享下具體原因及解決辦法,一起看下吧2016-07-07JavaScript使用prototype原型實(shí)現(xiàn)的封裝繼承多態(tài)示例
這篇文章主要介紹了JavaScript使用prototype原型實(shí)現(xiàn)的封裝繼承多態(tài),涉及javascript prototype與面向?qū)ο蟪绦蛟O(shè)計(jì)相關(guān)操作技巧,需要的朋友可以參考下2018-08-08Webpack-cli安裝成功后查看webpack -v報(bào)錯(cuò)案例詳解
這篇文章主要介紹了Webpack-cli安裝成功后查看webpack -v報(bào)錯(cuò)案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09js替換字符串中所有指定的字符(實(shí)現(xiàn)代碼)
下面小編就為大家?guī)?lái)一篇js替換字符串中所有指定的字符(實(shí)現(xiàn)代碼)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-08-08