国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

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

服務器之家 - 編程語言 - JavaScript - js實現(xiàn)掃雷源代碼

js實現(xiàn)掃雷源代碼

2021-11-24 16:32木子three石 JavaScript

這篇文章主要為大家詳細介紹了js實現(xiàn)掃雷源代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

經(jīng)過一段時間學習,對javascript有了一個初步的了解自己制作了一個掃雷,源代碼+詳細注釋放在后面,先看下效果圖。

初始化界面:

js實現(xiàn)掃雷源代碼

游戲界面:

js實現(xiàn)掃雷源代碼

難易程度切換:

js實現(xiàn)掃雷源代碼

游戲結束:

js實現(xiàn)掃雷源代碼

思路

采用構造函數(shù)的形式進行全局開發(fā)

生成游戲棋盤

  • 利用雙層for循環(huán)創(chuàng)建設定的棋盤大小
  • 為每個單元格的dom元素創(chuàng)建一個屬性,該屬性用于保存單元格的所有信息,如x,y坐標,value,是否為雷等

隨機生成炸彈

  • 利用隨機數(shù),隨機生成炸彈x,y坐標,并將符合該坐標信息的單元格的屬性更改為雷
  • 炸彈是在用戶第一次點擊的時候生成,防止用戶第一次點擊到炸彈
  • 將生成的每個炸彈信息都保存到一個this變量中,方便后續(xù)使用
  • 遍歷每個炸彈周圍的非炸彈方格,每遍歷一次value值+1

鼠標左鍵點擊

  • 點擊的時候需要考慮該單元格是否有被標記小旗子(isFlag屬性),如果有則無法點擊
  • 判斷是雷還是數(shù)字,雷的話則游戲結束,數(shù)字則繼續(xù)判斷是否等于0,等于0則使用遞歸顯示空白區(qū)域
  • 每次打開一個單元格,需要更改該單元格的isOpen屬性,表示單元格被打開

鼠標右鍵點擊

  • 點擊時需要考慮該單元格的isOpen屬性是否被打開,打開的話則無法點擊
  • 當該單元格沒有標記旗幟時標記,如果有標記旗幟則取消標記
  • 每標記一個方格,剩余炸彈數(shù)量-1,取消標記則+1

游戲結束

  • 當左鍵點擊到炸彈的時候游戲結束。失敗
  • 剩余炸彈數(shù)量為0時。判斷旗幟標記是否正確,正確游戲勝利,標記有誤則失敗

HTML代碼

超短的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
<!DOCTYPE html>
<html lang="en">
 
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
 <link rel="stylesheet" href="css/index.css" >
</head>
 
<body>
 <div class="main">
  <header class="header">
   <button>初級</button>
   <button>中級</button>
   <button>高級</button>
  </header>
  <div class="gameBox" id="gameBox"></div>
  <footer class="footer">剩余雷數(shù)量:<span id="surplusMine"></span>
  </footer>
 </div>
</body>
<script src="js/index.js"></script>
 
</html>

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
.main .header {
 text-align: center;
 margin: 20px auto;
}
 
.main .gameBox table {
 border-spacing: 1px;
 background-color: rgb(170, 170, 170);
 text-align: center;
 margin: 20px auto;
}
 
.main .gameBox table td.mine {
 /* 游戲結束時顯示 */
 border: none;
 background: url(./../img/mine.png) no-repeat;
 background-size: 90% 90%;
 background-color: #e9e6e6;
 background-position: 2px 0;
}
 
.main .gameBox table td.targetMine {
 /* 游戲結束時顯示,觸發(fā)雷的單元格 */
 border: none;
 background: url(./../img/mine.png) no-repeat;
 background-size: 90% 90%;
 background-color: #ff4b4b;
 background-position: 2px 0;
}
 
