服务器之家:专注于服务器技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - js教程 - 原生js实现自定义难度的扫雷游戏

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

2022-01-06 15:16清欢灬 js教程

这篇文章主要为大家详细介绍了原生js实现自定义难度的扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

游戏功能:

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

1、html相关代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!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样式

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
*{
 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代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
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教程JavaScript Html实现移动端红包雨功能页面

    JavaScript Html实现移动端红包雨功能页面

    这篇文章主要为大家详细介绍了JavaScript Html实现移动端红包雨功能页面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考...

    Jeslie-He4742021-12-29
  • js教程JS+CSS实现过渡特效

    JS+CSS实现过渡特效

    这篇文章主要为大家详细介绍了JS+CSS实现过渡特效,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Dr_空山3582021-12-23
  • js教程原生js实现自定义滚动条组件

    原生js实现自定义滚动条组件

    这篇文章主要为大家详细介绍了原生js实现自定义滚动条组件的开发,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一...

    蒲公英芽11192022-01-05
  • js教程JavaScript 中 find() 和 filter() 方法的区别

    JavaScript 中 find() 和 filter() 方法的区别

    JavaScript 在 ES6 上有很多数组方法,每种方法都有独特的用途和好处。...

    锋享前端4592021-12-28
  • js教程浅析JavaScript中的事件委托机制跟深浅拷贝

    浅析JavaScript中的事件委托机制跟深浅拷贝

    这篇文章主要介绍了JavaScript中的事件委托机制跟深浅拷贝,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要...

    打游戏也要有梦想5562022-01-05
  • js教程JavaScript实现下拉列表

    JavaScript实现下拉列表

    这篇文章主要为大家详细介绍了JavaScript实现下拉列表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    编程的牛牛11542022-01-05
  • js教程基于javascript实现移动端轮播图效果

    基于javascript实现移动端轮播图效果

    这篇文章主要为大家详细介绍了基于javascript实现移动端轮播图效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    A.香辣鸡腿堡8982021-12-15
  • js教程原生js实现放大镜组件

    原生js实现放大镜组件

    这篇文章主要为大家详细介绍了js实现放大镜组件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    蒲公英芽5272022-01-06