JavaScript版经典游戏之扫雷游戏完整示例【附demo源码下载】


Posted in Javascript onDecember 12, 2016

本文实例讲述了JavaScript扫雷游戏。分享给大家供大家参考,具体如下:

翻出年初写的游戏贴上来,扫雷相信大家都玩过,先上图:

JavaScript版经典游戏之扫雷游戏完整示例【附demo源码下载】

源码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Javascript版扫雷</title>
<style>
  input{ margin:0; padding:0;}
  input{ outline:none;}
  #game_box{ width:400px; height:430px; margin:100px auto; border:#333 1px solid; background:#ccc -webkit-repeating-linear-gradient(top,#ccc,#000);background:#ccc -moz-repeating-linear-gradient(top,#ccc,#000);background:#ccc -o-repeating-linear-gradient(top,#ccc,#000);background:#ccc -ms-repeating-linear-gradient(top,#ccc,#000); box-shadow:0 0 50px 10px #333; box-shadow:0 0 50px 10px #333;
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#CBCBCB', endColorstr='#000000');
   }
  #map{width:400px; height:348px;*height:380px;}
  #time{ height:18px; line-height:22px; text-align:center;margin:6px 0; margin-top:10px; _margin-top:40px; color:#fff; position:relative;}
  #time input{ width:40px; height:18px; line-height:18px; text-align:center;}
  #table_map{ width:336px; height:336px; border:none; border-left:#000 1px solid;border-top:#000 1px solid; margin:32px 32px 0px 32px; background:#D8ECF6; text-align:center; border-collapse: collapse}
  #table_map td{ width:20px; height:20px; border:none;border-right:#000 1px solid;border-bottom:#000 1px solid; color:#333333; transition:all 0.7s; cursor:pointer;}
  #table_map td.mask{ border:none;border-right:#000 1px solid;border-bottom:#000 1px solid; background:#333; }
  #table_map td.over{ border:none;border-right:#000 1px solid;border-bottom:#000 1px solid; }
  .over_bg{ background:#E1E1E1;}
  @-webkit-keyframes round{
    from{ -webkit-transform:rotateX(0);}
    to{ -webkit-transform:rotateX(360deg);}
  }
  @-webkit-keyframes show{
    from{ -webkit-transform:rotateX(180deg) rotateY(0) scale(0);}
    to{ -webkit-transform:rotateX(360deg) rotateY(360deg) scale(1);}
  }
  @-moz-keyframes round{
    from{ -moz-transform:rotateX(0);}
    to{ -moz-transform:rotateX(360deg);}
  }
  @-moz-keyframes show{
    from{ -moz-transform:rotateX(180deg) rotateY(0) scale(0);}
    to{ -moz-transform:rotateX(360deg) rotateY(360deg) scale(1);}
  }
  @-ms-keyframes round{
    from{ -ms-transform:rotateX(0);}
    to{ -ms-transform:rotateX(360deg);}
  }
  @-ms-keyframes show{
    from{ -ms-transform:rotateX(180deg) rotateY(0) scale(0);}
    to{ -ms-transform:rotateX(360deg) rotateY(360deg) scale(1);}
  }
  #game_box{-webkit-animation:show 3s;-moz-animation:show 3s;-ms-animation:show 3s;}
</style>
</head>
<body>
<div id="game_box">
  <div id="map"></div>
  <div id="time">时间:<input type="text" value="0" disabled="disabled" />  炸弹:<input type="text" value="50" disabled="disabled" /></div>
</div>
<script>
// 2014年3月 by 王美建 QQ1207526854
  window.onload=function()
  {
    Game.init('game_box','map');
  };
  var Game={
    data : {  //关卡数据
      mine : 40, col : 16, row : 16
    },
    init : function(box_id,mapbox_id){ //初始化
      this.oBox = document.getElementById(box_id);
      this.mapBox = document.getElementById(mapbox_id)
      this.mapBox.innerHTML = this.createMap();
      this.oMap = this.mapBox.getElementsByTagName('table')[0];
      this.aTd = this.oMap.getElementsByTagName('td');
      this.time = document.getElementById('time').getElementsByTagName('input')[0];
      this.mineNum = document.getElementById('time').getElementsByTagName('input')[1];
      this.mineNum.value = this.data.mine;
      this.surplus = [];
      this.iCount = this.data.col*this.data.row-this.data.mine;
      this.createMine();
      this.addVal();
      this.play();
    },
    createMap : function() //生成画布
    {
      var html = '';
      var This = this.data;
      var i=0,j=0;
      function createTd()
      {
        var tds = '';
        for(j = 0; j < This.row; j++)
        {
          tds += '<td class = "mask" index='+ (This.col*i+j) +'></td>';
        };
        return tds;
      }
      for(i = 0; i < This.col; i++)
      {
        html += '<tr>' + createTd() + '</tr>';
      };
      return ('<table id="table_map" cellpadding="0" cellspacing="0" ><tbody>'+html+'</table></tbody>');
    },
    createMine : function(){ //生成炸弹
      var This = this.data;
      this.indexArr = [];
      this.mineArr = [];
      for(var i = 0,j = This.col*This.row; i < j; i++ )
      {
        this.indexArr.push(i) ;  //所有单元格的索引
      };
      for( var i = 0; i < This.mine; i++ ) //随机取出This.mine个做为炸弹的索引,不重复
      {
        var index = Math.round(Math.random()*(this.indexArr.length-1)); //索引
        this.mineArr.push(this.indexArr.splice(index,1)[0]);
      };
      this.mineArr.sort( function(a,b){return a-b;} );
    },
    addVal : function() //给有炸弹的td添加自定义属性hasMine值为true
    {
      for(var i = 0, j = this.mineArr.length; i < j; i++)
      {
        this.aTd[ this.mineArr[i] ].hasMine = true;
      };
    },
    play : function()
    {//鼠标左右键同时按下  ev.button=3
      this.timeOnoff = false;
      var This = this;
      this.markNum = [];
      this.oMap.oncontextmenu=function(ev)  //插旗标记
      {
        var ev = ev || window.event;
        var target = ev.srcElement || ev.target;
        if( target.tagName.toLowerCase() == 'td' && target.className == 'mask' )
        {
          !target.mark ? (target.innerHTML = '▲',target.style.color = '#FFEFAD',target.mark = true,This.mineNum.value--,This.markNum.push( target.getAttribute( 'index' ) )) : (target.innerHTML = '',target.style.color = '#333333',target.mark = false,This.mineNum.value++,This.markNum.splice( This.findIndex( This.markNum,target.getAttribute( 'index' ) ),1 ));
        };
        return false;
      };
      this.oMap.onclick = function(ev)
      {
        var ev = ev || window.event;
        var target = ev.srcElement || ev.target;
        if(!This.timeOnoff) //开始计时
        {
          This.timeOnoff = true;
          This.timer=setInterval(function(){
            This.time.style.webkitAnimation = 'round 1s infinite';   //计时器翻转
            This.time.value++;
          },1000)
        };
        function openTd(aTd,meg,len)
        {
          var num = 0;
          var show = null;
          var t = Math.ceil( 15*This.data.col*This.data.row/len );  //未打开格子越多,翻开时间间隔越短
          show = setInterval(function(){
            aTd[ This.surplus[num] ].className = 'over';
            aTd[ This.surplus[num] ].style.webkitAnimation = 'round 1s 1';
            if( aTd[ This.surplus[num] ].hasMine && aTd[ This.surplus[num] ].className == 'over' )
            {
              aTd[ This.surplus[num] ].style.color = '#333333';
              aTd[ This.surplus[num] ].innerHTML = '★';
            }else{
              aTd[ This.surplus[num] ].innerHTML = '';
            };
            num++;
            if(num == len)
            {
              clearInterval(show);
              alert(meg);
            }
          },t)
        };
        function countSur() //统计没打开的格子的索引
        {
          var iCheck = 0;
          This.surplus = [];
          for( var i = 0,j = This.data.col*This.data.row; i < j; i++ )
          {
            if( This.aTd[i].className == 'mask' )
            {
              iCheck++;
              This.surplus.push( i );
            };
          };
          return iCheck;
        };
        if( target.tagName.toLowerCase() == 'td' && target.className == 'mask' && !target.hasMine )//没踩到雷
        {
          This.count( parseInt(target.getAttribute('index')) ); //递归
          target.style.webkitAnimation = 'round 1s 1';
          if( This.iCount <= 10 ) //通关检测
          {
            //console.log( 'iCheck='+iCheck+'iCount='+This.iCount )
            if( countSur() == This.data.mine ) //剩下格子数等于炸弹数而又没踩到炸弹,可不就是过关了
            {
              clearInterval( This.timer );
              This.time.style.webkitAnimation = '';   //停止计时器翻转
              openTd( This.aTd,'不错小伙子,过关了!用时:'+This.time.value+'s',This.surplus.length );
            };
          };
        }else if( target.tagName.toLowerCase() == 'td' && target.className == 'mask' && target.hasMine ){ //踩到雷
          clearInterval(This.timer);   //停止计时器
          This.time.style.webkitAnimation = '';   //停止计时器翻转
          var mineArr = This.mineArr;  //优化:全局变局部
          var aTd = This.aTd;
          for( var i = 0,j = mineArr.length; i < j; i++ )
          {
            aTd[ mineArr[i] ].style.color = '#333333';
            aTd[ mineArr[i] ].className = 'over';
            aTd[ mineArr[i] ].innerHTML = '★';   //显示炸弹标志
          };
          target.style.color = 'red';
          countSur();
          openTd( aTd,'小朋友,你输了~',This.surplus.length );
        };
      };
    },
    findIndex : function(arr,ele) //找到数组某个元素在数组中的位置
    {
      for(var i=0,j=arr.length;i<j;i++)
      {
        if(ele === arr[i])
        {
          return i;
        };
      };
      return -1;
    },
    count : function(iNow) //统计事件源周围炸弹
    {
      var arr = []; //事件源周围的格子索引
      var iNum = 0; //事件源周围炸弹个数
      var len = this.data.col;
      if( iNow % len == 0 )  //点击最左边的格子时
      {
        arr = [iNow+1,iNow-len,iNow-len+1,iNow+len,iNow+len+1];
      }else if( iNow == ( Math.floor( iNow/len ) + 1 ) *len -1 ){ //点击靠右边的格子时
        arr = [iNow-1,iNow-len,iNow-len-1,iNow+len,iNow+len-1];
      }else{ //点击不靠边的格子时
        arr = [iNow-1,iNow+1,iNow-len,iNow-len+1,iNow-len-1,iNow+len,iNow+len-1,iNow+len+1];
      };
      for( var i = 0; i < arr.length; i++ ) //统计周围炸弹
      {
        if( this.aTd[ arr[ i ] ] && this.aTd[ arr[ i ] ].hasMine )
        {
          iNum++;
        }
      };
      if( iNum == 0 )  //当前点击格子周围没有炸弹则递归
      {
        this.aTd[iNow].className = '';
        this.aTd[ iNow ].innerHTML == '▲' ? this.aTd[ iNow ].innerHTML = '' : '';
        for( var i = 0,j = arr.length; i < j; i++ )
        {
          if( this.aTd[ arr[ i ] ] && this.aTd[ arr[i] ].className == 'mask')
          {
            this.aTd[ arr[i] ].className = '';
            this.aTd[ arr[i] ].innerHTML == '▲' ? this.aTd[ arr[i] ].innerHTML = '' : '';
            this.iCount--;
            this.count( arr[i] );
          };
        };
      }else{ //当前点击格子周围有炸弹则显示炸弹个数
        this.aTd[iNow].innerHTML = iNum;
        this.aTd[iNow].style.color = '#333333';
        this.aTd[iNow].style.webkitAnimation = 'round 1s 1';
        this.aTd[iNow].className == 'mask' ? (this.aTd[iNow].className = '',this.iCount--) : '';
      };
    }
  };
</script>
</body>
</html>

完整实例代码点击此处本站下载

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JavaScript入门教程(8) Location地址对象
Jan 31 Javascript
jquery select(列表)的操作(取值/赋值)
Aug 06 Javascript
用Javascript 获取页面元素的位置的代码
Sep 25 Javascript
原生JS绑定滑轮滚动事件兼容常见浏览器
Jun 30 Javascript
Angularjs 基础入门
Dec 26 Javascript
JQuery的ON()方法支持的所有事件罗列
Feb 28 Javascript
一道常被人轻视的web前端常见面试题(JS)
Feb 15 Javascript
js中的eval()函数把含有转义字符的字符串转换成Object对象的方法
Dec 02 Javascript
微信小程序 less文件编译成wxss文件实现办法
Dec 05 Javascript
vue判断input输入内容全是空格的方法
Mar 02 Javascript
微信小程序-API接口安全详解
Jul 16 Javascript
ES10的13个新特性示例(小结)
Sep 23 Javascript
JavaScript利用正则表达式替换字符串中的内容
Dec 12 #Javascript
基于BootstrapValidator的Form表单验证(24)
Dec 12 #Javascript
Sequelize中用group by进行分组聚合查询
Dec 12 #Javascript
js原生之焦点图转换加定时器实例
Dec 12 #Javascript
IntersectionObserver API 详解篇
Dec 11 #Javascript
想学习javascript JS和jQuery哪个重要 先学哪个
Dec 11 #Javascript
基于javascript实现的购物商城商品倒计时实例
Dec 11 #Javascript
You might like
Ext第一周 史上最强学习笔记---GridPanel(基础篇)
2008/12/29 Javascript
JavaScript delete操作符应用实例
2009/01/13 Javascript
Mootools 1.2教程 滑动效果(Slide)
2009/09/15 Javascript
Javascript的匿名函数小结
2009/12/31 Javascript
模拟jQuery中的ready方法及实现按需加载css,js实例代码
2013/09/27 Javascript
jquery-syntax动态语法着色示例代码
2014/05/14 Javascript
JavaScript对象反射用法实例
2015/04/17 Javascript
js给selected添加options的方法
2015/05/06 Javascript
JavaScript对Cookie进行读写操作实例
2015/07/25 Javascript
深入浅析JavaScript函数前面的加号和叹号
2016/07/09 Javascript
JavaScript暂停和继续定时器的实现方法
2016/07/18 Javascript
jQuery实现底部浮动窗口效果
2016/09/07 Javascript
JavaScript中三个等号和两个等号你了解多少
2017/07/04 Javascript
Scala解析Json字符串的实例详解
2017/10/11 Javascript
在微信小程序中保存网络图片
2019/02/12 Javascript
探索JavaScript中私有成员的相关知识
2019/06/13 Javascript
解决vue.js提交数组时出现数组下标的问题
2019/11/05 Javascript
[02:58]献给西雅图的情书_高清
2014/05/29 DOTA
bat和python批量重命名文件的实现代码
2016/05/19 Python
Python+Selenium自动化实现分页(pagination)处理
2017/03/31 Python
浅谈python 线程池threadpool之实现
2017/11/17 Python
Python实现的圆形绘制(画圆)示例
2018/01/31 Python
Python设计模式之原型模式实例详解
2019/01/18 Python
在Django的View中使用asyncio的方法
2019/07/12 Python
基于python实现的百度新歌榜、热歌榜下载器(附代码)
2019/08/05 Python
python matplotlib折线图样式实现过程
2019/11/04 Python
巴西最大的家电和百货零售商:Casas Bahia
2016/11/22 全球购物
创建索引时需要注意的事项
2013/05/13 面试题
计算机大学生的自我评价
2013/10/15 职场文书
财务总监岗位职责
2014/03/07 职场文书
责任书格式范文
2014/07/28 职场文书
社区护士演讲稿
2014/08/27 职场文书
刑事辩护授权委托书格式
2014/10/13 职场文书
教师个人考察材料
2014/12/16 职场文书
初中生物教学随笔
2015/08/15 职场文书
大学生活委员竞选稿
2015/11/21 职场文书