• 售前

  • 售后

热门帖子
入门百科

原生js实现自界说难度的扫雷游戏

[复制链接]
123456881 显示全部楼层 发表于 2021-10-25 20:08:53 |阅读模式 打印 上一主题 下一主题
本文实例为各人分享了js实现扫雷游戏的具体代码,供各人参考,具体内容如下

游戏功能:

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

1、html相干代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>扫雷</title>
  7. <script src="js/mine.js"></script>
  8. <link rel="stylesheet" href="./css/mine.css" >
  9. </head>
  10. <!--
  11. 需求分析:
  12. 1.游戏的区域:
  13.   9*9的区域
  14. 2.方格可以打开与标记
  15.   左键打开,显示数字,为周围格子的地雷数,右键标记
  16. 3.地雷
  17.   地雷随机分布
  18. 4.踩到地雷时,游戏结束
  19.   所有的地雷显示出来
  20. 5.连锁开大空方格
  21. 6.剩余地雷数与计时器
  22. 7.游戏胜利条件
  23.   所有的方格除了地雷都被打开了,则游戏胜利
  24. 一个方格所包含的信息:
  25.   坐标 x y
  26.   是否是一个地雷
  27.   周围的地雷数 = 9
  28.   二维数组中存储的是周围的地雷数
  29. -->
  30. <body>
  31. <div class="level">
  32. <button type="button" name="button" class="choice-level">自定义</button>
  33. <button type="button" name="button" class="choice-level">初级</button>
  34. <button type="button" name="button" class="choice-level">中级</button>
  35. <button type="button" name="button" class="choice-level">高级</button>
  36. <button type="button" name="button" class="choice-level">魔鬼级</button>
  37. <button type="button" name="button" class="restart">重新开始</button>
  38. </div>
  39. <div class="gameBox"></div>
  40. <div class="info">
  41. <p>剩余雷数:
  42.   <span class="residue"></span>
  43. </p>
  44. <p>
  45.   TIME:
  46.   <span class="tick"></span>S
  47. </p>
  48. </div>
  49. </body>
  50. </html>
复制代码
2、css样式

  1. *{
  2. margin: 0;
  3. padding: 0;
  4. }
  5. .gameBox{
  6. margin-top: 30px;
  7. }
  8. body{
  9. font-size: 0;
  10. }
  11. ul{
  12. list-style: none;
  13. text-align: center;
  14. overflow: hidden;
  15. }
  16. .col{
  17. display: inline-block;
  18. width: 22px;
  19. height: 22px;
  20. line-height: 22px;
  21. background-color: rgba(32, 226, 255, 0.4);
  22. border: 1px solid rgb(129, 129, 129);
  23. font-size: 16px;
  24. margin: 1.5px;
  25. vertical-align: top;
  26. position: relative;
  27. }
  28. .col:hover{
  29. background-color: #0af;
  30. }
  31. .col span{
  32. cursor: default;
  33. }
  34. .hide{
  35. display: none;
  36. }
  37. .boom{
  38. background: url("../img/boom.svg") no-repeat 2.5px 2px;
  39. background-size: 18px 18px;
  40. }
  41. .num-1{
  42. color: rgb(8, 153, 235);
  43. }
  44. .num-2{
  45. color: rgb(255, 45, 178);
  46. }
  47. .num-3{
  48. color:#16a085;
  49. }
  50. .num-4{
  51. color: #8e44ad;
  52. }
  53. .num-5{
  54. color: rgb(255, 167, 45);
  55. }
  56. .num-6{
  57. color: rgb(8, 126, 176);
  58. }
  59. .num-7{
  60. color: #e67e22;
  61. }
  62. .num-8{
  63. color: #c0392b;
  64. }
  65. .img-flag{
  66. width: 18px;
  67. height: 18px;
  68. position: absolute;
  69. top: 3px;
  70. left: 3px;
  71. }
  72. .level{
  73. margin-top: 30px;
  74. font-size: 20px;
  75. text-align: center;
  76. }
  77. .level button{
  78. padding: 5px 8px;
  79. background-color: rgb(67, 183, 189);
  80. border: none;
  81. outline: none;
  82. border-radius: 3px;
  83. cursor: pointer;
  84. color: #fff;
  85. }
  86. .level button:hover{
  87. background-color: rgb(23, 132, 138);
  88. }
  89. .info{
  90. margin-top: 30px;
  91. font-size: 16px;
  92. text-align: center;
  93. }
  94. .info p{
  95. display: inline-block;
  96. width: 130px;
  97. margin: 0 auto;
  98. }
  99. .info p span{
  100. color: rgb(67, 183, 189);
  101. }
