有一天午睡突然突发奇想写个贪吃蛇玩一玩,一开始是想用c来写,然后弄一个8*8的点阵屏来玩的,但是又觉得太过于麻烦,所以就想着用最简单的方法来实现,所以就选择了JavaScript和HTML来实现,简述一下实现原理和提出代码
示例demo
snake-game
建议用手机打开,当然电脑也做了上下左右键盘控制,但是显示效果是为了手机显示适应的
效果图

实现原理
我觉得弄这个需要一点点的面相对象的思维就能简简单单的实现,首先我们需要有一个地图,所以就需要在这个地图上建立坐标系,不让我们的贪吃蛇抛出我们的坐标系,所以我就选择了二维数组来建立我们的坐标系,然后给每个坐标都设定一个值(
我设定的就是x轴左边加y轴坐标的字符串),然后我们还需要一条贪吃蛇,和砖块,这里其实可以看成一部分,其实砖块就是我们坐标里面对应的值,而我们的贪吃蛇就是这个砖块的数组,所以我们可以理解成以下样子
地图:
一个二维数组
贪吃蛇
一个包含在地图里面的一维数组 ==> 多个砖块的拼接组成的一个数组
砖块
一个地图里面对应的准确的值
所以看到这里就很简单了,所谓的贪吃蛇其实就是在操作我们熟知的数组
上述的是我们游戏里面涉及到的元素,接下来我们讲讲我们涉及到的一些动作
蛇的行动范围
这个其实很简单,主要就是对蛇头做判断(数组第一个),只要蛇头不大于地图数组,游戏便可以继续下去
蛇的位移
其实蛇移动比较容易理解,例如 向下移动的时候y轴坐标+1,x轴坐标不动 其他方向同理,这样就能实现蛇的整体位移

看图比较容易看懂,就是蛇头以后得元素需要向之前的移动
蛇的成长