.main .gameBox table td.targetFlag {
 /* 右鍵標記方格時顯示 */
 background: url(./../img/flag.png) no-repeat;
 background-size: 90% 90%;
 background-position: 2px 0;
 background-color: #e9e6e6;
}
 
.main .gameBox table td {
 /* 單元格初始樣式 */
 width: 20px;
 height: 20px;
 box-sizing: border-box;
 border: 2px solid;
 border-color: #eee #ccc #ccc #eee;
 background-color: #e9e6e6;
 font-size: 1px;
 font-weight: 800;
}
 
.gameBox table td.zero,
.gameBox table td.one,
.gameBox table td.two,
.gameBox table td.three,
.gameBox table td.four,
.gameBox table td.five,
.gameBox table td.six,
.gameBox table td.seven,
.gameBox table td.eight,
.gameBox table td.nine {
 border: none;
 background-color: rgb(211, 200, 200);
}
 
.gameBox table td.zero {}
 
.gameBox table td.one {
 color: blue;
}
 
.gameBox table td.two {
 color: rgb(5, 93, 5);
}
 
.gameBox table td.three {
 color: #008c8c;
}
 
.gameBox table td.four {
 color: crimson;
}
 
.gameBox table td.five {
 color: rgb(228, 91, 0);
}
 
.gameBox table td.six {
 color: darkorange;
}
 
.gameBox table td.seven {
 color: rgb(193, 196, 50);
}
 
.gameBox table td.eight {
 color: pink;
}
 
.main .footer {
 text-align: center;
}

javaScript代碼

核心代碼

?
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
function Game(tr, td, mineNum) {
  this.td = td;
  this.tr = tr;
  this.mineNum = mineNum; //存儲預設或設定的炸彈總數(shù),用于后續(xù)判斷是否勝利使用
  this.surplusMine = 0; //剩余雷數(shù)
  this.mineInfo = []; //用于接收隨機生成的雷的信息
  this.tdsArr = [] //存放單元格的信息
  this.isPlay = false; //是否開始玩
  this.openClass = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
  this.gameBox = document.getElementById("gameBox");
  this.table = document.createElement("table"); //生成table標簽
  this.footerNum = document.getElementById("surplusMine"); //剩余炸彈數(shù)量顯示框
 
 }
 
 Game.prototype.creatDom = function() { //創(chuàng)建游戲區(qū)域,在玩家第一次點擊游戲區(qū)域的時候執(zhí)行
  this.table.oncontextmenu = function() { return false }; //清除默認右鍵單機事件
  for (var i = 0; i < this.gameBox.children.length; i++) { //為防止重新開始游戲時,重復生成多個table,在添加之前先刪除之前的
   var childNod = this.gameBox.children[i];
   this.gameBox.removeChild(childNod);
  }
 
  for (var i = 0; i < this.tr; i++) {
   var tr = document.createElement("tr");
   this.tdsArr[i] = []; //為每一行生成一個數(shù)組
 
   for (var j = 0; j < this.td; j++) {
    var td = document.createElement("td");
    tr.appendChild(td); //將生成的td插入到tr中
    this.tdsArr[i][j] = td;
    td.info = { //info屬性包括了單元格的所有信息,很重要
     type: "number", //格子類型,用于判斷是否時炸彈
     x: i, //行
     y: j, //列
     value: 0, //當該格子周圍有炸彈時顯示該數(shù)值,生成炸彈的時候會++
     isOpen: false, //判斷該單元格是否被打開
     isFlag: false //判斷是否有標記flag
    }
   }
   this.table.appendChild(tr); //見tr插入到table中
  }
  this.gameBox.appendChild(this.table);
 }
 
 Game.prototype.creatMine = function(event, target) { //生成炸彈,該方法會在用戶第一次點擊棋盤的時候執(zhí)行一次
 
  var This = this;
  for (var i = 0; true; i++) { //隨機生成炸彈,生成扎當數(shù)與設定扎當書mineNum相同時終止循環(huán)
   var randomX = Math.floor(Math.random() * this.tr), //隨機生成炸彈的行數(shù)
    randomY = Math.floor(Math.random() * this.td); //隨機生成炸彈的列數(shù)
   // console.log(randomX + " " + randomY)
   if (target.info.x != randomX || target.info.y != randomY) { //保證第一次點擊的時候不是炸彈
    if (this.tdsArr[randomX][randomY].info.type != "mine") { //保證每次生成的雷的位置不重復
 
     this.tdsArr[randomX][randomY].info.type = "mine"; //單元格更改屬性為雷
     this.surplusMine++; //生成雷的數(shù)量+1
     this.mineInfo.push(this.tdsArr[randomX][randomY]); //將生成的雷的信息存放到this變量中,方便后續(xù)使用
 
    }
    if (this.surplusMine >= this.mineNum) { //當生成的炸彈數(shù)量等于設定的數(shù)量后跳出循環(huán)
     break;
    }
   }
  }
 
  //為每個炸彈周圍的方格添加數(shù)字
  for (var i = 0; i < this.mineInfo.length; i++) {
   var around = this.getAround(this.mineInfo[i], This); //獲取每個炸彈的周圍方格
   // console.log(this.getAround(this.mineInfo[i], This))
 
   for (var j = 0; j < around.length; j++) { //將周圍每個方格的value++
    around[j].info.value += 1;
   }
  }
 
 
 }
 
 Game.prototype.getAround = function(thisCell, This) { //獲取某個方格的周圍非炸彈方格,需要傳遞一個單元格dom元素,Game的this
  var x = thisCell.info.x, //行
   y = thisCell.info.y, //列
   result = [];
  // x-1,y-1  x-1,y  x-1,y+1
  // x,y-1   x,y   x,y+1
  // x+1,y-1  x+1y  x+1,y+1
  for (var j = x - 1; j <= x + 1; j++) {
   for (var k = y - 1; k <= y + 1; k++) {
    if ( //游戲區(qū)域的邊界,行數(shù)x和列數(shù)y不能為負數(shù),且不能超過設定的行數(shù)和列數(shù)
     j < 0 ||
     k < 0 ||
     j > (This.tr - 1) ||
     k > (This.td - 1) ||
     //同時跳過自身和周邊是雷的方格
     This.tdsArr[j][k].info.type == "mine" ||
     (j == x && k == y)
 
    ) {
     continue; //滿足上述條件是則跳過當此循環(huán);
    } else {
     result.push(This.tdsArr[j][k]) //將符合的單元格push到result中返回
    }
   }
  }
  return result;
 }
 
 Game.prototype.lifeMouse = function(event, target) { //左鍵點擊事件
  var This = this; //用變量的方式將Game的this傳遞到函數(shù)中
  var noOpen = 0; //沒有被打開的格子數(shù)量
  if (!target.info.isFlag) { //表示該必須沒有被右鍵標記才能鼠標左擊
   if (target.info.type == "number") { //是數(shù)字時,則可視化
 
    function getAllZero(target, This) { //遞歸函數(shù)
     // console.log(target.info)
     if (target.info.isFlag) { //當這個單元格之前有被標記過flag時,則將剩余炸彈數(shù)+1
      This.surplusMine += 1;
      target.info.isFlag = false; //單元格被打開后初始化flag
     }
     if (target.info.value == 0) { //等于格子的value等于0的時候
 
      target.className = This.openClass[target.info.value]; //可視化
 
      target.info.isOpen = true; //表示該單元格被打開
 
      var thisAround = This.getAround(target, This); //獲取該單元格周圍的格子信息
 
      for (var i = 0; i < thisAround.length; i++) {
       // console.log(thisAround[i].info.isOpen)
       if (!thisAround[i].info.isOpen) { //遞歸的條件,當格子的open為true時不執(zhí)行
 
        getAllZero(thisAround[i], This) //執(zhí)行遞歸
       }
 
      }
 
     } else {
      target.innerHTML = target.info.value;
      target.className = This.openClass[target.info.value]; //可視化
      target.info.isOpen = true; //表示單元格被打開
      target.info.isFlag = false; //單元格被打開后初始化flag
 
     }
    }
 
    getAllZero(target, This); //首次執(zhí)行
 
    //每次鼠標左鍵點擊的時候都需要檢查一下沒有被打開的方格數(shù)量,每有一個則noOpen++
    for (var i = 0; i < this.tr; i++) {
     for (var j = 0; j < this.tr; j++) {
      if (this.tdsArr[i][j].info.isOpen == false) {
       noOpen++;
      }
     }
 
    }
    //當noOpen的數(shù)量與炸彈數(shù)量相同時,說明剩余的方格全是雷,游戲通過
    if (noOpen == this.mineNum) {
     console.log(noOpen)
     this.gameWin();
    }
 
   } else { //點擊到了炸彈,游戲結束
    this.gameOver(target)
   }
  }
 
 
 
 }
 
 Game.prototype.rightMouse = function(target) { //鼠標右鍵點擊執(zhí)行
  if (!target.info.isOpen) {
   if (!target.info.isFlag) { //標記
    target.className = "targetFlag"; //顯示旗幟
    target.info.isFlag = true; //表示該方格已經(jīng)被標記
    this.surplusMine -= 1; //每標記一個方格,剩余炸彈數(shù)量-=1
    // console.log(this.surplusMine)
   } else { //取消標記
    target.className = ""; //去掉旗幟
    target.info.isFlag = false;
    this.surplusMine += 1;
    // console.log(this.surplusMine)
 
   }
 
   var isWin = true;
   if (this.surplusMine == 0) { //標記完所有flag時,遍歷所有單元格
    // console.log(this.mineInfo.length)
    for (var i = 0; i < this.mineInfo.length; i++) {
     console.log(this.mineInfo[i].info.isFlag)
     if (!this.mineInfo[i].info.isFlag) { //檢查每個雷的isFlag屬性是否被標記,只要有一個為false則輸?shù)粲螒?/code>
      isWin = false;
      this.gameOver(target, 1);
      break;
     }
    }
    isWin ? this.gameWin(1) : 0; //三目運算符號
   }
 
 
   // if (this.surplusMine == 0) { //標記完所有flag時,遍歷所有單元格
   //  for (var i; i < this.tr; i++) {
   //   for (var j; j < this.td; j++) {
   //    if()
   //   }
 
   //  }
   // }
  }
 }
 
 Game.prototype.gameOver = function(target, code) { //游戲結束,code為觸發(fā)代碼,當旗用完了時為1,點擊到炸彈為0
  // console.log(this.mineInfo)
  var mineInfoLen = this.mineInfo.length;
  for (var i = 0; i < mineInfoLen; i++) { //顯示每個雷的位置
   this.mineInfo[i].className = "mine";
  }
  this.table.onmousedown = false; //取消鼠標事件
 
  if (code) {
   alert("旗幟用完了,沒有排除所有雷,游戲結束")
  } else {
   target.className = "targetMine"; //觸發(fā)雷標紅色
   alert("你被炸彈炸死了,游戲結束")
  }
 
 }
 
 Game.prototype.gameWin = function(code) { //游戲勝利
  if (code) {
   alert("你成功標記所有地雷,游戲通過")
  } else {
   alert("你找到了所有安全區(qū)域,游戲通過")
  }
  this.table.onmousedown = false;
 
 
 }
 
 Game.prototype.play = function() {
  var This = this; //需要將this傳遞到事件函數(shù)中使用
  this.table.onmousedown = function(event) {
   event = event || window.event; //兼容IE
   target = event.target || event.srcElement //兼容IE
 
   if (!this.isPlay) { //首次點擊初始化棋盤,隨機生成炸彈
    this.isPlay = true;
    This.creatMine(event, target);
   }
 
   if (event.button == 0) { //鼠標左鍵點擊時執(zhí)行
    This.lifeMouse(event, target);
 
   } else if (event.button == 2) { //右鍵點擊執(zhí)行
    This.rightMouse(target)
   }
   This.footerNum.innerHTML = This.surplusMine; //每次點擊右鍵,刷新頁面下方的剩余雷數(shù)
  }
 }
 
 Game.prototype.tablePos = function() { //將table居中顯示
  var width = this.table.offsetWidth,
   height = this.table.offsetHeight;
  // console.log(this.table.offsetWidth)
  this.table.style.width = width + "px ";
  this.table.style.height = height + "px "
 
 
 }
 
 
 function addEvent(elem, type, handle) { //添加事件函數(shù)
  if (elem.addEventListener) { //w3c標準
   elem.addEventListener(type, handle, false);
  } else if (elem.attachEvent) { //IE9及以下
   elem.attachEvent("on" + type, function() {
    handle.call(elem);
   })
  } else { //其他情況
   elem["on" + type] = handle;
  }
 }
 
 Game.prototype.setDegree = function() { //調(diào)整難度
  var button = document.getElementsByTagName("button");
 
  addEvent(button[0], "click", function() { //簡單
   var game = new Game(10, 10, 10);
   game.creatDom();
   game.play();
   game.tablePos();
  });
 
  addEvent(button[1], "click", function() { //一般
   var game = new Game(16, 16, 50);
   game.creatDom();
   game.play();
   game.tablePos();
  });
 
  addEvent(button[2], "click", function() { //困難
   var game = new Game(30, 30, 125);
   game.creatDom();
   game.play();
   game.tablePos();
  });
 
 
 }
 
 // 默認棋盤
 var game = new Game(10, 10, 10);
 game.creatDom();
 game.play();
 game.tablePos();
 game.setDegree()

總結一下,該游戲個人覺得難點有4個:

  • 沒有思路,在bilibili看了一個教學視頻,但是比較難理解,在原有基礎上增加了自己的一些想法
  • 遞歸
  • 獲取某一個方格周圍的八個方格
  • 多層的if嵌套和循環(huán)

缺點:

  • 性能不佳,存在大量for循環(huán),且沒有優(yōu)化
  • 某些時候界面顯示的剩余炸彈數(shù)量不準確(已修復)
  • 代碼冗余較多

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/weixin_47582190/article/details/110186059

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 高清在线一区二区 | 黄色动漫在线观看 | 日韩欧美一级片在线观看 | 欧美精品一区二区久久 | 国产欧美日韩综合精品一区二区 | 亚洲免费精品 | 国产视频1区 | 欧美 日韩 中文 | 高清一区二区 | 鲁管视频 | 亚洲精品成人悠悠色影视 | 久久精品| 亚洲国产精品久久久久久 | 国产精品久久久久久亚洲影视 | 97久久精品午夜一区二区 | 亚洲在线| 中文字幕在线影院 | 日本久久香蕉 | 日韩精品一区二区三区四区 | 黄视频| 一区视频在线 | 国产精品久久久久久久久久东京 | 国产中文字幕在线播放 | 成人性生交大片免费看网站 | 国产精品一区二区三区免费 | 国产激情网址 | 亚洲视频在线观看免费 | 欧美日本韩国一区二区 | 亚洲不卡高清视频 | 欧美一区二区三区电影 | 欧美日韩久 | 日本久久精品视频 | 精品国产乱码久久久久久久 | 久久精品国产一区二区三区不卡 | 亚洲精品一区二区三区蜜桃下载 | 精品久久久久久 | 日本在线免费观看视频 | 精品久久99| 国产成人在线一区二区 | 亚洲综合在线播放 | 一区二区三区四区免费看 |