贪吃蛇案列---2.0可调速版

Posted on 2019-09-06 09:32  柒月柳无絮  阅读(143)  评论(0编辑  收藏  举报
  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>