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 asp.net 获取当前超链接中的文本
Apr 14 Javascript
精通Javascript系列之数值计算
Jun 07 Javascript
Extjs优化(二)Form表单提交通用实现
Apr 15 Javascript
node.js操作mongoDB数据库示例分享
Nov 26 Javascript
DOM事件阶段以及事件捕获与事件冒泡先后执行顺序(图文详解)
Aug 18 Javascript
探寻JavaScript中this指针指向
Apr 23 Javascript
JavaScript兼容性总结之获取非行间样式案例
Aug 07 Javascript
JavaScript登录验证基础教程
Nov 01 Javascript
详解webpack3编译兼容IE8的正确姿势
Dec 21 Javascript
基于 flexible 的 Vue 组件:Toast -- 显示框效果
Dec 26 Javascript
vue.js使用代理和使用Nginx来解决跨域的问题
Feb 03 Javascript
Element-ui之ElScrollBar组件滚动条的使用方法
Sep 14 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
php实现ping
2006/10/09 PHP
php错误、异常处理机制(补充)
2012/05/07 PHP
PHP格式化显示时间date()函数代码
2018/10/03 PHP
php菜单/评论数据递归分级算法的实现方法
2019/08/01 PHP
修改jquery.lazyload.js实现页面延迟载入
2010/12/22 Javascript
functional继承模式 摘自javascript:the good parts
2011/06/20 Javascript
js获取class的所有元素
2013/03/28 Javascript
extJS中常用的4种Ajax异步提交方式
2014/03/07 Javascript
jQuery操作元素css样式的三种方法
2014/06/04 Javascript
CSS+JS实现点击文字弹出定时自动关闭DIV层菜单的方法
2015/05/12 Javascript
JS制作手机端自适应缩放显示
2015/06/11 Javascript
学习javascript面向对象 理解javascript原型和原型链
2016/01/04 Javascript
利用Angularjs和原生JS分别实现动态效果的输入框
2016/09/01 Javascript
JS动态的把左边列表添加到右边的实现代码(可上下移动)
2016/11/17 Javascript
Node.js中文件操作模块File System的详细介绍
2017/01/05 Javascript
详解Angular2中Input和Output用法及示例
2017/05/21 Javascript
详解nodejs实现本地上传图片并预览功能(express4.0+)
2017/06/28 NodeJs
JavaScript之filter_动力节点Java学院整理
2017/06/28 Javascript
ES6之模版字符串的具体使用
2018/05/17 Javascript
Vue实现剪贴板复制功能
2019/12/31 Javascript
微信小程序如何加载数据库真实数据的实现
2020/03/04 Javascript
Python挑选文件夹里宽大于300图片的方法
2015/03/05 Python
Linux下远程连接Jupyter+pyspark部署教程
2019/06/21 Python
python opencv实现图像配准与比较
2021/02/09 Python
海淘零差价,宝贝全球购: 宝贝格子
2016/08/24 全球购物
美国标志性加大尺码时装品牌:Ashley Stewart
2016/12/15 全球购物
大学生毕业求职自荐书范文
2014/02/04 职场文书
2014年3.15团委活动总结
2014/03/16 职场文书
责任心演讲稿
2014/05/14 职场文书
大学生党性分析材料
2014/12/19 职场文书
基层党支部承诺书
2015/04/30 职场文书
公司岗位说明书
2015/10/08 职场文书
观看《筑梦中国》纪录片心得体会
2016/01/18 职场文书
2016大学生国家助学贷款承诺书
2016/03/25 职场文书
导游词之日本富士山
2020/01/06 职场文书
win11怎么消除图标小盾牌?win11消除图标小盾牌解决方法
2022/08/05 数码科技