1 <html> 2 3 <head> 4 <title>贪吃蛇 Snake v2.4</title> 5 <style> 6 body { 7 font-size: 20px; 8 } 9 10 table { 11 border-collapse: collapse; 12 border: solid rgb(182, 178, 178) 1px; 13 background: #fff; 14 } 15 16 td { 17 height: 20px; 18 width: 20px; 19 font-size: 0px; 20 } 21 22 .filled { 23 background-color: blue; 24 } 25 </style> 26 </head> 27 <script> 28 function $(id) { 29 return document.getElementById(id); 30 } 31 /************************************************************** 32 * javascript贪吃蛇 33 **************************************************************/ 34 //贪吃蛇类 35 var Snake = { 36 tbl: null, 37 /** 38 * body: 蛇身,数组放蛇的每一节, 39 * 数据结构{x:x0, y:y0, color:color0}, 40 * x,y表示坐标,color表示颜色 41 **/ 42 body: [], 43 //当前移动的方向,取值0,1,2,3, 分别表示向上,右,下,左, 按键盘方向键可以改变它 44 direction: 0, 45 //定时器 46 timer: null, 47 //速度 48 speed: 250, 49 //是否已经暂停 50 paused: true, 51 //行数 52 rowCount: 20, 53 //列数 54 colCount: 40, 55 //初始化 56 init: function() { 57 var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple', 'pink']; 58 this.tbl = $("main"); 59 var x = 0; 60 var y = 0; 61 var colorIndex = 0; 62 //产生初始移动方向 63 this.direction = Math.floor(Math.random() * 4); 64 //构造table 65 for (var row = 0; row < this.rowCount; row++) { 66 var tr = this.tbl.insertRow(-1); 67 for (var col = 0; col < this.colCount; col++) { 68 var td = tr.insertCell(-1); 69 } 70 } 71 //产生20个松散节点 72 for (var i = 0; i < 10; i++) { 73 x = Math.floor(Math.random() * this.colCount); 74 y = Math.floor(Math.random() * this.rowCount); 75 colorIndex = Math.floor(Math.random() * 7); 76 if (!this.isCellFilled(x, y)) { 77 this.tbl.rows[y].cells[x].style.backgroundColor = colors[colorIndex]; 78 } 79 } 80 //产生蛇头 81 while (true) { 82 x = Math.floor(Math.random() * this.colCount); 83 y = Math.floor(Math.random() * this.rowCount); 84 if (!this.isCellFilled(x, y)) { 85 this.tbl.rows[y].cells[x].style.backgroundColor = "black"; 86 this.body.push({ 87 x: x, 88 y: y, 89 color: 'black' 90 }); 91 break; 92 } 93 } 94 this.paused = true; 95 //添加键盘事件 96 document.onkeydown = function(e) { 97 if (!e) e = window.event; 98 switch (e.keyCode | e.which | e.charCode) { 99 case 13: 100 { 101 if (Snake.paused) { 102 Snake.move(); 103 Snake.paused = false; 104 } else { 105 //如果没有暂停,则停止移动 106 Snake.pause(); 107 Snake.paused = true; 108 } 109 break; 110 } 111 case 37: 112 { //left 113 //阻止蛇倒退走 114 if (Snake.direction == 1) { 115 break; 116 } 117 118 Snake.direction = 3; 119 break; 120 } 121 case 38: 122 { //up 123 //快捷键在这里起作用 124 if (event.ctrlKey) { 125 Snake.speedUp(-20); 126 break; 127 } 128 if (Snake.direction == 2) { //阻止蛇倒退走 129 break; 130 } 131 Snake.direction = 0; 132 break; 133 } 134 case 39: 135 { //right 136 if (Snake.direction == 3) { //阻止蛇倒退走 137 break; 138 } 139 Snake.direction = 1; 140 break; 141 } 142 case 40: 143 { //down 144 if (event.ctrlKey) { 145 Snake.speedUp(20); 146 break; 147 } 148 if (Snake.direction == 0) { //阻止蛇倒退走 149 break; 150 } 151 Snake.direction = 2; 152 break; 153 } 154 } 155 } 156 }, 157 //移动 158 move: function() { 159 this.timer = setInterval(function() { 160 Snake.erase(); 161 Snake.moveOneStep(); 162 Snake.paint(); 163 }, this.speed); 164 }, 165 //移动一节身体 166 moveOneStep: function() { 167 if (this.checkNextStep() == -1) { 168 clearInterval(this.timer); 169 alert("Game over!/nPress Restart to continue."); 170 return; 171 } 172 if (this.checkNextStep() == 1) { 173 var _point = this.getNextPos(); 174 var _x = _point.x; 175 var _y = _point.y; 176 var _color = this.getColor(_x, _y); 177 this.body.unshift({ 178 x: _x, 179 y: _y, 180 color: _color 181 }); 182 //因为吃了一个食物,所以再产生一个食物 183 this.generateDood(); 184 return; 185 } 186 //window.status = this.toString(); 187 var point = this.getNextPos(); 188 //保留第一节的颜色 189 var color = this.body[0].color; 190 //颜色向前移动 191 for (var i = 0; i < this.body.length - 1; i++) { 192 this.body[i].color = this.body[i + 1].color; 193 } 194 //蛇尾减一节, 蛇尾加一节,呈现蛇前进的效果 195 this.body.pop(); 196 this.body.unshift({ 197 x: point.x, 198 y: point.y, 199 color: color 200 }); 201 //window.status = this.toString(); 202 }, 203 //探寻下一步将走到什么地方 204 pause: function() { 205 clearInterval(Snake.timer); 206 this.paint(); 207 }, 208 getNextPos: function() { 209 var x = this.body[0].x; 210 211 var y = this.body[0].y; 212 var color = this.body[0].color; 213 //向上 214 if (this.direction == 0) { 215 y--; 216 } 217 //向右 218 else if (this.direction == 1) { 219 x++; 220 } 221 //向下 222 else if (this.direction == 2) { 223 y++; 224 } 225 //向左 226 else { 227 x--; 228 } 229 //返回一个坐标 230 return { 231 x: x, 232 y: y 233 }; 234 }, 235 //检查将要移动到的下一步是什么 236 checkNextStep: function() { 237 var point = this.getNextPos(); 238 var x = point.x; 239 var y = point.y; 240 if (x < 0 || x >= this.colCount || y < 0 || y >= this.rowCount) { 241 return -1; //触边界,游戏结束 242 } 243 for (var i = 0; i < this.body.length; i++) { 244 if (this.body[i].x == x && this.body[i].y == y) { 245 return -1; //碰到自己的身体,游戏结束 246 } 247 } 248 if (this.isCellFilled(x, y)) { 249 return 1; //有东西 250 } 251 return 0; //空地 252 }, 253 //擦除蛇身 254 erase: function() { 255 for (var i = 0; i < this.body.length; i++) { 256 this.eraseDot(this.body[i].x, this.body[i].y); 257 } 258 }, 259 //绘制蛇身 260 paint: function() { 261 for (var i = 0; i < this.body.length; i++) { 262 this.paintDot(this.body[i].x, this.body[i].y, this.body[i].color); 263 } 264 }, 265 //擦除一节 266 eraseDot: function(x, y) { 267 this.tbl.rows[y].cells[x].style.backgroundColor = ""; 268 }, 269 paintDot: function(x, y, color) { 270 this.tbl.rows[y].cells[x].style.backgroundColor = color; 271 }, 272 //得到一个坐标上的颜色 273 getColor: function(x, y) { 274 return this.tbl.rows[y].cells[x].style.backgroundColor; 275 }, 276 //用于调试 277 toString: function() { 278 var str = ""; 279 for (var i = 0; i < this.body.length; i++) { 280 str += "x:" + this.body[i].x + " y:" + this.body[i].y + " color:" + this.body[i].color + " - "; 281 } 282 return str; 283 }, 284 //检查一个坐标点有没有被填充 285 isCellFilled: function(x, y) { 286 if (this.tbl.rows[y].cells[x].style.backgroundColor == "") { 287 return false; 288 } 289 return true; 290 }, 291 //重新开始 292 restart: function() { 293 if (this.timer) { 294 clearInterval(this.timer); 295 } 296 for (var i = 0; i < this.rowCount; i++) { 297 this.tbl.deleteRow(0); 298 } 299 this.body = []; 300 this.init(); 301 this.speed = 250; 302 }, 303 //加速 304 speedUp: function(time) { 305 if (!this.paused) { 306 if (this.speed + time < 10 || this.speed + time > 2000) { 307 return; 308 } 309 this.speed += time; 310 this.pause(); 311 this.move(); 312 } 313 }, 314 //产生食物。 315 generateDood: function() { 316 var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple', '#ccc']; 317 var x = Math.floor(Math.random() * this.colCount); 318 var y = Math.floor(Math.random() * this.rowCount); 319 var colorIndex = Math.floor(Math.random() * 7); 320 if (!this.isCellFilled(x, y)) { 321 this.tbl.rows[y].cells[x].style.backgroundColor = colors[colorIndex]; 322 } 323 } 324 }; 325 </script> 326 327 <body onload="Snake.init();"> 328 329 <br /> 330 <table id="main" border="1" cellspacing="0" cellpadding="0"></table> 331 <input type="button" id="btn" value="开始/暂停" />点左边按钮或按Enter开始/暂停游戏<br /> 332 <input type="button" id="reset" value="重新开始" /><br /> 333 <input type="button" id="upSpeed" value="加速" />点左边按钮或按Ctrl + ↑加速<br /> 334 <input type="button" id="downSpeed" value="减速" />点左边按钮或按Ctrl + ↓减速 335 <script> 336 $('btn').onclick = function() { 337 if (Snake.paused) { 338 Snake.move(); 339 Snake.paused = false; 340 } else { 341 Snake.pause(); 342 Snake.paused = true; 343 } 344 }; 345 $("reset").onclick = function() { 346 Snake.restart(); 347 this.blur(); 348 }; 349 $("upSpeed").onclick = function() { 350 Snake.speedUp(-20); 351 }; 352 $("downSpeed").onclick = function() { 353 Snake.speedUp(20); 354 }; 355 </script> 356 </body> 357 358 </html>