基于JavaScript实现简单扫雷游戏


Posted in Javascript onJanuary 02, 2021

对于10年前的人来说,扫雷肯定是家喻户晓,由于当时的科技并不是很发达,大家对于电脑游戏的了解,可能都是从扫雷开始的,今天就交大家一种用js原生代码写一个简单的扫雷游戏,话不多说,直接上干货:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
 <style>
  *{
   margin: 0;
   padding: 0;
  }
  li{
   list-style: none;
  }
  .box{
   border: 1px solid #666;
   position: fixed;
   width: 300px;
   height: 350px;
   top: 0;
   right: 0;
   bottom: 0;
   left: 0;
   margin: auto;
  }
  .btn-group{
   display: flex;
   height: 50px;
   line-height: 50px;
   text-align: center;
   justify-content: space-evenly;
   font-size: 12px;
  }
  .row{
   height: 30px;
   line-height: 30px;
   text-align: center;
   display: flex;
  }
  .col{
   flex-shrink: 0;
   /* flex-shrink 是否允许缩小 */
   flex-grow: 0;
   /* flex-grow 是否允许放大 */
   width: 30px;
   height: 30px;
   border: 1px solid #666;
   background-color: #ccc;
   box-sizing: border-box;
  }
 </style>
</head>
<body>
 <div class="box">
  <div class="qipan">
  </div>
  <div class="btn-group">
   <div class="btn-item">
    <span class="item-name">时间</span>
    <span class="item-value passTime">000</span>
   </div>
   <div class="btn-item">
    <span class="item-name">剩余雷数</span>
    <span class="item-value leftLei">10</span>
   </div>
   <div class="btn-item">
    <select class="level">
     <option value="1">初级</option>
     <option value="2">中级</option>
     <option value="3">高级</option>
    </select>
   </div>
   <div class="btn-item">
    <span class="start">开始</span>
    <span class="restart">重开</span>
   </div>
  </div>
 </div>
 <script>
  function $(s,t){
   if(t == 'l'){
    return document.querySelectorAll(s)
   }else{
    return document.querySelector(s)
   }
  }
  var qipan = $('.qipan'),
    box = $('.box'),
    level = $('.level'),
    leftLei = $('.leftLei'),
    start = $('.start'),
    restart = $('.restart'),
    passTime = $('.passTime')
    ;
  var row = 10,// 行数
    col = 10,// 列数
    leiNum = 10,// 雷数
    restNum = 10,//剩余的雷数
    flag = false,// 格子是否可以被点击
    time,//计时器的名字
    count = 0,// 计时的秒数
    leiList = [],// 用来存放地雷坐标的数组
    sum = col*row,// 棋盘所有格子的总数
    openGz = 0,// 已经点开的格子的数量
    color = ['rgba(0,0,255,.6)','rgba(0,255,0,.6)','red','blue','yellow','pink','auqa','black']
    ;
  window.oncontextmenu = function(e){
   e.preventDefault();
   if(!flag){
    alert('请先点开始!');
    return;
   }
   if(e.target.isOpen){
    alert('这个格子已经翻过了,换个格子标记');
    return
   }
   if(e.target.localName == 'li'){
    if(e.target.isMark){
     e.target.isMark = false;
     e.target.innerHTML = '';
     restNum++;
    }else{
     e.target.isMark = true;
     e.target.innerHTML = '▲';
     e.target.style.color = 'red';
     restNum--;
    }
    leftLei.innerHTML = restNum
   }
  }
  start.onclick = function(){//点击开始游戏
   flag = true;// 棋盘可以被点击
   if(time>0){// 判断开始键是否已经被点过,防止重复点击
    alert('游戏已经开始了,不要再点开始了')
    return
   }
   countTime()//开始计时
  }
  restart.onclick = function(){//点击开始游戏
   flag = false;// flag置为false,棋盘格子变成不可点击状态
   createQp();// 画棋盘
  }
  box.onclick = function(e){//点击棋盘的格子
   var t = e.target;
   if(t.localName == 'li'){// 只有当点击的格子是li的时候才会继续往下判断
    if(!flag){// 如果当前不允许点击,提示先点开始
     alert('请先点开始!')
     return
    }
    var x = t.dataset.x - 0 ,y = t.dataset.y - 0;
    // console.log(x,y);
    if(t.isOpen){
     alert('这个格子已经翻过了,换个格子翻');
     return
    }
    if(t.isMark){
     alert('这个格子已经标记了,换个格子翻');
     return
    }
    if(isInArray(x,y,leiList) != -1 ){
     flag = false;
     clearInterval(time);
     count = 0;
     passTime.innerHTML = count;
     boom();
     alert('你输了')
    }else{
     testLei(x,y);
     if(leiNum == sum - openGz){
      flag = false;
      boom();
      clearInterval(time);
      alert('你赢了');
     }
    }
   }
  }
  level.onchange = function(){
   var v = this.value;//获取改变后的level
   if(v == 1){//改变棋盘规格及雷的数量
    row = 10;
    col = 10;
    leiNum = 10;
   }else if(v == 2){
    row = 16;
    col = 16;
    leiNum = 40;
   }else if(v == 3){
    row = 16;
    col = 30;
    leiNum = 99;
   }
   createQp();// 重新画棋盘
  };
  function createQp(){// 创建棋盘
   var str = '';
   for(var i = 0;i<row;i++){// 行数
    str += '<ul class="row">'
    for(var j = 0;j<col;j++){// 列数
     str+='<li class="col" data-x="'+i+'" data-y="'+j+'"></li>'
    }
    str += '</ul>'
   }
   box.style.width = col * 30 +'px';//修改box的宽度
   box.style.height = row * 30 + 50 +'px';// 修改box的高度
   leftLei.innerHTML = leiNum;// 修改剩余雷数
   qipan.innerHTML = str;// 将拼接的棋盘内容添加到棋盘中
   count = 0;// 计时重置为0
   sum = row*col;// 重置格子的总数
   openGz = 0;// 重置已经点开的格子的数量
   passTime.innerHTML = count; // 时间设置为count
   restNum = leiNum;//重置剩余的雷的数量
   leftLei.innerHTML = restNum;
   clearInterval(time);// 清除定时器
   time = 0;// 定时器变量的值置为 0 
   createLei();
  }
  function countTime(){// 开始计时
   time = setInterval(function(){
    count++;
    passTime.innerHTML = count;
   },1000)
  }
  function createLei(){// 创建地雷
   leiList = [];// 把地雷的坐标先清空
   for(var i = 0;i<leiNum;i++){
    var x = parseInt(Math.random()*row),//
     y = parseInt(Math.random()*col);//
     if(isInArray(x,y,leiList) == -1){// 如果 x,y组成的坐标[x,y] 不在leiList里
      leiList.push([x,y])// 把 [x,y] push进 leiList里
     }else{// x,y组成的坐标 [x,y] 已经在 leiList里了
      i-- // 重新取一次随机坐标
     }
   }
  }
  // arr = [[0,0],[1,1],[2,2],...]
  function isInArray(x,y,arr){// 判断 x,y 组成的坐标 [x,y] 在不在数组 arr 里
   for(var i = 0;i<arr.length;i++){// 遍历arr的每一个元素
    if(x == arr[i][0] && y == arr[i][1]){// 将 x与arr[i]的第0个元素对比,将 y 与 arr[i]的第1个元素对比,如果能对上,说明 [x,y] 已经存在于 arr 里,
     return i;// 返回[x,y] 在 arr中的索引
    }
   }
   if(i == arr.length){// 当 循环遍历一遍也没在arr中找到与 [x,y] 相同的坐标时,说明 [x,y] 不在arr 里
    return -1;// 返回 -1;
   }
  }
  function boom(){// boom
   var ul = $('.row','l');//获取棋盘里所有的行
   for(var i = 0;i<leiList.length;i++){
    var li = ul[leiList[i][0]].querySelectorAll('li')[leiList[i][1]];//通过索引去获取行里具体的li
    li.style.background = 'red'
   }
  }
  function testLei(x,y){
   var num = 0; // 声明一个num用来累计雷的数量
   for(var i = 0;i<leiList.length;i++){// 遍历所有的雷的坐标
    if(Math.abs(x - leiList[i][0]) <2 && Math.abs(y - leiList[i][1])<2){// 找到在当前点击的格子周围八个格子里的雷
     num++;
    }
   }
   var ul = $('.row','l');
   var li = ul[x].querySelectorAll('li')[y];// 通过索引获取当前被点击的格子
   li.innerHTML = num;// 把格子的内容换成雷的数量
   li.isOpen = true;// 给当前格子加一个属性 isOpen,表示当前格子已经被点开了
   openGz++;
   li.style.background = '#fff';
   if(num>0){
    li.style.color = color[num-1];// 把代表雷的数量的数字换一个颜色
   }
   if(num == 0){// 如果当前格子周围没有雷
    li.innerHTML = '';// 
    for(var a = x-1;a<=x+1;a++){// 
     for(var b = y-1;b<=y+1;b++){// 遍历当前格子周围八个格子
      var ul = $('ul','l');
      if(a>= 0 && a<row && b>=0 && b<col){// 保证要遍历的格子坐标在棋盘之内
       var dom = ul[a].querySelectorAll('li')[b];// 通过坐标获取到具体的 li
       if(!dom.isOpen && !dom.isMark){// 判断当前的li格子是否已经被点开了,如果还没有被点开,递归查询该格子周围有几颗雷
        testLei(a,b)
       }
      }
     }
    }
   }
  }
  createQp();
 </script>