这里我们有使用数据结构中比较高级的插入方式,使用了我比较喜欢的渣渣方式,就是直接在数组的后面添加一个元素,实现蛇吃砖块长大的方式
砖块的随机生成
这里需要确保不会和我门蛇的数组位置冲突,需要做一些判断
蛇吃自己
这里只需要判断蛇里面没有重复的元素便可以了
视图渲染
每次蛇的移动完成以后都生成一个0和1组成的二维数组,遍历数组为HTML添加颜色就可以了
写在最后
其实实现起来远比我说明的这些要容易的多,毕竟我是一个喜欢讲废话的人,我个人觉得看了代码就知道这个东西确实是挺简单的
代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 
 | <!DOCTYPE html><html lang="en">
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="user-scalable=0">
 <title>snake game</title>
 <style>
 * {
 width: 100%;
 height: 100%;
 margin: 0;
 padding: 0;
 }
 
 #score {
 font-size: 300%;
 display: flex;
 align-items: center;
 justify-content: center;
 }
 
 #handle {
 display: flex;
 flex-direction: column;
 overflow: hidden;
 font-size: 150%;
 }
 
 .game-row {
 display: flex;
 flex-direction: row;
 }
 
 .game-column {
 display: flex;
 flex-direction: column;
 align-items: center;
 justify-content: space-between;
 border: 1px #ce53d2 solid;
 }
 
 .game-column-snake {
 display: flex;
 flex-direction: column;
 align-items: center;
 justify-content: space-between;
 border: 1px #ce53d2 solid;
 background: black;
 }
 
 .game-column-block {
 display: flex;
 flex-direction: column;
 align-items: center;
 justify-content: space-between;
 border: 1px #ce53d2 solid;
 background: lightgreen;
 }
 
 .center {
 display: flex;
 align-items: center;
 justify-content: center;
 }
 </style>
 </head>
 <body id="body" style="display: flex;flex-direction: column">
 <div id="score">分数</div>
 <div id="game"></div>
 <div id="handle">
 <div class="center" style="height: 30%;" onclick="handle('up')">上</div>
 <div style="display: flex;flex-direction: row;height: 60%;">
 <div class="center" onclick="handle('left')">左</div>
 <div class="center" onclick="handle('start')">重新开始</div>
 <div class="center" onclick="handle('right')">右</div>
 </div>
 <div class="center" style="height: 30%;" onclick="handle('down')">
 下
 </div>
 </div>
 </body>
 <script>
 var w = 0,
 h = 0,
 block = '00',
 snake = [],
 map = [],
 xy = [],
 hanld = 'right',
 mapSize = 10,
 score = 0,
 level = 500,
 endflag = false,
 runStatus = 0;
 main();
 
 
 
 
 function main() {
 initShow();
 initMap();
 genSnake();
 genBlock();
 gen01();
 next();
 }
 
 
 
 
 function initShow() {
 
 var dom = document.getElementById("body");
 w = dom.offsetWidth, h = dom.offsetHeight;
 var h_w = h - w;
 
 var score = document.getElementById('score');
 score.style.height = parseInt(h_w) * 0.2 + 'px';
 
 var handle = document.getElementById('handle');
 handle.style.height = parseInt(h_w) * 0.8 + 'px';
 
 var game = document.getElementById('game');
 game.style.width = parseInt(w) + 'px';
 game.style.height = parseInt(w) + 'px';
 }
 
 
 
 
 function initMap() {
 for (var x = 0; x < mapSize; x++) {
 map[x] = [];
 for (var y = 0; y < mapSize; y++) {
 map[x][y] = splitStr(y, x);
 }
 }
 }
 
 
 
 
 
 
 function rand(filter) {
 var rand = parseInt(Math.random() * 10);
 if (rand == filter) {
 rand(filter);
 }
 return rand;
 }
 
 
 
 
 function gen01() {
 var overflag = false;
 for (var i = 0; i < mapSize; i++) {
 xy[i] = [];
 for (var j = 0; j < mapSize; j++) {
 xy[i][j] = 0;
 for (var s = 0; s < snake.length; s++) {
 if (snake[s] == map[i][j]) {
 xy[i][j] = 1;
 break;
 }
 }
 if (block == map[i][j]) {
 xy[i][j] = 2;
 }
 if (snake[0] == map[i][j]) {
 overflag = true;
 }
 }
 }
 if (!overflag) {
 
 showover();
 } else {
 if (!endflag) {
 
 show(xy);
 }
 }
 }
 
 
 
 
 function genSnake() {
 snake.push(splitStr(rand(), rand()));
 }
 
 
 
 
 function genBlock() {
 block = splitStr(rand(), rand());
 
 for (var i in snake) {
 if (block == snake[i]) {
 genBlock();
 }
 }
 }
 
 
 
 
 function next() {
 clearTimeout(runStatus);
 changeSnakeHead();
 eatself();
 eatblock();
 gen01();
 runStatus = setTimeout(function () {
 next();
 }, level);
 }
 
 
 
 
 
 function eatself() {
 for (var s = 0; s < snake.length; s++) {
 if (s > 0 && snake[s] == snake[0]) {
 showover();
 break
 }
 }
 }
 
 
 
 
 function changeSnakeHead() {
 var tempa = snake[0];
 for (var i = 0; i < snake.length; i++) {
 var a = snake[i][0], b = snake[i][1];
 if (i == 0) {
 switch (hanld) {
 case 'up':
 snake[i] = splitStr(a, parseInt(b) - 1);
 break;
 case 'down':
 snake[i] = splitStr(a, parseInt(b) + 1);
 break;
 case 'left':
 snake[i] = splitStr(parseInt(a) - 1, b);
 break;
 case 'right':
 snake[i] = splitStr(parseInt(a) + 1, b);
 break;
 }
 } else {
 var tempb = tempa;
 tempa = snake[i];
 snake[i] = tempb;
 }
 }
 }
 
 
 
 
 function eatblock() {
 if (snake[0] == block) {
 var tail = snake[snake.length - 1], temp = [], a = tail[0], b = tail[1];
 switch (hanld) {
 case 'up':
 temp = splitStr(a, parseInt(b) + 1);
 break;
 case 'down':
 temp = splitStr(a, parseInt(b) - 1);
 break;
 case 'left':
 temp = splitStr(parseInt(a) + 1, b);
 break;
 case 'right':
 temp = splitStr(parseInt(a) - 1, b);
 break;
 }
 snake.push(temp);
 addscore();
 genBlock();
 }
 }
 
 
 
 
 
 
 function splitStr(x, y) {
 return x + '' + y;
 }
 
 
 
 
 
 document.onkeydown = function (e) {
 var e = window.event || e;
 switch (e.keyCode) {
 case 37:
 hanld = hanld != 'left' && hanld != 'right' ? 'left' : hanld;
 break;
 case 38:
 hanld = hanld != 'up' && hanld != 'down' ? 'up' : hanld;
 break;
 case 39:
 hanld = hanld != 'left' && hanld != 'right' ? 'right' : hanld;
 break;
 case 40:
 hanld = hanld != 'up' && hanld != 'down' ? 'down' : hanld;
 break;
 }
 }
 
 
 
 
 function handle(e) {
 if (e == 'start') {
 if (endflag) {
 
 window.location.reload();
 }
 } else {
 if ((hanld == 'left' || hanld == 'right')) {
 if (e == 'up' || e == 'down') {
 hanld = e;
 }
 } else {
 if (e == 'left' || e == 'right') {
 hanld = e;
 }
 }
 }
 }
 
 
 
 
 function addscore() {
 var score = parseInt(snake.length) - 1;
 
 if (score > 20) {
 level = 250;
 } else if (score > 15) {
 level = 300;
 } else if (score > 10) {
 level = 350;
 } else if (score > 5) {
 level = 400;
 } else if (score > 1) {
 level = 450;
 } else {
 level = level;
 }
 document.getElementById('score').innerHTML = '分数:' + score;
 }
 
 
 
 
 
 function show(xy) {
 var html = '',
 height = parseInt(w) / mapSize;
 for (var i = 0; i < mapSize; i++) {
 html += '<div class="game-row" style="height:' + height + 'px;">'
 for (var j = 0; j < mapSize; j++) {
 if (xy[i][j] == 1) {
 html += '<div class="game-column-snake"></div>';
 } else if (xy[i][j] == 2) {
 html += '<div class="game-column-block"></div>';
 } else {
 html += '<div class="game-column"></div>';
 }
 
 }
 html += '</div>';
 }
 document.getElementById('game').innerHTML = html;
 }
 
 
 
 
 function showover() {
 document.getElementById('game').innerHTML = '<h1 align="center" style="font-size: 500%;color:red;">game over!</h1>';
 endflag = true;
 }
 
 
 </script>
 </html>
 
 
 |