利用原生js做了一个扫雷
之前看了别人用js做的一个扫雷游戏,但是发现有一堆bug,还不能配置!!
想了一下,自己也做了一个原生js的扫雷游戏,目前还没发现bug,欢迎指出!
游戏主体稍微复杂点的就是递归做扩散(也还好)!
设置了可配置的棋牌和雷数量,并对对输入进行验证!
HTML 没啥好看的!
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 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>Document</title> 8 <link rel="stylesheet" href="demo.css"> 9 <script src="demo.js"></script> 10 </head> 11 <body> 12 <div class="control"> 13 <div class="configure"> 14 <div class="col"> 15 <span>行数:</span><input type="text" id="col" placeholder="默认为10" value=""> 16 </div> 17 <div class="row"> 18 <span>列数:</span><input type="text" id="row" placeholder="默认为10" value=""> 19 </div> 20 <div class="lei"> 21 <span>地雷:</span><input type="text" id="lei" placeholder="默认为10" value=""> 22 </div> 23 </div> 24 <div class="dis"> 25 <button id="begin">开始游戏</button> 26 <button id="again">重新开始</button> 27 <span class="save">安全区</span> 28 <span class="lei">地雷</span> 29 <span class="flag">地雷标记</span> 30 </div> 31 <div class="sore"> 32 <div class="time">TIME:<span id="time"></span></div> 33 <div class="residual">剩余地雷:<span id="leave"></span></div> 34 </div> 35 </div> 36 <div id="mysaolei"></div> 37 </body> 38 </html>
css 就这点!
1 * { 2 margin: 0; 3 padding: 0; 4 list-style: none 5 } 6 .control { 7 width: 1000px; 8 height: 150px; 9 position: relative; 10 left: 50%; 11 transform: translateX(-50%); 12 margin-top: 10px; 13 border: 1px solid silver; 14 border-radius: 2px; 15 } 16 .control .configure { 17 width: 300px; 18 height: 150px; 19 float: left; 20 } 21 .control .configure div{ 22 margin-top: 5px; 23 height: 40px; 24 line-height: 40px; 25 } 26 .control .configure div span { 27 font-size: 25px; 28 font-weight: 700; 29 margin-left: 10px; 30 } 31 .control .configure div input { 32 width: 100px; 33 font-size: 20px; 34 text-align: center; 35 } 36 .control .dis { 37 position: absolute; 38 width: 300px; 39 left: 50%; 40 margin-left: -150px; 41 } 42 .control .dis button { 43 position: absolute; 44 width: 200px; 45 height: 80px; 46 border-radius: 40px; 47 outline: 0px; 48 font-size: 35px; 49 font-weight: 700; 50 border: 1px solid silver; 51 margin-top: 10px; 52 margin-left: -100px; 53 left: 50%; 54 } 55 .control .dis button#again{ 56 display: none; 57 58 } 59 60 .control .dis span { 61 position: relative; 62 top: 110px; 63 display: inline-block; 64 font-weight: 600; 65 padding: 5px 10px; 66 border-radius: 5px; 67 68 } 69 .control .dis span.lei{ 70 background: red; 71 float: left; 72 margin-left: 30px; 73 } 74 .control .dis span.save{ 75 background: greenyellow; 76 margin-left: 20px; 77 } 78 .control .dis span.flag{ 79 background: yellow; 80 float: right; 81 margin-right: 30px; 82 83 } 84 .control .sore { 85 width: 300px; 86 float: right; 87 } 88 .control .sore .time { 89 font-size: 40px; 90 margin-top: 30px; 91 } 92 .control .sore .residual { 93 font-size: 20px; 94 margin-top: 30px; 95 margin-left: 20px; 96 } 97 98 99 100 #mysaolei { 101 /* width: 50%; */ 102 /* height: 200px; */ 103 position: relative; 104 left: 50%; 105 transform: translateX(-50%); 106 margin-top: 20px; 107 border: 1px solid silver; 108 border-radius: 2px; 109 margin-bottom: 30px; 110 } 111 #mysaolei div { 112 position: absolute; 113 width: 23px; 114 height: 23px; 115 line-height: 23px; 116 font-size: 16px; 117 text-align: center; 118 border: 1px solid silver; 119 border-radius: 2px; 120 } 121 #mysaolei div.lei{ 122 background: red; 123 } 124 #mysaolei div.save{ 125 background: greenyellow; 126 } 127 #mysaolei div.flag{ 128 background: yellow; 129 130 }
重点js!
1 window.onload = function(){ 2 var col , 3 row , 4 lei_n , // 雷数 5 lei_flag = 0, // 类标记数量 6 mount = 0, 7 save_num = 0, // 不是雷被点开的数量 8 setTime, 9 useTime = 0, 10 lock = true; 11 map = []; 12 13 var mysaolei = document.getElementById("mysaolei"), // 存储地图位置信息 14 begin = document.getElementById("begin"), 15 again = document.getElementById("again"), 16 time = document.getElementById("time"), 17 leave = document.getElementById("leave"), 18 col_v = document.getElementById("col"), 19 row_v = document.getElementById("row"), 20 lei_v = document.getElementById("lei"); 21 22 var reg = /^\d+$/; 23 24 col_v.addEventListener('input',function(){ 25 if(reg.test(col_v.value) ){ 26 if(col_v.value < 1 ){ 27 col_v.value = 1; 28 }else if(col_v.value > 40){ 29 col_v.value = 40; 30 } 31 }else{ 32 col_v.value = ''; 33 } 34 }) 35 row_v.addEventListener('input',function(){ 36 if(reg.test(row_v.value) ){ 37 if(Number(row_v.value) < 1 ){ 38 row_v.value = 1; 39 }else if(Number(row_v.value) > 30){ 40 row_v.value = 30; 41 } 42 }else{ 43 row_v.value = ''; 44 } 45 }) 46 lei_v.addEventListener('input',function(){ 47 if(reg.test(lei_v.value) ){ 48 if(Number(lei_v.value) < 1 ){ 49 lei_v.value = 1; 50 }else if(Number(lei_v.value) > 1200){ 51 lei_v.value = 1200; 52 } 53 }else{ 54 lei_v.value = ''; 55 } 56 }) 57 begin.onclick = function(){ 58 col = col_v.value || 10; 59 row = row_v.value || 10; 60 lei_n = lei_v.value || 10; 61 if((col * row) < lei_n){ 62 alert("你TM要这么多雷炸死谁! 格子都放不下了!赶紧少放点雷!"); 63 return false; 64 } 65 this.style.display = "none"; 66 again.style.display = "block"; 67 init(); 68 69 } 70 again.onclick = function(){ 71 col = col_v.value || 10; 72 row = row_v.value || 10; 73 lei_n = lei_v.value || 10; 74 if((col * row) < lei_n){ 75 alert("你TM要这么多雷炸死谁! 格子都放不下了!赶紧少放点雷!"); 76 return false; 77 } 78 map = []; 79 lei_flag = 0; 80 save_num = 0; 81 mount = 0; 82 useTime = 0; 83 clearInterval(setTime); 84 mysaolei.innerHTML = ''; 85 init(); 86 } 87 88 89 90 91 92 93 94 95 96 function createMap(){ // 创建地图数组 97 for(var i = 0; i < row; i ++){ 98 map[i] = []; 99 for(var j = 0; j < col; j ++){ 100 map[i][j] = {'x' : i ,'y' : j , 'num' : 0 , 'flag' : false , 'lei': false} 101 } 102 } 103 createLei(); 104 computeNum(); 105 } 106 107 function createLei(){ 108 lei_map = 0; // 雷以创建个数 109 for(;;){ 110 var randomX = parseInt(Math.random() * row); 111 var randomy = parseInt(Math.random() * col); 112 if(lei_map == lei_n){ 113 return 114 }else if(!map[randomX][randomy].lei){ 115 map[randomX][randomy].lei = true; 116 lei_map ++; 117 } 118 } 119 } 120 121 function computeNum(){ // 数组负值 122 for(var i = 0; i < row; i ++){ 123 for(var j = 0; j < col; j ++){ 124 if(map[i][j].lei){ 125 if(map[i-1] && map[i-1][j-1] && !map[i-1][j-1].lei){map[i-1][j-1].num ++}; 126 if(map[i-1] && map[i-1][j] && !map[i-1][j].lei ){map[i-1][j].num ++}; 127 if(map[i-1] && map[i-1][j+1] && !map[i-1][j+1].lei){map[i-1][j+1].num ++}; 128 if(map[i] && map[i][j-1] && !map[i][j-1].lei ){map[i][j-1].num ++}; 129 if(map[i] && map[i][j+1] && !map[i][j+1].lei ){map[i][j+1].num ++}; 130 if(map[i+1] && map[i+1][j-1] && !map[i+1][j-1].lei){map[i+1][j-1].num ++}; 131 if(map[i+1] && map[i+1][j] && !map[i+1][j].lei ){map[i+1][j].num ++}; 132 if(map[i+1] && map[i+1][j+1] && !map[i+1][j+1].lei){map[i+1][j+1].num ++}; 133 } 134 } 135 } 136 } 137 138 function mapInBox(){ // 地图展示 139 mysaolei.style.width = col * 27 + 2 + 'px'; 140 mysaolei.style.height = row * 27 + 2 + 'px'; 141 mysaolei.oncontextmenu = function(){return false}; // 禁止右键菜单事件 142 for(var i = 0; i < row; i ++){ 143 for(var j = 0; j < col; j ++){ 144 var temp = createSquare(map[i][j]); 145 mysaolei.appendChild(temp); 146 } 147 } 148 } 149 150 function createSquare(obj){ // 创建单元格 151 var square = document.createElement('div'); 152 square.style.top = obj.x * 25 + (obj.x + 1) * 2 + 'px'; 153 square.style.left = obj.y * 25 + (obj.y + 1) * 2 + 'px'; 154 square.num = obj.num; 155 square.flag = obj.flag; 156 square.lei = obj.lei; 157 square.index = [obj.x, obj.y]; 158 square.eq = obj.x * row + obj.y; 159 square.addEventListener('mousedown',click); 160 return square; 161 } 162 163 function click(event){ // 点击事件 164 if(!lock){return false} 165 var e = event || window.event; 166 if(e.which == 1){ 167 leftClick(this); 168 } 169 if(e.which == 3) { 170 rightClick(this) 171 } 172 } 173 function leftClick(self){ // 左键事件 174 if(!self.className){ 175 if(self.lei){ 176 self.classList.add("lei"); 177 gameOver(); 178 }else{ 179 // console.log(self.eq); 180 var x = self.index[0]; 181 var y = self.index[1]; 182 self.classList.add("save"); 183 save_num ++ ; 184 if(self.num !=0 ){ 185 self.innerHTML = self.num; 186 }else if (self.num == 0){ 187 for( var i = x - 1 ; i < x + 2; i ++){ 188 for(var j = y - 1; j < y + 2;j ++){ 189 var arr = [i,j]; 190 if(mysaolei.children[i*col + j] && (mysaolei.children[i*col + j].index[0] == arr[0] && mysaolei.children[i*col + j].index[1] == arr[1])){ 191 leftClick(mysaolei.children[i*col + j]); 192 } 193 } 194 } 195 } 196 isGameWin(); 197 } 198 } 199 } 200 function rightClick(self){ // 右键事件 201 if(self.classList.contains("flag") || !self.className){ 202 self.classList.toggle("flag"); 203 self.flag = !self.flag; 204 lei_flag = self.flag ? lei_flag + 1 : lei_flag - 1; 205 if(lei_n == lei_flag){ 206 for(var i = 0; i < mysaolei.children.length; i++){ 207 if ((mysaolei.children[i].flag + mysaolei.children[i].lei) == 2){ 208 mount += 1; 209 } 210 } 211 if(mount != lei_n){ 212 mount = 0 213 } 214 } 215 } 216 showLeaveLei(); 217 isGameWin(); 218 } 219 220 function gameOver(){ // 游戏结束事件 221 for(var i = 0; i < mysaolei.children.length; i++){ 222 if(mysaolei.children[i].lei){ 223 mysaolei.children[i].classList.add("lei"); 224 } 225 } 226 lock = false; 227 clearInterval(setTime); 228 setTimeout(function(){ 229 alert("game over !!!"); 230 },500) 231 } 232 function isGameWin(){ 233 if(mount == lei_n || save_num == (row * col - lei_n)){ 234 lock = false; 235 clearInterval(setTime); 236 alert('大吉大利!今晚吃鸡!'); 237 map = []; 238 lei_flag = 0; 239 save_num = 0; 240 mount = 0; 241 } 242 } 243 function showLeaveLei(){ 244 leave.innerHTML = lei_n - lei_flag + '个'; 245 } 246 function init(){ 247 lock = true; 248 createMap(); 249 // console.log(map); 250 mapInBox(); 251 showLeaveLei(); 252 setTime = setInterval(function(){ 253 useTime += 0.5; 254 time.innerHTML = parseInt(useTime) + 's'; 255 },500) 256 } 257 }
纯手打!独立完成,欢迎提意见,找bug!