vue3开发扫雷游戏,支持调整难度,支持计时

闲来练习练习js,写了个扫雷游戏,直接拿去复制粘到自己本地某个html文件里就能运行,记得把vue加载地址改成线上的~~

有空了可以再加上计分板

运行起来长下面这样

 直接上代码

 

  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>扫雷v1.0</title>
  7     <!-- <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> -->
  8     <script src="vue.global-v3.5.12.js"></script>
  9     <style>
 10         *{ margin:0; padding:0; font-size:14px; color:#333;}
 11         body{ padding: 20px; }
 12         .container{
 13             background-color: #efefef;
 14             padding: 10px;
 15             display: flex;
 16         }
 17         .warper{
 18             padding:1px;
 19             background-color: #cfcfcf;
 20         }
 21         .row{
 22             display: flex;
 23             flex-direction: row;
 24         }
 25         .cell{
 26             width: 30px;
 27             text-align: center;
 28             height: 30px;
 29             line-height: 30px;
 30             background-color: #dfdfdf;
 31             border: 2px solid #cfcfcf;
 32         }
 33         .cell:hover{
 34             border-color:rgb(250, 179, 112);
 35             background-color: rgb(231, 202, 164);
 36             cursor: pointer;
 37         }
 38         .board{
 39             width: 170px;
 40             margin-right: 20px;
 41         }
 42         .config-item{
 43             padding:10px;
 44         }
 45         .config-item .btn{
 46             margin-right: 20px;
 47         }
 48         .cell.clicked-0{ background-color: #f7f7f7; }
 49         .cell.clicked-1{ background-color: #fff0f0; }
 50         .cell.clicked-2{ background-color: #ffdbdb; }
 51         .cell.clicked-3{ background-color: #ffc3c3; }
 52         .cell.clicked-4{ background-color: #ffa3a3; }
 53         .cell.clicked-5{ background-color: #ff9898; color: white; }
 54         .cell.clicked-6{ background-color: #ff6f6f; color: white; }
 55         .cell.clicked-7{ background-color: #ff5a5a; color: white; }
 56         .cell.clicked-8{ background-color: #ff2424; color: white; }
 57         .cell.boom{ background-color: #ffffff; color: rgb(255, 0, 0); font-size:22px;}
 58         .cell.flag{ border-color: #fdafaf; }
 59     </style>
 60 </head>
 61 <body>
 62     <div class="container" id="app">
 63         <div class="board">
 64             <div class="config-item">
 65                 <h3>请点击START开始游戏</h3>
 66                 <h3>点击RESET重置游戏</h3>
 67             </div>
 68             <div class="config-item">
 69                 <form>
 70                     <label for="rowsindex">难度</label>
 71                     <select v-model="currentLevel" @change="handleLevelChange">
 72                         <option v-for="(level, index) in levels" :key="index" :value="level">{{ level.name }}</option>
 73                     </select>
 74                 </form>
 75             </div>
 76             <div class="config-item">
 77                 用时 <strong>{{ costTime }}</strong>
 78             </div>
 79             <div class="config-item">
 80                 <button class="btn" @click="resetGame">RESET</button>
 81                 <button class="btn" :disabled="gameStatus == 'start'" @click="startGame">START</button>
 82             </div>
 83         </div>
 84         <div class="warper">
 85             <div class="row" v-for="(row, indexRow) in cells" :key="indexRow">
 86                 <div 
 87                     v-for="(column, indexColumn) in cells[indexRow]" 
 88                     :key="indexColumn" 
 89                     :class="'cell '+column.style" 
 90                     @click="handleCellClick(indexRow, indexColumn)"
 91                     @click.right.prevent="handleCellFlag(indexRow, indexColumn)"
 92                 >
 93                     {{ column.text }}
 94                 </div>
 95             </div>
 96         </div>
 97     </div>
 98 
 99 <script>
100     const { createApp, ref, computed, nextTick } = Vue
101     createApp({
102         setup() {
103             const boomValue = 332962963;
104             const levels = ref([
105                 { name: '黑铁', rowsindex: 8, columnsindex: 8, boomCount: 6 },
106                 { name: '青铜', rowsindex: 10, columnsindex: 10, boomCount: 11 },
107                 { name: '白银', rowsindex: 14, columnsindex: 14, boomCount: 20 },
108                 { name: '黄金', rowsindex: 16, columnsindex: 16, boomCount: 28 },
109                 { name: '白金', rowsindex: 20, columnsindex: 20, boomCount: 44 },
110                 { name: '钻石', rowsindex: 24, columnsindex: 24, boomCount: 60 },
111                 { name: '大师', rowsindex: 30, columnsindex: 30, boomCount: 95 },
112                 { name: '王者', rowsindex: 36, columnsindex: 36, boomCount: 120 }
113             ]);
114             const currentLevel = ref(levels.value[0]);
115 
116             let rowsindex = currentLevel.value.rowsindex;
117             let columnsindex = currentLevel.value.columnsindex;
118             let boomCount = currentLevel.value.boomCount;
119 
120             const start = 0;
121             let end = computed(()=>{
122                 return rowsindex*columnsindex-1;
123             })
124             const gameStatus = ref("stop");
125             const costTime = ref("00:00:00");
126             let timer;
127             let startTime = 0;
128 
129             const cells = ref([]);
130             let randoms = [];
131             let rightsZero = [];
132 
133             const startGame = () => {
134                 gameStatus.value = "start";
135                 startTimer();
136                 initGame();
137             }
138 
139             const resetGame = () => {
140                 gameStatus.value = "stop";
141                 stopTimer();
142                 resetTimer();
143                 initGame();
144             }
145 
146             const handleLevelChange = () => {
147                 console.log(currentLevel.value)
148                 resetGame();
149             }
150 
151             const handleCellClick = (i, j) => {
152                 if(gameStatus.value!=='start'){
153                     return;
154                 }
155 
156                 if(cells.value[i][j].value != boomValue){
157                     rightsZero = [];
158                     clickRights(i, j);
159                     for(let i=0; i<rightsZero.length; i++){
160                         let [rowIndex, columnIndex] = getRowIndexColumnIndex(rightsZero[i]);
161                         cells.value[rowIndex][columnIndex] = getCellClickedInfo(rowIndex, columnIndex);
162                     }
163                     ifWin();
164                 }else{
165                     cells.value[i][j] = {style:'boom', clicked: true, text: '⭕️', value: boomValue};
166                     finishGame();
167                 }
168             }
169 
170             const handleCellFlag = (i, j) => {
171                 if(gameStatus.value!=='start'){
172                     return;
173                 }
174                 
175                 let cell = cells.value[i][j];
176                 if(cell.clicked){
177                     return;
178                 }
179                 if(cell.style === 'flag'){
180                     cells.value[i][j] = {style:'unClicked', clicked: false, text: '', value: cell.value};
181                 }else{
182                     cells.value[i][j] = {style:'flag', clicked: false, text: '🚩', value: cell.value};
183                     ifWin();
184                 }
185             }
186 
187             const ifWin = () => {
188                 let flagCount = 0;
189                 for(let i=0; i<rowsindex; i++){
190                     for(let j=0; j<columnsindex; j++){
191                         if(cells.value[i][j].style === 'flag'){
192                             flagCount++;
193                         }
194                     }
195                 }
196                 let rightCount = 0;
197                 for(let i=0; i<rowsindex; i++){
198                     for(let j=0; j<columnsindex; j++){
199                         if(cells.value[i][j].value === boomValue && cells.value[i][j].style == 'flag'){
200                             rightCount++;
201                         }
202                     }
203                 }
204                 if(flagCount === boomCount && flagCount === rightCount){
205                     winGame();
206                 }
207             }
208 
209             const clickRights = (i, j) => {
210                 let index = i*rowsindex+j;
211                 if(rightsZero.indexOf(index) !== -1){
212                     return;
213                 }
214                 rightsZero.push(index);
215                 if(cells.value[i][j].value === 0){
216                     //
217                     if(i - 1 >= 0 && cells.value[i-1][j].value === 0 && cells.value[i-1][j].clicked === false && cells.value[i-1][j].style !== 'flag'){
218                         clickRights(i-1, j);
219                     }
220                     //
221                     if(i + 1 < rowsindex && cells.value[i+1][j].value === 0 && cells.value[i+1][j].clicked === false && cells.value[i+1][j].style !== 'flag'){
222                         clickRights(i+1, j);
223                     }
224                     //
225                     if(j - 1 >= 0 && cells.value[i][j-1].value === 0 && cells.value[i][j-1].clicked === false && cells.value[i][j-1].style !== 'flag'){
226                         clickRights(i, j-1);
227                     }
228                     //
229                     if(j + 1 < columnsindex && cells.value[i][j+1].value === 0 && cells.value[i][j+1].clicked === false && cells.value[i][j+1].style !== 'flag'){
230                         clickRights(i, j+1);
231                     }
232                 }
233             }
234 
235             const getCellClickedInfo = (row, index) => {
236                 let cell = cells.value[row][index];
237                 return {style:'clicked-'+cell.value, clicked: true, text: cell.value === 0 ? '' : cell.value, value: cell.value};
238             }
239 
240             const finishGame = () => {
241                 gameStatus.value = 'stop';
242                 setTimeout(()=>{
243                     stopTimer();
244                     alert('Game Over');
245                     showAllBoom();
246                     // initGame();
247                 }, 50)
248             }
249 
250             const winGame = () => {
251                 gameStatus.value = 'stop';
252                 setTimeout(()=>{
253                     stopTimer();
254                     alert('You Win');
255                     // initGame();
256                 }, 50)
257             }
258 
259             const showAllBoom = () => {
260                 for(let i=0; i<rowsindex; i++){
261                     for(let j=0; j<columnsindex; j++){
262                         const cell = cells.value[i][j];
263                         if(cell.value === boomValue){
264                             cells.value[i][j] = {style:'boom', clicked: true, text: '⭕️', value: boomValue};
265                         }else{
266                             cells.value[i][j] = {style:'clicked-'+cell.value, clicked: true, text: cell.value === 0 ? '' : cell.value, value: cell.value};
267 
268                         }
269                     }
270                 }
271             }
272 
273             const initGame = () => {
274                 console.log('initGame')
275                 rowsindex = currentLevel.value.rowsindex;
276                 columnsindex = currentLevel.value.columnsindex;
277                 boomCount = currentLevel.value.boomCount;
278 
279                 cells.value = [];
280                 randoms = [];
281                 for(let i=0; i<rowsindex; i++){
282                     cells.value[i] = [];
283                     for(let j=0; j<columnsindex; j++){
284                         cells.value[i][j] = {style:'unClicked', clicked: false, text: '', value: 0};
285                     }
286                 }
287                 for(let i=0; i<boomCount; i++){
288                     getUniqueRandoms(randoms);
289                 }
290                 for(let i=0; i<randoms.length; i++){
291                     let [rowIndex, columnIndex] = getRowIndexColumnIndex(randoms[i]);
292                     cells.value[rowIndex][columnIndex].value = boomValue;
293                 }
294                 for(let i=0; i<rowsindex; i++){
295                     for(let j=0; j<columnsindex; j++){
296                         if(cells.value[i][j].value !== boomValue){
297                             let count = 0;
298                             for(let x=i-1; x<=i+1; x++){
299                                 for(let y=j-1; y<=j+1; y++){
300                                     if(x>=0 && x<rowsindex && y>=0 && y<columnsindex && cells.value[x][y].value === boomValue){
301                                         count++;
302                                     }
303                                 }
304                             }
305                             cells.value[i][j].value = count;
306                         }
307                     }
308                 }
309             }
310 
311             const getRandoms = () => {
312                 return parseInt(Math.random()*(start+1-end.value) + end.value);
313             }
314 
315             const getUniqueRandoms = (randoms) => {
316                 let random = getRandoms();
317                 if(randoms.indexOf(random) === -1){
318                     randoms.push(random);
319                 }else{
320                     getUniqueRandoms(randoms);
321                 }
322             }
323 
324             const getRowIndexColumnIndex = (index) => {
325                 let rowIndex = parseInt(index / columnsindex);
326                 let columnIndex = index % columnsindex;
327                 return [rowIndex, columnIndex];
328             }
329 
330             const startTimer = () => {
331                 startTime = new Date().getTime();
332                 timer = setInterval(()=>{
333                     costTime.value = getCostTime();
334                 }, 1000)
335             }
336 
337             const stopTimer = () => {
338                 clearInterval(timer);
339             }
340 
341             const resetTimer = () => {
342                 startTime = 0;
343                 costTime.value = '00:00:00';
344             }
345 
346             const getCostTime = () => {
347                 let now = new Date().getTime();
348                 let diff = parseInt((now - startTime) / 1000);
349                 let h = parseInt(diff / 3600);
350                 let hStr = h < 10? '0'+h : h;
351                 let m = parseInt((diff % 3600) / 60);
352                 let mStr = m < 10? '0'+m : m;
353                 let s = diff % 60;
354                 let sStr = s < 10? '0'+s : s;
355                 return hStr+':'+mStr+':'+sStr;
356             }
357 
358             initGame();
359             
360             return {
361                 cells,
362                 costTime,
363                 gameStatus,
364                 rowsindex,
365                 columnsindex,
366                 levels,
367                 currentLevel,
368                 handleCellClick,
369                 handleCellFlag,
370                 resetGame,
371                 startGame,
372                 handleLevelChange
373             }
374         }
375     }).mount('#app')
376 </script>
377 </body>
378 </html>

 

posted @ 2024-11-13 16:04  红岸  阅读(3)  评论(0编辑  收藏  举报