1. 程式人生 > >原生JS之掃雷

原生JS之掃雷

注:所有程式碼是根據網上教程所編寫

html程式碼

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>掃雷</title>
    <link rel="stylesheet" href="style.css">
    
</head>
<body>
  <div class="wrapper">
      <div class="btn" id="btn"></div>
     
      <div class="box" id="box"></div>
       <div class="flag" id="flag">
          當前剩餘累數:
          <span id="score">10</span>
      </div>
      <div class="alertBox" id="alertBox">
          <div class="alertImg" id="alertImg">
              <div class="close" id="close"></div>
          </div>
      </div>
  </div>
  <script src="sl.js"></script>
</body>
</html>

css程式碼

*{
    margin: 0;
    padding: 0;
}
.wrapper{
    width: 100%;
    height: 1000px;
    position: fixed;
    top:0;
    left: 0;
    background-image:url('img/bg.jpg') ;
    background-size: 100% 100%;
}
.btn{
    height: 80px;
    width: 170px;
    position: absolute;
    left:50%;
    margin-left:-85px; 
    top:75%;
    background-image:url('img/start.gif') ;
    background-size: 100% 100%;
    cursor: pointer;
}
.box{
    height: 500px;
    width: 500px;
    /* 設定景深800px  繞x軸旋轉45°*/
    transform: perspective(500px) rotateX(45deg) ;
    margin: 100px auto;
    /* border:1px solid #B25F27;  */
    border-top:1px solid #B25F27;
    border-left: 1px solid #B25F27; 
    /* 設定邊框陰影 */
    box-shadow: 5px 5px 5px rgba(0,0, 0, 0.3);
    display: none;
   

}
.flag{
    position: absolute;
    top:150px;
    left:50%;
    width: 200px;
    height: 50px;
    margin-left:-100px;
    color: #333333;
    font-size: 20px;
    font-weight: bolder; 
    display: none;
}
.alertBox{
    display: none;
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top:0;
    background-color: rgba(0,0, 0, 0.2);
}
.alertImg{
    height: 400px;
    width: 600px;
    background-size: 100% 100%;
    position: absolute;
    left: 0;
    right: 0;
    top:20%;
    margin: auto;
    border-radius: 20px;
}
.close{
    position: absolute;
    right: 0;
    top:0;
    height: 30px;
    width: 30px;
    background-image: url('img/x.jpg');
    background-size: 100% 100%;
    cursor: pointer;
    border-radius: 20px;

}
.block{
    float: left;
    width: 49px;
    height: 49px;
    border-right: 1px solid #B25F27;
    border-bottom: 1px solid #B25F27;
    /* 向內陰影 */
    box-shadow: 0 0 4px #333333 inset;
    background-image: url('img/green.jpg');
    background-size: 100% 100%;
    cursor: pointer;
}
.show{
    background-image: url('img/mine.jpg');
    background-size: 100% 100%;
}
.num{
    background: #ECD0A1;
    font-size: 18px;
    font-weight: bold;
    line-height: 49px;
    text-align: center;
}
.flagbox{
    background-image: url('img/flag.jpg');
    background-size: 100% 100%;
}

js部分

編碼的邏輯思路

點選開始遊戲 動態生成100個格子-->100div

leftClick沒有雷 顯示數字(代表以當前格子為中心,周圍8個格子的雷個數) 有雷 遊戲結束

擴散(當前周圍沒有雷)

rightClick 沒有標記並且沒有數字--進行標記/有標記--取消標記 判斷標記是否正確,所有都正確標記,提示成功

已經出現數字--不進行任何操作

程式碼

var  startBtn=document.getElementById('btn');
var  box=document.getElementById('box');
var  flag=document.getElementById('flag');
var  alertBox=document.getElementById('alertBox');
var alertImg=document.getElementById('alertImg');
var close=document.getElementById('close');
var  score=document.getElementById('score');
var minesNum;//雷的數量
var minesOver;//被標記的雷的數量
var block;//選中的格子
var mineMap=[];

