本文給大家分享的是個人剛開始學習javascript的時候寫的仿windows經典的掃雷游戲的代碼,當時只是寫了下來,沒加注釋,這里補上,有需要的小伙伴可以參考下。
很久以前寫的 當時都沒寫注釋的 剛加上了 (尼瑪,好多自己都不認識了 ... )
不足的地方就是本來想寫個游戲排名的統計的,等有空了再加上(好像每次都這么說 然后就等好久好久...)
還有就是沒有實現:點擊第一個格子不能是雷的功能
- <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(mine.gif) no-repeat;}
- #mine .mine_02{background:url(mine.gif) -30px 0 no-repeat;}
- #mine .mine_03{background:url(mine.gif) -60px 0 no-repeat;}
- #mine .mine_04{background:url(mine.gif) -90px 0 no-repeat;}
- #mine .mine_05{background:url(mine.gif) -120px 0 no-repeat;}
- #mine .mine_06{background:url(mine.gif) -150px 0 no-repeat;}
- #mine .mine_07{background:url(mine.gif) -180px 0 no-repeat;}
- #count{font-size:12px;}
- #time{color:#900;font-weight:bold;}
- </style>
- <select id="wh">
- <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'>重新開始</button>
- <div id="count">
- 計時: <span id="time">0</span>
- </div>
- <ul id="mine">
- </ul>
- ie6+ ff oprea 谷歌
- opera 早期版本 默認不支持document.oncontextmenu事件 沒有找到好的替代方法
- <script>
- var $ = function(id){return document.getElementById(id)};
- window.onload=function ready(){
- var V=$('wh').value.split('*')
- setMineField(Number(V[0]),Number(V[1]));
- $('wh').onchange=$('ready').onclick=function(){
- V=$('wh').value.split('*')
- setMineField(Number(V[0]),Number(V[1]))
- }
- }
- //---------------------------------------------------雷區
- var mineField={
- _mineW:30, //每一個雷的寬度 必須和樣式同步
- _mineH:30,
- _mineFieldBlock:$('mine'),
- _mineFieldEle:$('mine').getElementsByTagName('li'),
- _time:$('time'),
- status:0, //雷區狀態 0還沒開始 1開始了 已經在計時了 2游戲結束了
- mineNum:0, //雷數
- clearPlace:0, //統計掃除的格子;
- x:0, //列
- y:0, //行
- density:0.2, //雷的密度 雷區密度不宜超過0.5 在有些尺寸的雷區下 過高的設置 無法生成mineMap數組
- mineMap:[], //雷區的二維圖,0 : 不是雷 -1 : 雷
- time:-1, //計時 s
- debug:false //調試模式
- }//mineField object end
- function timedCount(){
- if(mineField.status!=1){return false}
- mineField.time++;
- mineField._time.innerHTML=mineField.time;
- setTimeout("timedCount()",1000);
- }
- //--------------------------------------對雷的狀態設置
- function setThisMine(str,index){
- var allMine=mineField._mineFieldEle;
- //設置雷是否插旗
- if(str=='setOn'){
- var thisMine=allMine[index];
- thisMine.on=thisMine.on<2?thisMine.on+1:0;
- if(thisMine.on==1){thisMine.className='mine_03';}//插旗
- else if(thisMine.on==2){thisMine.className='mine_04'}//取消插旗
- else if(thisMine.on==0){thisMine.className='mine_01'}//取消插旗
- return false;
- }
- //顯示方格
- if(str=='show'){
- if(Object.prototype.toString.call(index) === '[object Array]'){//顯示一大片
- mineField.clearPlace=mineField.clearPlace+index.length;
- for(var i=0;i<index.length;i++){
- var thisMine=allMine[index[i]];
- thisMine.innerHTML=mineField.mineMap[thisMine.index];
- thisMine.className='mine_02';
- thisMine.on=3;
- }
- }
- else{//顯示單個非雷區域
- mineField.clearPlace++;
- allMine[index].on=3;
- allMine[index].innerHTML=mineField.mineMap[index];
- allMine[index].className='mine_02';
- }
- if(mineField.clearPlace==mineField.x*mineField.y-mineField.mineNum){//恭喜你
- alert('恭喜你');
- for(var i=0;i<allMine.length;i++){
- if(mineField.mineMap[allMine[i].index]==-1){
- allMine[i].className='mine_07';
- }
- }
- mineField.status=2;
- return false;
- }
- }
- //顯示全部雷
- if(str=='peng'){
- for(var i=0;i<allMine.length;i++){
- if(mineField.mineMap[allMine[i].index]==-1){
- allMine[i].className=i==index?'mine_06':'mine_05';
- }
- }
- mineField.status=2;
- }
- }
- //-----------------------------------------------設置行數 和 列數
- function setMineField(a,b){
- var thisMineFiele=mineField._mineFieldBlock;
- DivBox=document.createElement("div"),
- num=a*b,k=0;
- thisMineFiele.innerHTML='';
- //雷區參數調整
- mineField.x=a;//有幾列
- mineField.y=b;//有幾行
- mineField.mineNum=Math.floor(a*b*mineField.density);
- mineField.status=0;
- mineField.time=-1;
- mineField.clearPlace=0;
- mineField.mineMap.length=0;
- mineField._time.innerHTML=0;
- //生成雷區地圖
- setMineMap();
- //生成雷區(創建li)
- while(k<num){
- var newLi=document.createElement("li");
- if(mineField.debug) newLi.innerHTML=mineField.mineMap[k];//作弊
- newLi.className='mine_01';
- DivBox.appendChild(newLi);
- k++;
- }
- thisMineFiele.style.height=mineField._mineW*b+'px';
- thisMineFiele.style.width=mineField._mineH*a+'px';
- thisMineFiele.innerHTML=DivBox.innerHTML;
- DivBox=null;
- setEvent();//事件
- }
- //-----------------------------------生成雷區地圖
- function setMineMap(){
- var num=mineField.x*mineField.y,
- mineNum=mineField.mineNum,
- Interval=Math.floor(num/mineNum);
- for(var i=0;i<num;i++){
- if(i%Interval==0&&i<mineNum*Interval){mineField.mineMap[i]=-1;}else{mineField.mineMap[i]=0;}//雷等距離分布與數組中
- }
- mineField.mineMap.sort(function(){ return 0.5 - Math.random()})//打亂數組
- //判斷方格周圍是否都是雷 如果是的話 要重新生成雷區 從而避免成片雷區的存在
- var br=0,//所在行
- x=mineField.x,
- L_T,T,R_T,L,R,L_B,B,R_B;
- for(var i=0;i<num;i++){
- br=Math.ceil((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&&Math.ceil((L_T+1)/x)==br-1&&mineField.mineMap[L_T]==0){continue}
- if(T >=0&&Math.ceil((T +1)/x)==br-1&&mineField.mineMap[T ]==0){continue}
- if(R_T>=0&&Math.ceil((R_T+1)/x)==br-1&&mineField.mineMap[R_T]==0){continue}
- if(L>=0 &&Math.ceil((L+1)/x)==br&&mineField.mineMap[L]==0){continue}
- if(R<num&&Math.ceil((R+1)/x)==br&&mineField.mineMap[R]==0){continue}
- if(L_B<num&&Math.ceil((L_B+1)/x)==br+1&&mineField.mineMap[L_B]==0){continue}
- if(B <num&&Math.ceil((B +1)/x)==br+1&&mineField.mineMap[B ]==0){continue}
- if(R_B<num&&Math.ceil((R_B+1)/x)==br+1&&mineField.mineMap[R_B]==0){continue}
- setMineMap();
- return false
- }
- //統計非雷方格周圍的雷數
- for(i=0;i<num;i++){
- if(mineField.mineMap[i]==-1){continue}
- var thisMineNum=0
- br=Math.ceil((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&&Math.ceil((L_T+1)/x)==br-1&&mineField.mineMap[L_T]==-1){thisMineNum++;}
- if(T >=0&&Math.ceil((T +1)/x)==br-1&&mineField.mineMap[T ]==-1){thisMineNum++;}
- if(R_T>=0&&Math.ceil((R_T+1)/x)==br-1&&mineField.mineMap[R_T]==-1){thisMineNum++;}
- if(L>=0 &&Math.ceil((L+1)/x)==br&&mineField.mineMap[L]==-1){thisMineNum++;}
- if(R<num&&Math.ceil((R+1)/x)==br&&mineField.mineMap[R]==-1){thisMineNum++;}
- if(L_B<num&&Math.ceil((L_B+1)/x)==br+1&&mineField.mineMap[L_B]==-1){thisMineNum++;}
- if(B <num&&Math.ceil((B +1)/x)==br+1&&mineField.mineMap[B ]==-1){thisMineNum++;}
- if(R_B<num&&Math.ceil((R_B+1)/x)==br+1&&mineField.mineMap[R_B]==-1){thisMineNum++;}
- mineField.mineMap[i]=thisMineNum;
- }
- }
- //----------------------------------雷區事件
- function setEvent(){
- var thisMineFiele=mineField._mineFieldBlock,
- allMine=mineField._mineFieldEle,
- iMax=mineField.x*mineField.y;
- for(var i=0;i<iMax;i++){
- allMine[i].index=i;
- allMine[i].on=0;//0為默認 1為插旗 2為問號 3為顯示
- }
- thisMineFiele.onmouseup=function(e){
- if(mineField.status==2){return false;}
- if(mineField.status==0){mineField.status=1;timedCount();}
- var e=e||window.event,
- thisObj=e.target||e.srcElement;
- if(thisObj.nodeName=='UL'||thisObj.on==3){return false;}
- var Btn=getButton(e);
- if(Btn== 0){//左鍵
- if(thisObj.on==1){return false;}//插旗子了 就不能點了
- if(mineField.mineMap[thisObj.index]==-1){//點雷了
- setThisMine('peng',thisObj.index);
- }else if(mineField.mineMap[thisObj.index]==0){//點到空地了 打開一大片
- //alert('你運氣真好')
- var allShowMine=minesShow(thisObj.index);
- setThisMine('show',allShowMine)
- }else{//顯示一個格子
- setThisMine('show',thisObj.index)
- }
- }
- if(Btn== 2){//右鍵
- setThisMine('setOn',thisObj.index);
- }
- }
- }
- //--------------------------------按到空格時 顯示一大片
- function minesShow(I){
- var allMine=mineField._mineFieldEle,
- allShowMine=[I];//保存要顯示的雷的下標
- allMine[I].on=3;
- see(I);//查詢下標為I的周圍的方格
- function see(allI){
- var _allI=[];
- if(Object.prototype.toString.call(allI) === '[object Array]'){
- for(var i=0;i<allI.length;i++){f(allI[i])}
- }
- else{f(allI)}
- function f(thisI){
- var text,
- x=mineField.x,
- br,
- num=x*mineField.y,
- L_T,T,R_T,L,R,L_B,B,R_B;
- text='_'+allShowMine.join('_')+'_';//用來判斷下標是否已經寫入數組
- br=Math.ceil((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;
- //左上角的方格 如果是在雷區 又是在上一行 又是沒翻開的格子 又是空格 那么就寫如_allI數組 來進行下一次檢索
- if(L_T>=0&&Math.ceil((L_T+1)/x)==br-1&&allMine[L_T].on==0&&mineField.mineMap[L_T] == 0){_allI.push(L_T);}
- if(T >=0&&Math.ceil((T +1)/x)==br-1&&allMine[T ].on==0&&mineField.mineMap[T ] == 0){_allI.push(T);}
- if(R_T>=0&&Math.ceil((R_T+1)/x)==br-1&&allMine[R_T].on==0&&mineField.mineMap[R_T] == 0){_allI.push(R_T);}
- if(L>=0&&Math.ceil((L+1)/x)==br&&allMine[L].on==0&&mineField.mineMap[L] == 0){_allI.push(L);}
- if(R<num&&Math.ceil((R+1)/x)==br&&allMine[R].on==0&&mineField.mineMap[R] == 0){_allI.push(R);}
- if(L_B<num&&Math.ceil((L_B+1)/x)==br+1&&allMine[L_B].on==0&&mineField.mineMap[L_B] == 0){_allI.push(L_B);}
- if(B <num&&Math.ceil((B +1)/x)==br+1&&allMine[B ].on==0&&mineField.mineMap[B ] == 0){_allI.push(B);}
- if(R_B<num&&Math.ceil((R_B+1)/x)==br+1&&allMine[R_B].on==0&&mineField.mineMap[R_B] == 0){_allI.push(R_B);}
- //------------------------------------------------
- //左上角的的格子 如果在雷區 又是在上一行 又是沒翻開的格子 又是沒寫入allShowMine數組的 那就寫入吧 并提前標記為翻開的格子
- if(L_T>=0&&Math.ceil((L_T+1)/x)==br-1&&allMine[L_T].on==0&&text.indexOf('_'+L_T+'_') == -1){allShowMine.push(L_T);allMine[L_T].on=3}
- if(T >=0&&Math.ceil((T +1)/x)==br-1&&allMine[T ].on==0&&text.indexOf('_'+T+'_') == -1){allShowMine.push(T);allMine[T].on=3}
- if(R_T>=0&&Math.ceil((R_T+1)/x)==br-1&&allMine[R_T].on==0&&text.indexOf('_'+R_T+'_') == -1){allShowMine.push(R_T);allMine[R_T].on=3}
- if(L>=0&&Math.ceil((L+1)/x)==br&&allMine[L].on==0&&text.indexOf('_'+L+'_') == -1){allShowMine.push(L);allMine[L].on=3}
- if(R<num&&Math.ceil((R+1)/x)==br&&allMine[R].on==0&&text.indexOf('_'+R+'_') == -1){allShowMine.push(R);allMine[R].on=3}
- if(L_B<num&&Math.ceil((L_B+1)/x)==br+1&&allMine[L_B].on==0&&text.indexOf('_'+L_B+'_') == -1){allShowMine.push(L_B);allMine[L_B].on=3}
- if(B <num&&Math.ceil((B +1)/x)==br+1&&allMine[B ].on==0&&text.indexOf('_'+B+'_') == -1){allShowMine.push(B );allMine[B ].on=3}
- if(R_B<num&&Math.ceil((R_B+1)/x)==br+1&&allMine[R_B].on==0&&text.indexOf('_'+R_B+'_') == -1){allShowMine.push(R_B);allMine[R_B].on=3}
- if(_allI.length!=0){see(_allI)}
- }
- }
- return allShowMine
- }
- //--------------------------------------
- document.oncontextmenu=function(){return false;}//禁止右鍵菜單
- function getButton(e){
- var Btn;
- if(document.implementation.hasFeature('MouseEvents','2.0')){Btn=e.button;}
- else{ switch(e.button){
- 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>
以上所述就是本文的全部內容了,希望大家能夠喜歡。
新聞熱點
疑難解答
圖片精選