服务器之家

服务器之家 > 正文

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

时间:2022-01-06 15:16     来源/作者:清欢灬

本文实例为大家分享了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

标签:

相关文章

热门资讯

蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
2021年耽改剧名单 2021要播出的59部耽改剧列表
2021年耽改剧名单 2021要播出的59部耽改剧列表 2021-03-05
返回顶部