复制代码
3、js代码

  1. window.onload = function() {
  2. var row = 4;
  3. var col = 4;
  4. var num = 1;
  5. // 判断踩雷之后不能胜利
  6. var gg = false;
  7. // 生成地图
  8. function mineMap(r, c, num) {
  9. // 定义行
  10. var map = [];
  11. //给行数,生成二维数组
  12. for (var i = 0; i < r; i++) {
  13.   map[i] = new Array()
  14. }
  15. // 赋值
  16. for (var i = 0; i < map.length; i++) {
  17.   for (var j = 0; j < c; j++) {
  18.   // //周围的地雷数
  19.   map[i][j] = 0;
  20.   }
  21. }
  22. var plus = function(array, x, y) {
  23.   if (x >= 0 && x < r && y >= 0 && y < c) {
  24.   if (array[x][y] !== 9) {
  25.    array[x][y]++
  26.   }
  27.   }
  28. }
  29. for (var i = 0; i < num; i++) {
  30.   var x = Math.floor(Math.random() * r)
  31.   var y = Math.floor(Math.random() * c)
  32.   if (map[x][y] != 9) {
  33.   map[x][y] = 9
  34.    //上下6个 +1
  35.   for (var j = -1; j < 2; j++) {
  36.    //上三个
  37.    plus(map, x - 1, y + j)
  38.    //下三个
  39.    plus(map, x + 1, y + j)
  40.   }
  41.   //左右2个 +1
  42.   plus(map, x, y - 1)
  43.   plus(map, x, y + 1)
  44.   } else {
  45.   //重新随机
  46.   num++
  47.   }
  48. }
  49. return map;
  50. }
  51. //先通过x轴数量写入ul,再讲过y轴的属性写入li
  52. function writeHtml(map) {
  53. // 获取盒子
  54. var gameBox = document.querySelector(".gameBox");
  55. // 声明空字符串,存放生成的ul、li
  56. var gridHTML = "";
  57. for (var i = 0; i < map.length; i++) {
  58.   gridHTML += '<ul class = "row" data-x="' + i + '">';
  59.   //生成li
  60.   for (var j = 0; j < map[0].length; j++) {
  61.   var m = map[i][j]
  62.   if (m == 0) {
  63.    m = "";
  64.   }
  65.   gridHTML += "<li class='col' data-y=" + j + ">" +
  66.    "<span class='hide num-" + m + "'>" + m + "</span>" +
  67.    "<img src='img/flag.svg' class='img-flag hide'>" +
  68.    "</li>"
  69.   }
  70.   gridHTML += '</ul>'
  71.   gameBox.innerHTML = gridHTML;
  72. }
  73. }
  74. //给方格绑定事件, 点开数字 地雷 右键标记
  75. function show() {
  76. // 获取行ul
  77. var rows = document.querySelectorAll(".row");
  78. // 遍历所有ul
  79. for (var i = 0; i < rows.length; i++) {
  80.   var element = rows[i];
  81.   // 添加点击事件
  82.   element.onclick = function(event) {
  83.    // 当前点击元素
  84.    var el = event.target;
  85.    // 判断是否为li
  86.    if (el.nodeName != "LI") {
  87.    return;
  88.    }
  89.    //todo 判断是否被打开以及标记了
  90.    if (el.style.background == "white" || !el.children[1].classList.contains("hide")) {
  91.    return;
  92.    }
  93.    // 获取span标签内容
  94.    var mineNum = el.children[0].innerHTML;
  95.    if (mineNum !== "9" && el.style.background !== "white") {
  96.    // 空白连锁打开
  97.    if (mineNum == "") {
  98.     var x = parseInt(el.parentNode.dataset.x);
  99.     var y = parseInt(el.dataset.y);
  100.     showNoMine(x, y);
  101.    }
  102.    // li背景变白色;span显示
  103.    el.style.background = "white";
  104.    el.children[0].style.display = "inline";
  105.    // 判断打开数量
  106.    clearMineNum++;
  107.    // 胜利函数
  108.    judgeVictory()
  109.    } else if (mineNum == "9") {
  110.    // 清除胜利计时器
  111.    clearInterval(stopTime);
  112.    // li添加类名
  113.    el.classList.add("boom");
  114.    alert("你真菜!")
  115.    gg = true;
  116.    // 显示所有地雷,获取所有li
  117.    var all = document.querySelectorAll(".col");
  118.    // 放置所有的地雷
  119.    var ff = [];
  120.    var allnum = 0;
  121.    // 遍历所有li
  122.    for (var i = 0; i < all.length; i++) {
  123.     if (all[i].children[0].innerHTML == "9") {
  124.     // 雷赋值给数组
  125.     ff[allnum] = all[i];
  126.     allnum++;
  127.     }
  128.    }
  129.    // 设置一个计时器一个一个打开雷
  130.    allnum = 0;
  131.    var stop = setInterval(function() {
  132.     ff[allnum].classList.add("boom")
  133.     allnum++;
  134.     // 判断结束条件
  135.     if (allnum == ff.length) {
  136.     // 清除计时器
  137.     clearInterval(stop);
  138.     }
  139.    }, 30)
  140.    }
  141.   }
  142.   // 右键标记地雷
  143.   element.oncontextmenu = function(event) {
  144.   // 阻止右键菜单
  145.   event.preventDefault();
  146.   // 获取当前点击节点
  147.   var el = event.target;
  148.   // 判断是否是
  149.   if (el.parentNode.nodeName == "LI") {
  150.    el = el.parentNode;
  151.   }
  152.   if (el.nodeName != "LI") {
  153.    return;
  154.   }
  155.   // 获取img
  156.   var classList = el.children[1].classList;
  157.   // 剩余雷数
  158.   var residue = document.querySelector(".residue");
  159.   var mineNum = parseInt(residue.innerHTML);
  160.   // 如果没有旗子,没有被点开,可以插旗子
  161.   if (classList.contains("hide") && el.style.background != "white") {
  162.    // 移除隐藏
  163.    classList.remove("hide");
  164.    // 获取雷数
  165.    mineNum--;
  166.   } else if (el.style.background != "white") {
  167.    classList.add("hide");
  168.    // 判断雷数
  169.    if (mineNum < num) {
  170.    mineNum++;
  171.    }
  172.   }
  173.   // 剩余雷数
  174.   residue.innerHTML = mineNum;
  175.   }
  176. }
  177. }
  178. function judgeVictory() {
  179. //游戏胜利
  180. if (clearMineNum === (row * col - num)) {
  181.   //做一个小动画
  182.   var all = document.querySelectorAll(".col");
  183.   var allNum = 0;
  184.   var stop = setInterval(function() {
  185.   var r = Math.floor(Math.random() * 256)
  186.   var g = Math.floor(Math.random() * 256)
  187.   var b = Math.floor(Math.random() * 256)
  188.   all[allNum].style.background = "rgba(" + r + "," + g + "," + b + ",0.6)";
  189.   //将旗子和span都隐藏
  190.   all[allNum].children[0].style.display = "none"
  191.   all[allNum].children[1].style.display = "none"
  192.   allNum++
  193.   if (allNum === all.length) {
  194.    clearInterval(stop)
  195.    if (!gg) {
  196.    alert("大吉大利,今晚吃鸡")
  197.    init(row, col, num)
  198.    }
  199.   }
  200.   }, 20)
  201. }
  202. }
  203. //自动打开空格
  204. function showNoMine(x, y) {
  205. for (var i = -1; i <= 1; i++) {
  206.   if (x + i >= 0 && x + i < row) {
  207.   // 获取当前行
  208.   var rowElement = document.querySelectorAll(".row")[x + i];
  209.   for (var j = -1; j <= 1; j++) {
  210.    if (y + j >= 0 && y + j < col) {
  211.    //获取当前单元格
  212.    var el = rowElement.children[y + j]
  213.     //自动打开必须是未打开的方格
  214.    if (el.style.background != "white") {
  215.     el.style.background = "white"
  216.     el.children[0].style.display = "inline"
  217.     //打开方格数量+1
  218.     clearMineNum++
  219.     //判断游戏是否胜利
  220.     judgeVictory(clearMineNum)
  221.     if (el.children[0].innerText === "") {
  222.     showNoMine(x + i, y + j)
  223.     }
  224.    }
  225.    }
  226.   }
  227.   }
  228.   // if (x + i >= 0 && x + i < row) {
  229.   // // 获取当前行
  230.   // var rowElement = document.querySelectorAll(".row")[x + i];
  231.   // for (var j = -1; j <= 1; j++ && y + j < col) {
  232.   //  // 获取当前单元格
  233.   //  var el = rowElement.children[y + j];
  234.   //  if (el.style.background !== "white") {
  235.   //  el.style.background = "white";
  236.   //  el.children[0].style.display = "inline";
  237.   //  // 打开放格数量加1
  238.   //  clearMineNum++;
  239.   //  // 判断游戏是否胜利
  240.   //  judgeVictory(clearMineNum);
  241.   //  // 判断打开周围的放格周围是否为空
  242.   //  if (el.children[0].innerHTML === "") {
  243.   //   showNoMine(x + i, y + j)
  244.   //  }
  245.   //  }
  246.   // }
  247.   // }
  248. }
  249. }
  250. //初始化方法
  251. var stopTime;
  252. function init(row, col, num) {
  253. //数据初始化
  254. clearMineNum = 0
  255. gg = false;
  256. //清除原来的地图,生成新的地图
  257. var box = document.querySelector(".gameBox")
  258. box.innerHTML = "";
  259. var map = mineMap(row, col, num);
  260. // 新建地图
  261. writeHtml(map);
  262. show()
  263.   //将雷数写入html中
  264. var residue = document.querySelector(".residue")
  265. residue.innerHTML = num
  266.   // 获取计时
  267. var tick = document.querySelector(".tick");
  268. var i = 0;
  269. // 初始化
  270. tick.innerHTML = i;
  271. // 清除计时
  272. clearInterval(stopTime);
  273. // 时间计时器
  274. stopTime = setInterval(function() {
  275.   tick.innerHTML = ++i
  276. }, 1000)
  277. }
  278. // 重置
  279. var restart = document.querySelector(".restart");
  280. restart.onclick = function(event) {
  281.   //阻止冒泡
  282.   event.stopPropagation()
  283.   init(row, col, num)
  284. }
  285. // 自定义
  286. var level = document.querySelector(".level")
  287. level.onclick = function(event) {
  288. var el = event.target;
  289. switch (el.innerHTML) {
  290.   case "初级":
  291.   row = 9;
  292.   col = 9;
  293.   num = 10;
  294.   init(row, col, num)
  295.   break;
  296.   case "中级":
  297.   row = 16;
  298.   col = 16;
  299.   num = 40;
  300.   init(row, col, num)
  301.   break;
  302.   case "高级":
  303.   row = 16;
  304.   col = 30;
  305.   num = 479;
  306.   init(row, col, num)
  307.   break;
  308.   case "魔鬼级":
  309.   row = 40;
  310.   col = 50;
  311.   num = 300;
  312.   init(row, col, num)
  313.   break;
  314.   case "自定义":
  315.   row = prompt("请输入列数!");
  316.   col = prompt("请输入行数!");
  317.   num = prompt("请输入你想要的雷数,(请慎重选择)");
  318.   init(row, col, num);
  319.   break;
  320.   default:
  321.   row = 9;
  322.   col = 9;
  323.   num = 10;
  324.   init(row, col, num)
  325.   break;
  326. }
  327. }
  328. init(row, col, num)
  329. }
复制代码
以上就是本文的全部内容,盼望对各人的学习有所资助,也盼望各人多多支持脚本之家。

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作