Heim  >  Artikel  >  Web-Frontend  >  JavaScript zum Erstellen eines klassischen Minesweeper-Spiels für Windows_Javascript-Kenntnisse

JavaScript zum Erstellen eines klassischen Minesweeper-Spiels für Windows_Javascript-Kenntnisse

WBOY
WBOYOriginal
2016-05-16 16:06:471373Durchsuche

Der Code ist eigentlich sehr einfach, daher wird es hier nicht viel Unsinn geben

<html>
<head>
<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>扫雷-JavaScript Mine Sweeper</title>
<style type="text/css">
table{TABLE-LAYOUT: fixed;cursor:pointer}
td{width: 20px; height: 20px; font-size: 12px; font-family: Verdana;font-weight:bold; text-align:center;background:#CECECE;}
td.Normal, .Flag{border-left:2px solid #F5F5F5; border-right:2px outset #F5F5F5; border-top:2px solid #F5F5F5; border-bottom:2px outset #F5F5F5; font-weight:bold}
.Mine, .Boom, .M0, .M1, .M2, .M3, .M4, .M5, .M6, .M7, .M8{background:#C5C5C5;border-right:1px solid #B4B4B4; border-bottom:1px solid #B4B4B4;}
td.Mine{background: url(http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/mine.gif) no-repeat center}
td.Boom{background:#F00 url(http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/mine.gif) no-repeat center}
td.Flag, td.ErrFlag{background-image: url(http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/flag.gif);background-repeat: no-repeat; background-position: center;}
td.ErrFlag{background:#0F0}
td.M1 {color: #00f}
td.M2 {color: #008000}
td.M3 {color: #f00}
td.M4 {color: #000080}
td.M5 {color: #800000}
td.M6 {color: #008080}
td.M7 {color: #000}
td.M8 {color: #808080}
</style>
<script>
var $=function(id){return document.getElementById(id)},
  MouseButton=LeftMouse=0,//作为双键单击的计数,mouseup事件置0,mousedown事件+1,当MouseButton=2说明双键同时单击;鼠标左键是否按下,当鼠标左键按下时为1,松开为0
  FlagImg=new Image(),
  HappyImg=new Image(),
  MineImg=new Image(),
  SadImg=new Image(),
  SuccessImg=new Image(),
 
  WhichButton=function(e){
    e=e||window.event;
    var b=getOs();
    if(b!=2){ //非FF
      switch(e.button){
        case 2:
          return 0;
        case 0:
          return b==1&#63;0:1; //b==1,IE
        default:
          return 1;
      }
    }else{ //FF
      return e.which==3&#63;0:1;
    }
  },
 
OMine={
  MaxX:9,MaxY:9,//最大的坐标
  MineCount:10,//定义雷的个数,可改
  FlagCount:0, //已经标记的旗子的数量
  OpenedCount:0, //已经打开的地区的数量
  MaxOpenCount:0,//应该要打开的最大地区数量
  //当OpenedCount=MaxOpenCount&&FlagCount=MineCount的时候,判断游戏成功结束
  Mine:[],
  GameOver:false, //true代表游戏失败结束
  Success:false, //true代表游戏成功结束
  aClear:[],//临时开雷的数组
   
  //刷新网页的时候初始化
  fInit:function(){
    var T=this,MaxX=T.MaxX,MaxY=T.MaxY,nX,nY=MaxY,MineCount=T.MineCount,
      AStr=['<table bordercolor="#000000" border="0" cellpadding="0" cellspacing="0" height="'+20*MaxY+'px" width="'+20*MaxX+'px" style="border: 10px inset #a0a0a0">'],
      i=0,TAr,TMine=T.Mine;
    T.MaxOpenCount=MaxX*MaxY-MineCount;
    while(nY--){
      AStr[++i]='<tr>';
      TAr=TMine[nY]=[];
      nX=MaxX;
      while(nX--){
        AStr[++i]='<td class="Normal" onmousedown="OMine.fMouseDown('+nX+','+nY+',event);" onmouseup="OMine.fMouseUp('+nX+','+nY+',event);" onmouseover="OMine.fButtonMouseOver('+nX+','+nY+')" onmouseout="OMine.fButtonMouseOut('+nX+','+nY+')" id="Img'+nX+'_'+nY+'"> </td>';
        TAr[nX]={
          Mine:0, //0表示没有雷,1表示有雷
          State:0,//0表示未开启,1表示左键开启,2表示右键标记
          MineCount:0//周围有几个雷
        }
      }
       AStr[++i]='</tr>';
    }
    AStr[++i]='</table>';
    $('dMap').innerHTML=T.InitStr=AStr.join('');
    $('txtFlagCount').value=MineCount;
    T.fInitMine();
    $('btnRefreshMap').src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/happy.gif';
    T.GameOver=T.Success=false;
    T.OpenedCount=T.FlagCount=T.aClear.lenght=0;
  },
   
  //为了方便循环赋值,给表格数组赋值的时候是XY倒过来循环的,所以调用的时候要倒回去
  //比如要获得该格子是否有雷,用OMine.fGetMine(x,y).Mine;
  fGetMine:function(X,Y){return this.Mine[Y][X]},
   
  //仅当按重新开始的按钮,不初始化大表格字符
  fRefreshMap:function(){
    var T=this;
    $('dMap').innerHTML=T.InitStr;
    T.fResetOMine();//必须先重置OMine,再重置99个雷
    T.fInitMine();
    T.GameOver=T.Success=false;
    $('btnRefreshMap').src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/happy.gif';
    $('txtFlagCount').value=T.MineCount;
    T.OpenedCount=T.FlagCount=T.aClear.lenght=0;
  },
 
  //重置OMine.Mine数组
  fResetOMine:function(){
    var T=this,MaxY=T.MaxY,MaxX=T.MaxX,X,Y=MaxY,M,Mine=T.Mine,TAr;
    while(Y--){
      X=MaxX;
      TAr=Mine[Y];
      while(X--)(M=TAr[X]).Mine=M.State=M.MineCount=0;
    }
  },
   
  //初始化雷的数组
  fInitMine:function(){
    var T=this,MaxX=T.MaxX,MaxY=T.MaxY,a,fGetMine=T.fGetMine,
      aOld=[],x,y=MaxY,n=0,l=T.MineCount,xRand; //一个随机数字
    while(y--){
      x=MaxX;
      while(x--)aOld[n++]=[x,y];
    }
    while(l--){
      a=aOld[xRand=Math.floor(Math.random()*(n-1))];
      T.fGetMine(a[0],a[1]).Mine=1;
      aOld.splice(xRand,1);
      --n;
    }
  },
 
  //鼠标移动到某格子的时候
  fButtonMouseOver:function(X,Y){
    var T=this;
    switch(MouseButton){
      case 2://双键按下的状态
        var arr=T.fGetAround(X,Y),i=arr.length,TAr;
        while(i--)T.fButtonDown((TAr=arr[i])[0],TAr[1]);
      case 1:
        LeftMouse==1&&T.fButtonDown(X,Y); //左键是按下的
    }
  },
   
  //鼠标移出某格子的时候
  fButtonMouseOut:function(X,Y){
    var T=this;
    switch(MouseButton){
      case 2://双键按下的状态
        var arr=T.fGetAround(X,Y),i=arr.length,TAr;
        while(i--)T.fButtonUp((TAr=arr[i])[0],TAr[1]);
      case 1:
        LeftMouse==1&&T.fButtonUp(X,Y); //左键是按下的
    }
  },
 
  //鼠标按下时没被开启的格子呈现被按下
  fButtonDown:function(X,Y){
    var srcEle=$('Img'+X+'_'+Y);
    srcEle.className=='Normal'&&(srcEle.className='M0');
  },
   
  //让没被开启并且已经呈现被按下的格子回复Normal
  fButtonUp:function(X,Y){
    var srcEle=$('Img'+X+'_'+Y);
    srcEle.className=='M0'&&!this.fGetMine(X,Y).State&&(srcEle.className='Normal');
  },
   
  //获取8个方向的坐标
  fGetAround:function(X,Y){
    var TX,TY,i=8,MX=this.MaxX-1,MY=this.MaxY-1,
      Arr=[[-1,0],[-1,-1],[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1]],
      newArr=[],TAr;
    while(i--){
      TX=X+(TAr=Arr[i])[0];
      TY=Y+TAr[1];
      !(TX<0||TX>MX||TY<0||TY>MY)&&newArr.push([TX,TY]);
    }
    return newArr;
  },
   
  //鼠标在格子按下
  fMouseDown:function(X,Y,evt){
    var T=this;
    if(T.GameOver){
      alert('游戏失败,再接再厉!');
      return;
    }
    if(T.Success){
      alert('恭喜游戏成功!再来一局吧?');
      return;
    }
    var srcEle=$('Img'+X+'_'+Y),ObXY=T.fGetMine(X,Y),arr,i,TAr;
    ++MouseButton;
    evt=evt||window.event;
    switch(MouseButton){
      case 2:
        arr=T.fGetAround(X,Y);i=arr.length;
        while(i--)T.fButtonDown((TAr=arr[i])[0],TAr[1]);
        break;
      case 1:
        if(WhichButton(evt)){
          LeftMouse=1;
          T.fButtonDown(X,Y);
        }else{
          switch(ObXY.State){
            case 0:
              ObXY.State=2;
              srcEle.className='Flag';
              --$('txtFlagCount').value;
              ++T.FlagCount;
              break;
            case 2:
              ObXY.State=0;
              srcEle.className='Normal';
              ++$('txtFlagCount').value;
              --T.FlagCount;
          }
        }
      }
  },
   
  //鼠标在格子弹起
  fMouseUp:function(X,Y,evt){
    var T=this;
    evt=evt||window.event;
    var srcEle=$('Img'+X+'_'+Y),ObXY=T.fGetMine(X,Y),arr,i,TAr;
    switch(MouseButton){
      case 2: //MouseDown为两个键都单击按下,任意一个键弹起都判断为双键弹起
        LeftMouse=0;
        //鼠标弹起,把呈现被按下状态的格子恢复
        arr=T.fGetAround(X,Y);i=arr.length;
        while(i--)T.fButtonUp((TAr=arr[i])[0],TAr[1]);
        !ObXY.State&&T.fButtonUp(X,Y);
        ObXY.State==1&&ObXY.MineCount&&T.fOpenFlagMine(X,Y);
        break;
      case 1: //当MouseDown为一个键单击时,MouseUp才判断为一个键弹起
        if(WhichButton(evt)){
        //只有在State=0才起作用,跟是否有雷没关系
            LeftMouse=0;
            if(ObXY.State){break;}
            ObXY.Mine&#63;(
              //触雷,结束该局
              T.fFail(),
              srcEle.className='Boom'
            ):(
              ObXY.State=1, //压栈之前就要设置为已经开启
              T.aClear.push([X,Y]),
              T.fClearMine()
            )
        }
    }
    MouseButton=0;
    if(T.OpenedCount==T.MaxOpenCount&&T.FlagCount==T.MineCount){
      T.fSuccess();
      alert('恭喜游戏成功!再来一局吧?');
      return;
    }
    //当剩余未开启的格子数=剩余的旗子数,自动完成
    T.MaxOpenCount+T.MineCount-T.OpenedCount-T.FlagCount==$('txtFlagCount').value&&(
      T.fSuccess(),
      T.fAutoFlag(),
      alert('恭喜游戏成功!再来一局吧?')
    )
  },
   
  //自动填充未开启的地区的雷
  fAutoFlag:function(){
    var T=this,nX,nY=T.MaxY,MaxX=T.MaxX,Mine=T.Mine,TAr;
    while(nY--){
      nX=MaxX;
      TAr=Mine[nY];
      while(nX--)!TAr[nX].State&&($('Img'+nX+'_'+nY).className='Flag');
    }
    $('txtFlagCount').value=0;
  },
   
  //递归开雷
  fClearMine:function(){
    var T=this;
    if(T.aClear.length==0){return}
    ++T.OpenedCount;
    var aXY=T.aClear.pop(),X=aXY[0],Y=aXY[1],TX,TY,
      aTmpClear=[], //一个临时数组
      srcEle=$('Img'+X+'_'+Y),
      ObXY,ObTXTY,
      countMine=0, //获取周围雷的个数
    //从正左开始的8个方向
      arr=T.fGetAround(X,Y),i=arr.length,TAr;
    while(i--){
      //TX,TY获得本格周围的坐标
      (ObTXTY=T.fGetMine(TX=(TAr=arr[i])[0],TY=TAr[1])).Mine==1&&++countMine;
      !ObTXTY.State&&aTmpClear.push([TX,TY]);
    }
    ObXY=T.fGetMine(X,Y);
    ObXY.MineCount=countMine;
    srcEle.className='M'+countMine;
    if(!countMine){
      Array.prototype.push.apply(T.aClear,aTmpClear);
      i=aTmpClear.length;
      while(i--)T.fGetMine((TAr=aTmpClear[i])[0],TAr[1]).State=1;
    }else{
      getOs()==2&#63;
        srcEle.textContent=countMine
        :srcEle.innerText=countMine
    }
    T.fClearMine();
  },
   
  //获得双键辅助开启
  fOpenFlagMine:function(X,Y){
    var T=this,FlagCount=0,TX,TY,ObXY,ObTXTY,aTmpClear=[],FlagErr=false,
      arr=T.fGetAround(X,Y),i=arr.length,TAr;
    while(i--){
      //TX,TY获得本格周围的坐标
      ObTXTY=T.fGetMine(TX=(TAr=arr[i])[0],TY=TAr[1]);
      switch(ObTXTY.State){
        case 0: //未开启未标记
          !ObTXTY.Mine&&aTmpClear.push([TX,TY]); //没雷也没旗子的时候加入到被辅助开启的数组}
          break;
        case 2: //标记了旗子
          ++FlagCount; //只要标记了旗子,无论对错,都记录标记数+1
          !ObTXTY.Mine&&(FlagErr=true); //没有雷但是标记了旗子,标记错误
      }
    }
    if(FlagCount<T.fGetMine(X,Y).MineCount||aTmpClear.length==0)return;
    //旗子比实际雷少,无论标记对错,不开启
    //没有可以提供开启的空格
    if(FlagErr){ //有错误则进行结束游戏处理
      T.fFail();
      return;
    }
    Array.prototype.push.apply(T.aClear,aTmpClear);
    i=aTmpClear.length;
    while(i--)T.fGetMine((TAr=aTmpClear[i])[0],TAr[1]).State=1;
    T.fClearMine();
  },
   
  //显示所有的雷
  fShowMine:function(){
    var T=this,X=0,Y=T.MaxY,MaxX=T.MaxX,Mine=T.Mine,TAr,TArX;
    while(Y--){
      X=MaxX;
      TAr=Mine[Y];
      while(X--){
        TArX=TAr[X];
        switch(TArX.Mine){
          case 0:
            TArX.State==2&&($('Img'+X+'_'+Y).className='ErrFlag');
            break;
          case 1:
            $('Img'+X+'_'+Y).className='Mine';
        }
      }
    }
  },
 
  //游戏成功结束
  fSuccess:function(){
    this.Success=true;
    $('btnRefreshMap').src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/success.gif';
  },
   
  //游戏失败结束
  fFail:function(){
    this.GameOver=true;
    $('btnRefreshMap').src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/sad.gif';
    this.fShowMine();
  }
},
 
//换地图
ChangeMap=function(Map){
  var O=OMine;
  switch(Map){
    case 1:
      O.MaxX=O.MaxY=9;
      O.MineCount=10;
      break;
    case 2:
      O.MaxX=O.MaxY=16;
      O.MineCount=40;
      break;
    case 3:
      O.MaxX=30;
      O.MaxY=16;
      O.MineCount=99;
  }
  O.fInit();
},
 
getOs=function(){
  if(navigator.userAgent.indexOf("MSIE")>0)return 1;
  if(isFirefox=navigator.userAgent.indexOf("Firefox")>0)return 2;
  if(isSafari=navigator.userAgent.indexOf("Safari")>0)return 3;  
  if(isCamino=navigator.userAgent.indexOf("Camino")>0)return 4;
  if(isMozilla=navigator.userAgent.indexOf("Gecko/")>0)return 5;
  return 0;
};
 
 
FlagImg.src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/flag.gif';
HappyImg.src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/happy.gif';
MineImg.src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/mine.gif';
SadImg.src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/sad.gif';
SuccessImg.src='http://sandbox.runjs.cn/uploads/rs/202/xyovf5xj/success.gif';
</script>
</head>
<body topmargin="0" oncontextmenu="return false" ondragstart="return false" onselectstart="return false" onload="OMine.fInit()" bgcolor="#808080">
<center>
<div id="dTop" align="center" style="border-style: inset; border-width: 10;width:400">
<table cellpadding="0" cellspacing="0" style="border-collapse: collapse;" width="380" height="44">
 <tr>
  <td style="width: 102; height:50px">
  <input type="text" id="txtFlagCount" size="20" style="width: 60; height: 30; color:#FF0000; text-align:center; font-family:Verdana; font-weight:bold; background-color:#000000; font-size:13pt" value=""></td>
  <td style="width: 136; height:50px">
  <input onclick="OMine.fRefreshMap()" type="image" id="btnRefreshMap" src="happy.gif"><input onclick="OMine.fShowMine();" type="button" name="B3" value="显雷"style="display:none"></td>
  <td style="width: 142; height:50px">
  <input type="radio" value="V1" checked name="R1" id="R1" onclick="ChangeMap(1)">初级<input type="radio" value="V1" name="R1" id="R2" onclick="ChangeMap(2)">中级<input type="radio" value="V1" name="R1" id="R3" onclick="ChangeMap(3)">高级</td>
 </tr>
 
</table>
</div>
<div id="dMap" align="center"></div>
</center>
</body>
</html>

Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er gefällt Ihnen allen.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn