好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

原生js实现自定义难度的扫雷游戏

本文实例为大家分享了js实现扫雷游戏的具体代码,供大家参考,具体内容如下

游戏功能:

1、有四个难度
2、可以自定难度

1、html相关代码

?

<!DOCTYPE html>

< html lang = "en" >

 

< head >

  < meta charset = "UTF-8" >

  < meta name = "viewport" content = "width=device-width, initial-scale=1.0" >

  < title >扫雷</ title >

  < script src = "js/mine.js" ></ script >

  < link rel = "stylesheet" href = "./css/mine.css" >

</ head >

<!--

需求分析:

  1.游戏的区域:

   9*9的区域

  2.方格可以打开与标记

   左键打开,显示数字,为周围格子的地雷数,右键标记

  3.地雷

   地雷随机分布

  4.踩到地雷时,游戏结束

   所有的地雷显示出来

  5.连锁开大空方格

  6.剩余地雷数与计时器

  7.游戏胜利条件

   所有的方格除了地雷都被打开了,则游戏胜利

  一个方格所包含的信息:

   坐标 x y

   是否是一个地雷

   周围的地雷数 = 9

   二维数组中存储的是周围的地雷数

  -->

 

< body >

  < div class = "level" >

  < button type = "button" name = "button" class = "choice-level" >自定义</ button >

  < button type = "button" name = "button" class = "choice-level" >初级</ button >

  < button type = "button" name = "button" class = "choice-level" >中级</ button >

  < button type = "button" name = "button" class = "choice-level" >高级</ button >

  < button type = "button" name = "button" class = "choice-level" >魔鬼级</ button >

  < button type = "button" name = "button" class = "restart" >重新开始</ button >

  </ div >

  < div class = "gameBox" ></ div >

  < div class = "info" >

  < p >剩余雷数:

   < span class = "residue" ></ span >

  </ p >

  < p >

   TIME:

   < span class = "tick" ></ span >S

  </ p >

 

  </ div >

</ body >

 

 

</ html >

2、css样式

?

*{

  margin : 0 ;

  padding : 0 ;

}

.gameBox{

  margin-top : 30px ;

}

body{

  font-size : 0 ;

}

ul{

  list-style : none ;

  text-align : center ;

  overflow : hidden ;

}

.col{

  display : inline- block ;

  width : 22px ;

  height : 22px ;

  line-height : 22px ;

  background-color : rgba( 32 , 226 , 255 , 0.4 );

  border : 1px solid rgb ( 129 , 129 , 129 );

  font-size : 16px ;

  margin : 1.5px ;

  vertical-align : top ;

  position : relative ;

}

.col:hover{

  background-color : #0af ;

}

.col span{

  cursor : default ;

}

. hide {

  display : none ;

}

.boom{

  background : url ( "img/boom.svg" ) no-repeat 2.5px 2px ;

  background- size : 18px 18px ;

}

.num -1 {

  color : rgb ( 8 , 153 , 235 );

}

.num -2 {

  color : rgb ( 255 , 45 , 178 );

}

.num -3 {

  color : #16a085 ;

}

.num -4 {

  color : #8e44ad ;

}

.num -5 {

  color : rgb ( 255 , 167 , 45 );

}

.num -6 {

  color : rgb ( 8 , 126 , 176 );

}

.num -7 {

  color : #e67e22 ;

}

.num -8 {

  color : #c0392b ;

}

.img-flag{

  width : 18px ;

  height : 18px ;

  position : absolute ;

  top : 3px ;

  left : 3px ;

}

. level {

  margin-top : 30px ;

  font-size : 20px ;

  text-align : center ;

}

. level button{

  padding : 5px 8px ;

  background-color : rgb ( 67 , 183 , 189 );

  border : none ;

  outline : none ;

  border-radius: 3px ;

  cursor : pointer ;

  color : #fff ;

}

. level button:hover{

  background-color : rgb ( 23 , 132 , 138 );

}

.info{

  margin-top : 30px ;

  font-size : 16px ;

  text-align : center ;

}

.info p{

  display : inline- block ;

  width : 130px ;

  margin : 0 auto ;

}

.info p span{

  color : rgb ( 67 , 183 , 189 );

}

3、js代码

?

