SoFunction
Updated on 2025-03-02

Implementing classic mine-sweeping games with pure javascript

I wrote it a long time ago and didn't write comments at that time. I just added it (Damn, I don't know many of them anymore...)

The shortcoming is that I originally wanted to write a statistics on game rankings, and then add it when I have time (it seems like I say that every time and then wait for a long time...)

There is also no implementation: clicking on the first grid cannot be a thunder function

<style>
  ul{padding:0;list-style:none;}
  #mine{overflow:hidden;width:30px;height:30px;border:1px solid #966;}
  #mine li{float:left;width:30px;height:30px;line-height:30px;text-align:center;font-size:14px;color:#222;}
  #mine .mine_01{background:url() no-repeat;}
  #mine .mine_02{background:url() -30px 0 no-repeat;}
  #mine .mine_03{background:url() -60px 0 no-repeat;}
  #mine .mine_04{background:url() -90px 0 no-repeat;}
  #mine .mine_05{background:url() -120px 0 no-repeat;}
  #mine .mine_06{background:url() -150px 0 no-repeat;}
  #mine .mine_07{background:url() -180px 0 no-repeat;}

  #count{font-size:12px;}
  #time{color:#900;font-weight:bold;}
</style>
 <select >
 <option value="8*10">8*10</option>
 <option value="10*10">10*10</option>
 <option value="12*12">12*12</option>
 </select>
 <button id='ready'>restart</button>
<div >
 Timer: <span >0</span>
</div>

<ul >

</ul>

