javascript实现扫雷游戏
Posted Sunshine
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript实现扫雷游戏相关的知识,希望对你有一定的参考价值。
html代码:
<div id="mine"> <div class="level"> <button type="button">初级</button> <button type="button">中级</button> <button type="button">高级</button> <button type="button">重新开始</button> </div> <div class="gameBox"></div> <div class="info"> 剩余雷数:<span class="mineNum"></span> </div> </div>
css代码:
1 #mine { 2 margin: 50px auto; 3 } 4 .level { 5 text-align: center; 6 margin-bottom: 10px; 7 } 8 .level button { 9 padding: 5px 15px; 10 background-color: cornflowerblue; 11 border: none; 12 color: #fff; 13 border-radius: 3px; 14 outline: none; 15 cursor: pointer; 16 } 17 .level button.active { 18 background-color: #00abff; 19 } 20 .info { 21 margin-top: 10px; 22 text-align: center; 23 } 24 table { 25 border-spacing: 1px; 26 background: #929196; 27 margin: 0 auto; 28 } 29 td { 30 padding: 0; 31 width: 20px; 32 height: 20px; 33 background: #ccc; 34 border: 2px solid; 35 border-color: #fff #a1a1a1 #a1a1a1 #fff; 36 37 text-align: center; 38 line-height: 20px; 39 font-weight: bold; 40 } 41 td.zero { 42 border-color: #D9D9D9; 43 background: #D9D9D9; 44 } 45 td.one { 46 border-color: #D9D9D9; 47 background: #D9D9D9; 48 color: #0332fe; 49 } 50 td.two { 51 border-color: #D9D9D9; 52 background: #D9D9D9; 53 color: #019f02; 54 } 55 td.three { 56 border-color: #D9D9D9; 57 background: #D9D9D9; 58 color: #ff2600; 59 } 60 td.four { 61 border-color: #D9D9D9; 62 background: #D9D9D9; 63 color: #93208f; 64 } 65 td.five { 66 border-color: #D9D9D9; 67 background: #D9D9D9; 68 color: #019f02; 69 } 70 td.six { 71 border-color: #D9D9D9; 72 background: #D9D9D9; 73 color: #ff3fff; 74 } 75 td.seven { 76 border-color: #D9D9D9; 77 background: #D9D9D9; 78 color: #3fffbf; 79 } 80 td.eight { 81 border-color: #D9D9D9; 82 background: #D9D9D9; 83 color: #22ee0f; 84 } 85 .mine { 86 background: #d9d9d9 url(./mine.png) no-repeat center; 87 background-size: cover; 88 } 89 .flag { 90 background: #ccc url(./flag.png) no-repeat center; 91 background-size: cover; 92 }
javascript代码:
1 function Mine(tr, td, mineNum) { 2 this.tr = tr; //行数 3 this.td = td; //列数 4 this.mineNum = mineNum; //雷的数量 5 6 this.squares = []; //存储所有方块的信息,他是一个二维数组,按行列的顺序摆放,存储都使用行列形式 7 this.tds = []; //存储所有单元格的DOM(二维数组) 8 this.surplusMine = mineNum; //剩余雷的数量 9 this.allRight = false; //右击标的小红旗是否全是雷,用来判断用户是否游戏成功 10 11 this.parent = document.querySelector(‘.gameBox‘); 12 13 14 } 15 16 //生成n格不重复的数字 17 Mine.prototype.randomNum = function() { 18 var square = new Array(this.tr * this.td), //先生成一个空数组,长度为格子的总数 19 len = square.length; 20 for (var i = 0; i < square.length; i++) { 21 square[i] = i; 22 } 23 square.sort(function() { 24 return 0.5 - Math.random() 25 }); 26 return square.slice(0, this.mineNum); 27 } 28 Mine.prototype.init = function() { 29 var rn = this.randomNum(); //雷在格子里的位置 30 var n = 0; //用来找到格子对应的索引 31 for (var i = 0; i < this.tr; i++) { 32 this.squares[i] = []; 33 for (var j = 0; j < this.td; j++) { 34 // this.squares[i][j] = ; 35 36 //取一个方块在数组里的数据要使用行和列的形式去取, 37 //找方块周围的方块的时候要使用坐标的形式去取, 38 //行和列的形式跟坐标的形式 x,y 是刚好相反的 39 40 if (rn.indexOf(++n) != -1) { 41 //如果这个条件成立,说明现在循环到的这个索引在雷的数组中找到了,那就表示这个索引对应的是个雷 42 this.squares[i][j] = { 43 type: ‘mine‘, 44 x: j, 45 y: i 46 }; 47 } else { 48 this.squares[i][j] = { 49 type: ‘number‘, 50 x: j, 51 y: i, 52 value: 0 53 }; 54 } 55 } 56 } 57 58 59 this.updateNum(); 60 this.createDom(); 61 62 this.parent.oncontextmenu = function() { 63 return false; 64 } 65 66 //剩余雷数 67 this.mineNumDom = document.querySelector(‘.mineNum‘); 68 this.mineNumDom.innerHTML = this.surplusMine; 69 70 }; 71 72 //创建表格 73 Mine.prototype.createDom = function() { 74 var self = this; 75 var table = document.createElement(‘table‘); 76 77 for (var i = 0; i < this.tr; i++) { //行 78 var domTr = document.createElement(‘tr‘); 79 this.tds[i] = []; 80 81 for (var j = 0; j < this.td; j++) { //列 82 var domTd = document.createElement(‘td‘); 83 84 domTd.pos = [i, j]; //把格子对应的行和列存到格子身上,为了下面通过这个值去数组里取到对应的数据 85 domTd.onmousedown = function() { 86 self.play(event, this); //self 指的是实例对象, this指的是点击的那个td 87 }; 88 89 this.tds[i][j] = domTd; //这里是把所有创建的td都添加到数组中 90 91 // if (this.squares[i][j].type == ‘mine‘) { 92 // domTd.className = ‘mine‘; 93 // } 94 // if (this.squares[i][j].type == ‘number‘) { 95 // domTd.innerHTML = this.squares[i][j].value; 96 // } 97 98 99 domTr.appendChild(domTd); 100 } 101 table.appendChild(domTr); 102 } 103 this.parent.innerHTML = ‘‘; 104 this.parent.appendChild(table); 105 }; 106 107 //找某个方格周围的8个方格 108 Mine.prototype.getAround = function(square) { 109 var x = square.x; 110 var y = square.y; 111 var result = []; //把找到的格子的坐标返回出去--二维数组 112 113 114 //通过坐标去循环九宫格 115 for (var i = x - 1; i <= x + 1; i++) { 116 for (var j = y - 1; j <= y + 1; j++) { 117 if ( 118 i < 0 || //格子超出了左边的范围 119 j < 0 || //格子超出了上边的范围 120 i > this.td - 1 || //格子超出了右边的范围 121 j > this.tr - 1 || //格子超出了下边的范围 122 (i == x && j == y) || //当前循环到的格子是自己 123 this.squares[j][i].type == ‘mine‘ //周围的格子是个雷 124 ) { 125 continue; 126 } 127 128 result.push([j, i]); //要以行和列 129 } 130 } 131 return result; 132 }; 133 134 //更新所有的数字 135 Mine.prototype.updateNum = function() { 136 for (var i = 0; i < this.tr; i++) { 137 for (var j = 0; j < this.td; j++) { 138 //只更新的是雷周围的数字 139 if (this.squares[i][j].type == ‘number‘) { 140 continue; 141 } 142 143 var num = this.getAround(this.squares[i][j]); //获取到每一个雷周围的数字 144 145 for (var k = 0; k < num.length; k++) { 146 this.squares[num[k][0]][num[k][1]].value += 1; 147 } 148 } 149 } 150 } 151 152 153 Mine.prototype.play = function(ev, obj) { 154 var self = this; 155 if (ev.which == 1 && obj.className != ‘flag‘) { //后面的条件是为了限制用户标完小红旗后就不能够被左键点击 156 157 var curSquare = this.squares[obj.pos[0]][obj.pos[1]]; 158 var cl = [‘zero‘, ‘one‘, ‘two‘, ‘three‘, ‘four‘, ‘five‘, ‘six‘, ‘seven‘, ‘eight‘] 159 if (curSquare.type == ‘number‘) { 160 //用户点到的是数字 161 162 obj.innerHTML = curSquare.value; 163 obj.className = cl[curSquare.value]; 164 165 if (curSquare.value == 0) { 166 /* 167 用户点到了数字0 168 1/显示自己 169 2/找周围 170 1/显示四周(如果周围的值不为0, 那就显示到这里,不需要再找了 171 2/如果值为0 172 1/显示自己 173 2/找四周(如果四周的值不为0,那就显示到这里,不需要再找了) 174 */ 175 obj.innerHTML = ‘‘; //如果数字为0的话,不显示 176 function getAllZero(square) { 177 var around = self.getAround(square); //找到了周围的n个格子 178 179 for (var i = 0; i < around.length; i++) { 180 var x = around[i][0]; //行 181 var y = around[i][1]; //列 182 183 self.tds[x][y].className = cl[self.squares[x][y].value]; 184 185 if (self.squares[x][y].value == 0) { 186 //如果以某个格子为中心找到的格子值为0,那就需要接着调用函数 187 if (!self.tds[x][y].check) { 188 //给对应的td函数一个属性,这条属性用于决定这个格子有没有被找过 189 //如果找过的话,他的值就为true,下一次就不会再找了 190 self.tds[x][y].check = true; 191 getAllZero(self.squares[x][y]); 192 } 193 } else { 194 //如果以某个格子为中心找到的四周格子的值不为0, 那就把人家的数字显示出来 195 self.tds[x][y].innerHTML = self.squares[x][y].value; 196 } 197 } 198 } 199 getAllZero(curSquare); 200 } 201 } else { 202 this.gameOver(obj); 203 } 204 } 205 //用户点击 的 是右键 206 if (ev.which == 3) { 207 //如果右击的是一个数字,就不能点击 208 if (obj.className && obj.className != ‘flag‘) { 209 return; 210 } 211 obj.className = obj.className == ‘flag‘ ? ‘‘ : ‘flag‘; //切换class 212 213 if (this.squares[obj.pos[0]][obj.pos[1]].type == ‘mine‘) { 214 this.allRight = true; 215 } else { 216 this.allRight = false; 217 } 218 if (obj.className == ‘flag‘) { 219 this.mineNumDom.innerHTML = --this.surplusMine; 220 } else { 221 this.mineNumDom.innerHTML = ++this.surplusMine; 222 } 223 if (this.surplusMine == 0) { 224 //剩余的雷的数量为0 ,表示用户已经标完小红旗了,这时候要判断游戏是成功还是结束 225 if (this.allRight) { 226 alert(‘恭喜你,游戏通过‘); 227 } else { 228 alert(‘恭喜你,游戏失败‘); 229 this.gameOver(); 230 } 231 } 232 233 } 234 }; 235 236 //游戏失败函数 237 Mine.prototype.gameOver = function(clickTd) { 238 /* 239 1显示所有的雷 240 2/取消所有格子的点击事件 241 3/给点中的那个雷标上一个杠 242 */ 243 for (var i = 0; i < this.tr; i++) { 244 for (var j = 0; j < this.td; j++) { 245 if (this.squares[i][j].type == ‘mine‘) { 246 this.tds[i][j].className = ‘mine‘; 247 } 248 249 this.tds[i][j].onmousedown = null; 250 } 251 } 252 253 if (clickTd) { 254 clickTd.style.backgroundColor = ‘#f00‘; 255 } 256 257 258 } 259 260 //添加的是上面button的功能 261 var btns = document.querySelectorAll(‘.level button‘); 262 var mine = null; 263 var ln = 0; 264 var arr = [ 265 [9, 9, 10], 266 [16, 16, 40], 267 [28, 28, 90] 268 ]; 269 270 for(let i =0; i < btns.length-1; i ++) { 271 btns[i].onclick = function() { 272 btns[ln].className = ‘‘; 273 this.className = ‘active‘; 274 275 mine = new Mine(...arr[i]); 276 mine.init(); 277 ln = i; 278 } 279 } 280 btns[0].onclick(); //初始化一下 281 btns[3].onclick = function () { 282 mine.init(); 283 } 284 // var mine = new Mine(28, 28, 99); 285 286 // mine.init();
以上是关于javascript实现扫雷游戏的主要内容,如果未能解决你的问题,请参考以下文章