手把手教你使用JavaScript打造一款掃雷游戲
回復(fù)“資源”即可獲贈Python學(xué)習(xí)資料
大家好,我是皮皮。
掃雷大家都玩過,今天我們就是用JavaScript來打造掃雷游戲。廢話不多說,直接看下效果;

上圖是失敗后的結(jié)果。
一、思路分析
我們新建一個首頁,在首頁放置一個點(diǎn)擊開始游戲的按鈕,動態(tài)生成100個小格,即100div;然后通過點(diǎn)擊div進(jìn)行掃雷操作,然后掃雷成功或者失敗顯示對應(yīng)的結(jié)果;
二、靜態(tài)頁面搭建
2.1 結(jié)構(gòu)層
<body>
????<div?class="wrapper">
????????<div?class="btn"?id="btn">div>??
????????<div?class="box"?id="box">div>??
????????<div?class="flagBox"?id="flagBox">?
????????????當(dāng)前剩余雷數(shù):
????????????<span?id="score">10span>
????????div>
????????<div?class="alertBox"?id="alertBox">??
????????????<div?class="alertImg"?id="alertImg">
????????????????<div?class="close"?id="close">div>
????????????div>
????????div>
????div>
body>
2.2 樣式層
清楚默認(rèn)邊距
*{
????margin:0;
????padding:0;
}
頁面最大div
.wrapper?{
????width:100%;
????height:1000px;
????position:?fixed;
????top:0;
????left:0;
????background-image:?url('img/bg.jpg');
????background-size:?100%?100%;
}
效果如下:

開始游戲按鈕
.btn{
????height:140px;
????width:170px;
????position:absolute;
????left:50px;
????background-image:?url('img/startGame.png');
????background-size:?100%?100%;
????cursor:?pointer;
}
儲存雷的大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,開始游戲后顯示block?*/?
}
每一個方塊的小div(一共100個)
.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,開始游戲后顯示block?*/?
}
Game Over
.alertBox{
????display:none;?/*?先設(shè)置為none,開始結(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頁面交互
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個雷的初始化設(shè)置
function?init()?{
????minesNum?=?10;
????mineOver?=?10;
????score.innerHTML?=?mineOver;
????
????for?(var?i?=?0;?i?10;?i++)?{?//?雙層循環(huán)?10?*?10?個div
????????for?(var?j?=?0;?j?10;?j++)?{
????????????var?con?=?document.createElement('div');
????????????con.classList.add('block');?//?給創(chuàng)建出來的div添加類名?block?
????????????con.setAttribute('id',?i?+?'-'?+?j);
????????????box.appendChild(con);
????????????mineMap.push({?mine:?0?});
????????}
????}
????block?=?document.getElementsByClassName('block');
????while?(minesNum)?{?//?創(chuàng)建一個10次的循環(huán),即設(shè)置10個雷
????????var?mineIndex?=?Math.floor(Math.random()?*?100);
????????if?(mineMap[mineIndex].mine?===?0)?{
????????????mineMap[mineIndex].mine?=?1;
????????????block[mineIndex].classList.add('isLei');?//?10個雷有小div的block類屬性,還有自己的屬性,isLei
????????????minesNum--;
????????}
????}
}
3.3 游戲開始事件封裝
function?bindEvent()?{
????startBtn.onclick?=?function?()?{?//?開始按鈕點(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 ?沒有雷 ?--> 顯示數(shù)字(代表以當(dāng)前小格為中心周圍8個格的雷數(shù))擴(kuò)散(當(dāng)前周圍八個格沒有雷) 有雷? ? ?--> ?game Over
function?leftClick(dom)?{
????if(dom.classList.contains('flag')){
????????return;
????}
????var?isLei?=?document.getElementsByClassName('isLei');?//?獲得前面的10個雷的div
????if?(dom?&&?dom.classList.contains('isLei'))?{?//?判斷是不是雷塊
????????for?(var?i?=?0;?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 ? ?沒有標(biāo)記并且沒有數(shù)字 --> 進(jìn)行標(biāo)記;
有標(biāo)記 --> 取消標(biāo)記 --> 標(biāo)記是否正確,10個都正確標(biāo)記,提示成功;
如果已經(jīng)出現(xiàn),則點(diǎn)擊無效果;
function?rightClick(dom){
????if(dom.classList.contains('num')){?//?如果已經(jīng)出現(xiàn),則點(diǎn)擊無效果
????????return;
????}
????dom.classList.toggle('flag');?//?在元素中切換類名,切換為flag類名,顯示紅旗背景圖;此處的雷被掃除了
????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 游戲開始
bindEvent()
四、總結(jié)
本文我們通過JavaScript打造了簡單的掃雷游戲,首先是設(shè)計(jì)下簡單的界面樣式,然后通過掃雷的邏輯動態(tài)構(gòu)建雷塊的位置,通過點(diǎn)擊小方塊進(jìn)行掃雷,感興趣的小伙伴可以去試一下。
小伙伴們,快快用實(shí)踐一下吧!如果在學(xué)習(xí)過程中,有遇到任何問題,歡迎加我好友,我拉你進(jìn)Python學(xué)習(xí)交流群共同探討學(xué)習(xí)。
-------------------?End?-------------------
往期精彩文章推薦:

歡迎大家點(diǎn)贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持
想加入Python學(xué)習(xí)群請?jiān)诤笈_回復(fù)【入群】
萬水千山總是情,點(diǎn)個【在看】行不行