window.onload = function () {

  var row = 4;

  var col = 4;

  var num = 1;

  // 判断踩雷之后不能胜利

  var gg = false ;

  // 生成地图

  function mineMap(r, c, num) {

  // 定义行

  var map = [];

  //给行数,生成二维数组

  for ( var i = 0; i < r; i++) {

   map[i] = new Array()

  }

  // 赋值

  for ( var i = 0; i < map.length; i++) {

   for ( var j = 0; j < c; j++) {

   // //周围的地雷数

   map[i][j] = 0;

   }

  }

  var plus = function (array, x, y) {

   if (x >= 0 && x < r && y >= 0 && y < c) {

   if (array[x][y] !== 9) {

    array[x][y]++

   }

   }

  }

  for ( var i = 0; i < num; i++) {

   var x = Math.floor(Math.random() * r)

   var y = Math.floor(Math.random() * c)

   if (map[x][y] != 9) {

   map[x][y] = 9

    //上下6个 +1

   for ( var j = -1; j < 2; j++) {

    //上三个

    plus(map, x - 1, y + j)

    //下三个

    plus(map, x + 1, y + j)

   }

   //左右2个 +1

   plus(map, x, y - 1)

   plus(map, x, y + 1)

   } else {

   //重新随机

   num++

   }

  }

  return map;

  }

  //先通过x轴数量写入ul,再讲过y轴的属性写入li

  function writeHtml(map) {

  // 获取盒子

  var gameBox = document.querySelector( ".gameBox" );

  // 声明空字符串,存放生成的ul、li

  var gridHTML = "" ;

  for ( var i = 0; i < map.length; i++) {

   gridHTML += '<ul class = "row" data-x="' + i + '">' ;

   //生成li

   for ( var j = 0; j < map[0].length; j++) {

   var m = map[i][j]

   if (m == 0) {

    m = "" ;

   }

   gridHTML += "<li class='col' data-y=" + j + ">" +

    "<span class='hide num-" + m + "'>" + m + "</span>" +

    "<img src='img/flag.svg' class='img-flag hide'>" +

    "</li>"

   }

   gridHTML += '</ul>'

   gameBox.innerHTML = gridHTML;

  }

  }

 

  //给方格绑定事件, 点开数字 地雷 右键标记

  function show() {

  // 获取行ul

  var rows = document.querySelectorAll( ".row" );

  // 遍历所有ul

  for ( var i = 0; i < rows.length; i++) {

   var element = rows[i];

   // 添加点击事件

   element.onclick = function (event) {

    // 当前点击元素

    var el = event.target;

    // 判断是否为li

    if (el.nodeName != "LI" ) {

    return ;

    }

    //todo 判断是否被打开以及标记了

    if (el.style.background == "white" || !el.children[1].classList.contains( "hide" )) {

    return ;

    }

    // 获取span标签内容

    var mineNum = el.children[0].innerHTML;

    if (mineNum !== "9" && el.style.background !== "white" ) {

    // 空白连锁打开

    if (mineNum == "" ) {

     var x = parseInt(el.parentNode.dataset.x);

     var y = parseInt(el.dataset.y);

     showNoMine(x, y);

    }

    // li背景变白色;span显示

    el.style.background = "white" ;

    el.children[0].style.display = "inline" ;

    // 判断打开数量

    clearMineNum++;

    // 胜利函数

    judgeVictory()

 

    } else if (mineNum == "9" ) {

    // 清除胜利计时器

    clearInterval(stopTime);

    // li添加类名

    el.classList.add( "boom" );

    alert( "你真菜!" )

    gg = true ;

    // 显示所有地雷,获取所有li

    var all = document.querySelectorAll( ".col" );

    // 放置所有的地雷

    var ff = [];

    var allnum = 0;

    // 遍历所有li

    for ( var i = 0; i < all.length; i++) {

     if (all[i].children[0].innerHTML == "9" ) {

     // 雷赋值给数组

     ff[allnum] = all[i];

     allnum++;

     }

    }

    // 设置一个计时器一个一个打开雷

    allnum = 0;

    var stop = setInterval( function () {

     ff[allnum].classList.add( "boom" )

     allnum++;

     // 判断结束条件

     if (allnum == ff.length) {

     // 清除计时器

     clearInterval(stop);

     }

    }, 30)

 

    }

   }

   // 右键标记地雷

   element.oncontextmenu = function (event) {

   // 阻止右键菜单

   event.preventDefault();

   // 获取当前点击节点

   var el = event.target;

   // 判断是否是

   if (el.parentNode.nodeName == "LI" ) {

    el = el.parentNode;

   }

   if (el.nodeName != "LI" ) {

    return ;

   }

   // 获取img

   var classList = el.children[1].classList;

   // 剩余雷数

   var residue = document.querySelector( ".residue" );

   var mineNum = parseInt(residue.innerHTML);

   // 如果没有旗子,没有被点开,可以插旗子

   if (classList.contains( "hide" ) && el.style.background != "white" ) {

    // 移除隐藏

    classList.remove( "hide" );

    // 获取雷数

    mineNum--;

   } else if (el.style.background != "white" ) {

    classList.add( "hide" );

    // 判断雷数

    if (mineNum < num) {

    mineNum++;

    }

   }

   // 剩余雷数

   residue.innerHTML = mineNum;

   }

  }

  }

 

  function judgeVictory() {

  //游戏胜利

  if (clearMineNum === (row * col - num)) {

   //做一个小动画

   var all = document.querySelectorAll( ".col" );

   var allNum = 0;

   var stop = setInterval( function () {

   var r = Math.floor(Math.random() * 256)

   var g = Math.floor(Math.random() * 256)

   var b = Math.floor(Math.random() * 256)

   all[allNum].style.background = "rgba(" + r + "," + g + "," + b + ",0.6)" ;

   //将旗子和span都隐藏

   all[allNum].children[0].style.display = "none"

   all[allNum].children[1].style.display = "none"

   allNum++

   if (allNum === all.length) {

    clearInterval(stop)

    if (!gg) {

    alert( "大吉大利,今晚吃鸡" )

    init(row, col, num)

    }

   }

   }, 20)

  }

  }

  //自动打开空格

  function showNoMine(x, y) {

  for ( var i = -1; i <= 1; i++) {

   if (x + i >= 0 && x + i < row) {

   // 获取当前行

   var rowElement = document.querySelectorAll( ".row" )[x + i];

   for ( var j = -1; j <= 1; j++) {

    if (y + j >= 0 && y + j < col) {

    //获取当前单元格

    var el = rowElement.children[y + j]

     //自动打开必须是未打开的方格

    if (el.style.background != "white" ) {

     el.style.background = "white"

     el.children[0].style.display = "inline"

     //打开方格数量+1

     clearMineNum++

     //判断游戏是否胜利

     judgeVictory(clearMineNum)

 

     if (el.children[0].innerText === "" ) {

     showNoMine(x + i, y + j)

     }

    }

    }

   }

   }

   // if (x + i >= 0 && x + i < row) {

   // // 获取当前行

   // var rowElement = document.querySelectorAll(".row")[x + i];

   // for (var j = -1; j <= 1; j++ && y + j < col) {

   //  // 获取当前单元格

   //  var el = rowElement.children[y + j];

   //  if (el.style.background !== "white") {

   //  el.style.background = "white";

   //  el.children[0].style.display = "inline";

   //  // 打开放格数量加1

   //  clearMineNum++;

   //  // 判断游戏是否胜利

   //  judgeVictory(clearMineNum);

   //  // 判断打开周围的放格周围是否为空

   //  if (el.children[0].innerHTML === "") {

   //   showNoMine(x + i, y + j)

   //  }

   //  }

   // }

   // }

  }

 

  }

  //初始化方法

  var stopTime;

 

  function init(row, col, num) {

  //数据初始化

  clearMineNum = 0

  gg = false ;

  //清除原来的地图,生成新的地图

  var box = document.querySelector( ".gameBox" )

  box.innerHTML = "" ;

  var map = mineMap(row, col, num);

  // 新建地图

  writeHtml(map);

  show()

   //将雷数写入html中

  var residue = document.querySelector( ".residue" )

  residue.innerHTML = num

   // 获取计时

  var tick = document.querySelector( ".tick" );

  var i = 0;

  // 初始化

  tick.innerHTML = i;

  // 清除计时

  clearInterval(stopTime);

  // 时间计时器

  stopTime = setInterval( function () {

   tick.innerHTML = ++i

  }, 1000)

  }

  // 重置

  var restart = document.querySelector( ".restart" );

  restart.onclick = function (event) {

   //阻止冒泡

   event.stopPropagation()

   init(row, col, num)

  }

  // 自定义

  var level = document.querySelector( ".level" )

  level.onclick = function (event) {

  var el = event.target;

  switch (el.innerHTML) {

   case "初级" :

   row = 9;

   col = 9;

   num = 10;

   init(row, col, num)

   break ;

   case "中级" :

   row = 16;

   col = 16;

   num = 40;

   init(row, col, num)

   break ;

   case "高级" :

   row = 16;

   col = 30;

   num = 479;

   init(row, col, num)

   break ;

   case "魔鬼级" :

   row = 40;

   col = 50;

   num = 300;

   init(row, col, num)

   break ;

   case "自定义" :

   row = prompt( "请输入列数!" );

   col = prompt( "请输入行数!" );

   num = prompt( "请输入你想要的雷数,(请慎重选择)" );

   init(row, col, num);

   break ;

   default :

   row = 9;

   col = 9;

   num = 10;

   init(row, col, num)

   break ;

  }

  }

  init(row, col, num)

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/a754334599/article/details/112969475

查看更多关于原生js实现自定义难度的扫雷游戏的详细内容...

  阅读:59次