ie6+ ff oprea Google
opera Early versions Events are not supported by default No good alternative was found
<script>
var $ = function(id){return (id)};
=function ready(){
  var V=$('wh').('*')
  setMineField(Number(V[0]),Number(V[1]));
  
  $('wh').onchange=$('ready').onclick=function(){
    V=$('wh').('*')
    setMineField(Number(V[0]),Number(V[1]))
  }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------var mineField={
  _mineW:30,   //The width of each thunder must be synchronized with the style  _mineH:30,
  _mineFieldBlock:$('mine'),
  _mineFieldEle:$('mine').getElementsByTagName('li'),
  _time:$('time'),
  
  status:0,   //Minefield status 0 has not started yet 1 has started. Timed already 2 The game is over.  mineNum:0,   //Thunder number  clearPlace:0, //The grid for statistics and sweep;  x:0,      //List  y:0,      //OK  density:0.2,  //The density of the minefield should not exceed 0.5. In some sizes of minefields, too high settings cannot be generated. MineMap array cannot be generated if the minefields are set.  mineMap:[],  //The two-dimensional diagram of the minefield, 0: Not a thunder -1: thunder  time:-1,    //Time s  debug:false   //Debug mode}//mineField object end

function timedCount(){
  if(!=1){return false}
  ++;
  mineField._time.innerHTML=;
  setTimeout("timedCount()",1000);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------function setThisMine(str,index){

  var allMine=mineField._mineFieldEle;
  //Set whether to insert a flag on the thunder  if(str=='setOn'){
    var thisMine=allMine[index];
    =<2?+1:0;
    if(==1){='mine_03';}//Put the flag    else if(==2){='mine_04'}//Cancel flag insertion    else if(==0){='mine_01'}//Cancel flag insertion    return false;
  }
  //Show grid  if(str=='show'){
    if((index) === '[object Array]'){// Show a large piece      =+;
      for(var i=0;i<;i++){
        var thisMine=allMine[index[i]];
        =[];
        ='mine_02';
        =3;
      }
    }
    else{//Show a single non-thunder area      ++;
      allMine[index].on=3;
      allMine[index].innerHTML=[index];
      allMine[index].className='mine_02';
    }
    if(==*){//congratulations      alert('congratulations');
      for(var i=0;i<;i++){
        if([allMine[i].index]==-1){
          allMine[i].className='mine_07';
        }
      }
      =2;
      return false;
    }
  }
  //Show all thunder  if(str=='peng'){
      for(var i=0;i<;i++){
        if([allMine[i].index]==-1){
          allMine[i].className=i==index?'mine_06':'mine_05';
        }
      }
      =2;
  }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------function setMineField(a,b){
    var thisMineFiele=mineField._mineFieldBlock;
    DivBox=("div"),
    num=a*b,k=0;
    ='';
    //Minefield parameter adjustment    =a;//How many columns are there    =b;//How many lines are there    =(a*b*);
    =0;
    =-1;
    =0;
    =0;
    mineField._time.innerHTML=0;
        
    //Generate a minefield map    setMineMap();
    //Generate minefields (create li)    while(k<num){
    var newLi=("li");
    if() =[k];//Cheating    ='mine_01';
    (newLi);
    k++;
    }
    =mineField._mineW*b+'px';
    =mineField._mineH*a+'px';
    =;
    DivBox=null;
    setEvent();//event}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------function setMineMap(){
    var num=*,
      mineNum=,
      Interval=(num/mineNum);
    for(var i=0;i<num;i++){
      if(i%Interval==0&&i<mineNum*Interval){[i]=-1;}else{[i]=0;}//Thunder equidistance distribution and array    }
    (function(){ return 0.5 - ()})//Suppress the array    
    //Judge whether there are lightnings around the grid. If so, regenerate minefields to avoid the existence of large minefields    var br=0,//There is a line      x=,
      L_T,T,R_T,L,R,L_B,B,R_B;
    for(var i=0;i<num;i++){
      br=((i+1)/x);
      L_T = i-x-1;
      T  = i-x;
      R_T = i-x+1;
      L  = i-1;
      R  = i+1;
      L_B = i+x-1;
      B  = i+x;
      R_B = i+x+1;
       //Sit on the corner If it is in the minefield and is in the previous line and he is not a lightning, then perform the next square detection       if(L_T>=0&&((L_T+1)/x)==br-1&&[L_T]==0){continue}
       if(T >=0&&((T +1)/x)==br-1&&[T ]==0){continue}
       if(R_T>=0&&((R_T+1)/x)==br-1&&[R_T]==0){continue}
       
       if(L>=0 &&((L+1)/x)==br&&[L]==0){continue}
       if(R<num&&((R+1)/x)==br&&[R]==0){continue}
       
       if(L_B<num&&((L_B+1)/x)==br+1&&[L_B]==0){continue}
       if(B <num&&((B +1)/x)==br+1&&[B ]==0){continue}
       if(R_B<num&&((R_B+1)/x)==br+1&&[R_B]==0){continue}
       
       setMineMap();
       return false
    }
    //Count the number of thunders around the non-thunder square    for(i=0;i<num;i++){
       if([i]==-1){continue}
       var thisMineNum=0
       br=((i+1)/x);
       L_T = i-x-1;
       T  = i-x;
       R_T = i-x+1;
       L  = i-1;
       R  = i+1;
       L_B = i+x-1;
       B  = i+x;
       R_B = i+x+1;
       
       if(L_T>=0&&((L_T+1)/x)==br-1&&[L_T]==-1){thisMineNum++;}
       if(T >=0&&((T +1)/x)==br-1&&[T ]==-1){thisMineNum++;}
       if(R_T>=0&&((R_T+1)/x)==br-1&&[R_T]==-1){thisMineNum++;}
       
       if(L>=0 &&((L+1)/x)==br&&[L]==-1){thisMineNum++;}
       if(R<num&&((R+1)/x)==br&&[R]==-1){thisMineNum++;}
       
       if(L_B<num&&((L_B+1)/x)==br+1&&[L_B]==-1){thisMineNum++;}
       if(B <num&&((B +1)/x)==br+1&&[B ]==-1){thisMineNum++;}
       if(R_B<num&&((R_B+1)/x)==br+1&&[R_B]==-1){thisMineNum++;}
       
       [i]=thisMineNum;
    }
}
//-----------------------------------------------------------------------------------------------------------------------------function setEvent(){
    var thisMineFiele=mineField._mineFieldBlock,
      allMine=mineField._mineFieldEle,
      iMax=*;
    for(var i=0;i<iMax;i++){
      allMine[i].index=i;
      allMine[i].on=0;//0 is the default 1 is the flag insertion 2 is the question mark 3 is the display    }
    =function(e){
      if(==2){return false;}
      if(==0){=1;timedCount();}
      var e=e||,
        thisObj=||;
      if(=='UL'||==3){return false;}
      
      var Btn=getButton(e);
      if(Btn== 0){//Left key        if(==1){return false;}//I can't illuminate the flag once I put it in.
        if([]==-1){//The lightning is on          setThisMine('peng',);
        }else if([]==0){//Click to the open space. Open a large area          //alert('You are so lucky')          var allShowMine=minesShow();
          setThisMine('show',allShowMine)
        }else{//Show a grid          setThisMine('show',)
        }
      }
      if(Btn== 2){//Right click       setThisMine('setOn',);
      }
    }
}
//-----------------------------------------------------------------------------------------------------------------------------function minesShow(I){
      var allMine=mineField._mineFieldEle,
        allShowMine=[I];//Save the subscript of the thunder to be displayed      
      allMine[I].on=3;
      
      see(I);//Query the squares around the subscript I      function see(allI){
        var _allI=[];
        if((allI) === '[object Array]'){
          for(var i=0;i<;i++){f(allI[i])}
        }
        else{f(allI)}
        function f(thisI){
          var text,
          x=,
          br,
          num=x*,
          L_T,T,R_T,L,R,L_B,B,R_B;
        
          text='_'+('_')+'_';// Used to determine whether the subscript has been written to the array          br=((thisI+1)/x);
          L_T = thisI-x-1;
          T  = thisI-x;
          R_T = thisI-x+1;
          L  = thisI-1;
          R  = thisI+1;
          L_B = thisI+x-1;
          B  = thisI+x;
          R_B = thisI+x+1;
         //If the square in the upper left corner is in the minefield, it is in the previous line, it is a grid that has not been opened, and it is a space, then write it as _allI array to perform the next search         if(L_T>=0&&((L_T+1)/x)==br-1&&allMine[L_T].on==0&&[L_T] == 0){_allI.push(L_T);}
         if(T >=0&&((T +1)/x)==br-1&&allMine[T ].on==0&&[T ] == 0){_allI.push(T);}
         if(R_T>=0&&((R_T+1)/x)==br-1&&allMine[R_T].on==0&&[R_T] == 0){_allI.push(R_T);}
       
         if(L>=0&&((L+1)/x)==br&&allMine[L].on==0&&[L] == 0){_allI.push(L);}
         if(R<num&&((R+1)/x)==br&&allMine[R].on==0&&[R] == 0){_allI.push(R);}
       
         if(L_B<num&&((L_B+1)/x)==br+1&&allMine[L_B].on==0&&[L_B] == 0){_allI.push(L_B);}
         if(B <num&&((B +1)/x)==br+1&&allMine[B ].on==0&&[B ] == 0){_allI.push(B);}
         if(R_B<num&&((R_B+1)/x)==br+1&&allMine[R_B].on==0&&[R_B] == 0){_allI.push(R_B);}
         //------------------------------------------------
         //If the grid in the upper left corner is in the minefield, it is in the previous line, it is a grid that has not been opened, and it is not written into the allShowMine array, then write it and mark it as a grid that has been opened in advance.         if(L_T>=0&&((L_T+1)/x)==br-1&&allMine[L_T].on==0&&('_'+L_T+'_') == -1){(L_T);allMine[L_T].on=3}
         if(T >=0&&((T +1)/x)==br-1&&allMine[T ].on==0&&('_'+T+'_') == -1){(T);allMine[T].on=3}
         if(R_T>=0&&((R_T+1)/x)==br-1&&allMine[R_T].on==0&&('_'+R_T+'_') == -1){(R_T);allMine[R_T].on=3}
       
         if(L>=0&&((L+1)/x)==br&&allMine[L].on==0&&('_'+L+'_') == -1){(L);allMine[L].on=3}
         if(R<num&&((R+1)/x)==br&&allMine[R].on==0&&('_'+R+'_') == -1){(R);allMine[R].on=3}
       
         if(L_B<num&&((L_B+1)/x)==br+1&&allMine[L_B].on==0&&('_'+L_B+'_') == -1){(L_B);allMine[L_B].on=3}
         if(B <num&&((B +1)/x)==br+1&&allMine[B ].on==0&&('_'+B+'_') == -1){(B );allMine[B ].on=3}
         if(R_B<num&&((R_B+1)/x)==br+1&&allMine[R_B].on==0&&('_'+R_B+'_') == -1){(R_B);allMine[R_B].on=3}
         
         if(_allI.length!=0){see(_allI)}
        }
      }
      return allShowMine
}
//--------------------------------------
=function(){return false;}//Right-click menu prohibitedfunction getButton(e){
  var Btn;
  if(('MouseEvents','2.0')){Btn=;}
  else{    switch(){
          case 0:
          case 1:
          case 3:
          case 5:
          case 7:
           Btn=0;
           break;
          case 2:
          case 6:
           Btn=2;
           break;
          case 4:
           Btn=9;
           break;
        }
  }
  return Btn;
}
</script>

The above is the entire content of this article, I hope you like it.