javascript模拟Windows系统下的扫雷游戏

javascript模拟Windows系统下的扫雷游戏。

说好的一周一篇随笔的,这才第三周就延迟交作业了,深深的自责中...

先玩一把 demo

很久以前写的 当时都没写注释的 刚加上了 (尼玛,好多自己都不认识了 ... )

不足的敌方就是本来想写个游戏排名的统计的,等有空了再加上(好像每次都这么说 然后就等好久好久...)

还有就是没有实现:点击第一个格子不能是雷的功能

刚才在手机端 打开了下这篇文章 排版完全乱了...

<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>
时间: 2024-08-02 02:45:41

javascript模拟Windows系统下的扫雷游戏的相关文章

windows系统下简单nodejs安装及环境配置

相信对于很多关注javascript发展的同学来说,nodejs已经不是一个陌生的词眼,这里不想谈太多的nodejs的相关信息.只说一下,windows系统下简单nodejs环境配置 相信对于很多关注javascript发展的同学来说,nodejs已经不是一个陌生的词眼.有关nodejs的相关资料网上已经铺天盖地.由于它的高并发特性,造就了其特殊的应用地位. 国内目前关注最高,维护最好的一个关于nodejs的网站应该是http://www.cnodejs.org/  这里不想谈太多的nodejs

Windows系统下三十款优秀开源软件

Windows系统下三十款优秀开源软件 1.Firefox 官方网站:http://www.getfirefox.com/ 可替换Internet Explorer 功能特点:如果你还没有使用Firefox来作为你的网页浏览工具,那么你现在就可以动手了.它能够阻止那些烦人的弹出窗口,并且它还有大量优秀的插件,能够让你的网络冲浪体验更加美好.我可以全天候地赞美Firefox,但有一件事是肯定的:在新的Windows计算机上我要做的第一件事就是运行Internet Explorer,以让我去下载Fi

windows系统下简单nodej.s环境配置 安装

国内目前关注最高,维护最好的一个关于nodejs的网站应该是http://www.cnodejs.org/ windows系统下简单nodejs环境配置. 第一步:下载安装文件 下载地址:官网 https://nodejs.org/en/download/   这里用的是  第二步:安装nodejs 下载完成之后,双击 node-v6.9.1-x64.msi,开始安装nodejs,默认是安装在C:\Program Files\nodejs下面 第三步:安装相关环境 打开C:\Program Fi

windows系统下跨平台开发环境的搭建(cordova)+创建一个android项目

目的:在windows系统下,搭建跨平台的开发环境(cordova)创建一个安卓项目 前提:安装有java Jdk 1.8以上 Android SDK 23以上 1.安装node.js ,选择对应的版本下载安装,没什么好说的 官方网址:http://nodejs.cn/ 2.测试安装是否成功 win+r 键,打开运行窗口,输入cmd,然后确定,打开命令行窗口 输入node  -v 输出版本号,说明node.js安装成功,否则请查找原因,或者重新安装 输入npm -v 输出版本号说明npm可以使用

Windows系统下Android开发环境搭建

“工具善其事,必先利其器”.要想学好Android,搭建好Android开发环境是一个良好的开端. Windows系统下Android开发环境主要有4个大的步骤.分别是: 1.JDK的安装 2.eclipse的安装 3.Android SDK 的安装 4.Android ADT插件的安装 ---------------------------------------------------------------------------------------------------------

Windows系统下Python与NumPy安装方法

Windows系统下Python与NumPy安装方法 Windows下Python的某些第三方包安装步骤实在是太麻烦了(这里主要以NumPy为例,目前只有遇到安装它的时候出现了很多问题),晚上花了好几个小时才把NumPy科学计算包安装好,在这里描述下安装过程,避免大家走没有必要的弯路. 1,安装Python 首先,运行下载的MSI安装包,选择安装组件时,确保勾上了所有的组件. 特别要注意选上pip和Add python.exe to Path,然后多次点击Next即可完成安装. Python解释

linux 和windows系统下同时可用的UML建模工具(umbrello),超强

原文地址:linux 和windows系统下同时可用的UML建模工具(umbrello),超强 作者:zhangjiakouzf OPEN SOURCE 的 UML建模工具 -- umbrello 如果你的开发小组既有windows系统下的开发人员(比如客户端软件),又有linux或其他*nix系统下的开发人员(比如服务器端程序).就像我现在的处境一样,那么你需要"她",trust me!! umbrello 最初的 homepage 在http://uml.sourceforge.n

sys.stdout.flush()在Linux和Windows系统下的作用

sys.stdout.flush() -> 这句代码的意思是刷新输出 Linux系统下执行脚本 不加sys.stdout.flush() 上图所示:上面这个脚本他的原意是一秒在一排输出一个数字,但是他没有加sys.stdout.flush(),所以他在五秒之后,也就是等到程序执行完毕,他才一次性输出0,1,2,4,5 加了sys.stdout.flush()执行脚本 上图所示:程序加上了sys.stdout.flush(),他就一秒输出了一个数字,这是在Linux系统下的效果 Windows系统

windows系统下c语言暂停程序

原文:windows系统下c语言暂停程序 windows系统下,很多C语言初学者的调试时,往往没看到结果程序就退出了,据我所知的方法主要有以下几种 方法一: #include int main() { system("pause");//利用了DOS命令,按任意键继续 return 0; } 方法二: #include int main() { getchar();//须按回车键结束,不是任意键 return 0; }