</body>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS 常用校验函数
Mar 26 Javascript
javascript 获取表单file全路径
Dec 31 Javascript
jQuery的写法不同导致的兼容性问题的解决方法
Jul 29 Javascript
网页打开自动最大化的js代码
Aug 22 Javascript
Js 代码中,ajax请求地址后加随机数防止浏览器缓存的原因
May 07 Javascript
jQuery实现首页顶部可伸缩广告特效代码
Apr 15 Javascript
Jsonp post 跨域方案
Jul 06 Javascript
针对后台列表table拖拽比较实用的jquery拖动排序
Oct 10 Javascript
fckeditor部署到weblogic出现xml无法读取及样式不能显示问题的解决方法
Mar 24 Javascript
使用JQ完成表格隔行换色的简单实例
Aug 25 Javascript
vue+element tabs选项卡分页效果
Jun 29 Javascript
create-react-app中添加less支持的实现
Nov 15 Javascript
JS+CSS实现过渡特效
Jan 02 #Javascript
jQuery实现全选按钮
Jan 01 #jQuery
vue实现登录功能
Dec 31 #Vue.js
vue 实现图片懒加载功能
Dec 31 #Vue.js
vue 动态创建组件的两种方法
Dec 31 #Vue.js
Vue 修改网站图标的方法
Dec 31 #Vue.js
利用 JavaScript 实现并发控制的示例代码
Dec 31 #Javascript
You might like
提升PHP执行速度全攻略(下)
2006/10/09 PHP
在PHP中利用wsdl创建标准webservice的实现代码
2011/12/07 PHP
php初始化对象和析构函数的简单实例
2014/03/11 PHP
10个实用的PHP正则表达式汇总
2014/10/23 PHP
php版微信数据统计接口用法示例
2016/10/12 PHP
ext checkboxgroup 回填数据解决
2009/08/21 Javascript
firefox事件处理之自动查找event的函数(用于onclick=foo())
2010/08/05 Javascript
jQuery 操作option的实现代码
2011/03/03 Javascript
jquery和雅虎的yql服务实现天气预报服务示例
2014/02/08 Javascript
javascript生成随机数的方法
2014/05/16 Javascript
javascript实现阻止iOS APP中的链接打开Safari浏览器
2014/06/12 Javascript
Javascript学习笔记之 函数篇(二) : this 的工作机制
2014/06/24 Javascript
使用jsonp完美解决跨域问题
2014/11/27 Javascript
jquery实现简单的全选和反选功能
2016/01/02 Javascript
javascript高级选择器querySelector和querySelectorAll全面解析
2016/04/07 Javascript
Vue.js中数组变动的检测详解
2016/10/12 Javascript
微信小程序 页面传参实例详解
2016/11/16 Javascript
JavaScript中this的用法实例分析
2016/12/19 Javascript
基于JavaScript实现活动倒计时效果
2017/04/20 Javascript
Vue表单类的父子组件数据传递示例
2018/05/03 Javascript
简谈创建React Component的几种方式
2019/06/15 Javascript
vue组件传值的实现方式小结【三种方式】
2020/02/05 Javascript
JavaScript实现Tab标签页切换的最简便方式(4种)
2020/06/28 Javascript
在vant中使用时间选择器和popup弹出层的操作
2020/11/04 Javascript
一些Python中的二维数组的操作方法
2015/05/02 Python
Python合并字符串的3种方法
2015/05/21 Python
Django中Forms的使用代码解析
2018/02/10 Python
python读取图片任意范围区域
2019/01/23 Python
python 3.7.4 安装 opencv的教程
2019/10/10 Python
PYTHON如何读取和写入EXCEL里面的数据
2019/10/28 Python
python怎么对数字进行过滤
2020/07/05 Python
护士求职信范文
2014/05/24 职场文书
团队队名口号大全
2014/06/06 职场文书
企业财务人员岗位职责
2015/04/14 职场文书
浅谈:电影《孔子》观后感(范文)
2019/10/14 职场文书
PySwarms(Python粒子群优化工具包)的使用:GlobalBestPSO例子解析
2021/04/05 Python