var  startGame=true;


bindEvent();
function bindEvent(){
    startBtn.onclick=function(){
        if(startGame){
            box.style.display='block';
            flag.style.display='block';
            init();
            startGame=false;
        }
        
        
    }
    //取消預設事件
    box.oncontextmenu=function(){
        return false;
    }

    box.onmousedown=function(e){
        //獲取事件原物件  即當前點選的格子
        var event=e.target;
        //e.which==1代表點選左鍵
        if(e.which==1){
            leftClick(event);
        }//e.which==3代表點選右鍵
        else if(e.which==3){
            rightClick(event);
        }
    }
    close.onclick=function(){
        alertBox.style.display='none';
        flag.style.display='none';
        box.style.display='none';
        box.innerHTML='';
        startGame=true;
    }
}
//生成100個格子  並隨機生成10個雷區
function init(){
    minesNum=10;
    minesOver=10;
    score.innerHTML=minesOver;

    for(var i=0;i<10;i++){
        for(var j=0;j<10;j++){
            var con=document.createElement('div');
            //給生成的每個div新增類名
            con.classList.add('block');
            //用行和列表示每一個格子的id
            con.setAttribute('id',i+'-'+j);
            //將生成的格子插入box裡
            box.appendChild(con);
            mineMap.push({mine:0});
        }
    }

    block=document.getElementsByClassName('block');
    //隨機生成雷區
    while(minesNum){
        var mineIndex=Math.floor(Math.random()*100);
        if(mineMap[mineIndex].mine==0){
            mineMap[mineIndex].mine=1;//表示已經生成雷區
            block[mineIndex].classList.add('ismine');
            minesNum--;
        }
    }
    

}
//dom表示點選事件的原物件
function leftClick(dom){
    //插旗後  不能被左點選
    if(dom.classList.contains('flagbox')){
        return ;
    }
    var ismine=document.getElementsByClassName('ismine');
    if(dom&& dom.classList.contains('ismine')){
        //遊戲失敗的情況
        for(var i=0;i<ismine.length;i++){
            ismine[i].classList.add('show'); 
        }
        setTimeout(function(){
             alertBox.style.display='block'; 
            
             alertImg.style.backgroundImage='url("img/over.jpg")';      
         
           
        },500)
    }
    else {
        var n=0;//表示點選的格子周圍的雷的個數
        var posArr = dom && dom.getAttribute('id').split('-');
        var posX = posArr && +posArr[0];//x軸座標值
        var posY = posArr&& +posArr[1];//y軸座標值
        dom && dom.classList.add('num');
        //座標i,j周圍的關係
        //i-1,j-1   i-1,j  i-1,j+1
        //i,j-1     i,j    i,j+1
        //i+1,j-1   i+1,j  i+1,j+1

        for(var i=posX-1;i<=posX+1;i++){
            for(var j=posY-1;j<=posY+1;j++){
               var aroundBox = document.getElementById(i+'-'+j);
               //aroundBox.classList.contains('ismine')  表示類名為ismine
               if(aroundBox&&aroundBox.classList.contains('ismine')){
                   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);
                      }
                      
                  }
                }
            }
        }
    }
}

function rightClick(dom){
    //判斷是否已經顯示數字  如果已經顯示數字 則不做任何操作
    if(dom.classList.contains('num')){
        return ;
    }
    //toggle切換   如果沒有flagbox類名,則加上,反之則去掉
    dom.classList.toggle('flagbox');
    
    if(dom.classList.contains('ismine')&&dom.classList.contains('flagbox')){
        minesOver--;
    }
    if(dom.classList.contains('ismine')&&!dom.classList.contains('flagbox')){
        minesOver++;
    }
    score.innerHTML=minesOver;
    if(minesOver==0)
    {
       
            alertBox.style.display='block'; 
           
            alertImg.style.backgroundImage='url("img/success.jpg")';      
      
    }
}