相比于网上很火的20行贪吃蛇,这个版本有 2000 个字符,刚好也是20行版本字符数的两倍
环境是ES6
相较于20行版本
- 此版本用的是二维坐标系,而不是一维,因此更好调试
- 代码可读性更强,尽管为了省行数,控制流看起来不正常,并且用了很多隐式的循环(虽说jQuery一共也就3行
- 修补了一个BUG: 蛇身长为4时,是不可能碰到自己的
40行版本
- <!doctype html>
- <html>
- <body>
- <canvas id="1" width="400" height="400" ></canvas>
- <script>
- let ctx = document.getElementById("1").getContext("2d");
- let SpecialLen = 20, snakeDir = 2, snakeDirNow , food = [2,0], snakeBody = [ [0, 0], [1, 0] ]; //2 for right direction
- let Map = {}; //map对象存放 location:val ,例‘1,2‘:1 ,1表示蛇身,2表示食物
- for(let snakeNode of snakeBody) Map[snakeNode] = 1;
- let dirMat = [[-1, 0], [0, -1], [1, 0], [0, 1]]; //0 1 2 3 <- ↑ -> ↓
- let pairEqual = ((pair1, pair2) => pair1[0] == pair2[0] && pair1[1] == pair2[1]); //碰撞检测
- document.onkeydown = function (env) {
- arrowKeyCode = env.keyCode - 37; //37是"leftArrow"
- if (0 <= arrowKeyCode == arrowKeyCode < 4) //忽视其他键
- if (snakeDirNow !== (arrowKeyCode + 2) % 4) //周期过后才改变方向&&不能走相反方向
- snakeDir = arrowKeyCode;
- };
- !function () {
- let snakeHeadNext = snakeBody[snakeBody.length-1].map((x, i) => x + dirMat[snakeDirNow=snakeDir][i]); //得到蛇头的下一步位置
- if (!pairEqual(snakeHeadNext, food)) { //没吃到食物
- Map[snakeBody.shift()] = 0; //先去除蛇尾
- if (snakeBody.some(x=>pairEqual(x,snakeHeadNext)) || !snakeHeadNext.every(x => 0<=x == x < SpecialLen)) //蛇头不对
- return document.write("Game Over"); //overwrite all
- }
- snakeBody.push(snakeHeadNext);
- Map[snakeHeadNext] = 1; //蛇头合适,加入蛇身
- while (snakeBody.some(x => pairEqual(x, food)))
- food = [Math.floor(Math.random() * SpecialLen), Math.floor(Math.random() * SpecialLen)];
- Map[food] = 2;
- for(let i =0;i<SpecialLen ;i++)
- for(let j =0;j<SpecialLen ;j++){
- switch (Map[[i,j]]) {
- case 1:ctx.fillStyle= ‘purple‘;break;
- case 2:ctx.fillStyle= ‘green‘;break;
- default:ctx.fillStyle= ‘grey‘;break;
- }
- ctx.fillRect(i*SpecialLen,j*SpecialLen, SpecialLen, SpecialLen)
- }
- setTimeout(arguments.callee, 100); //130ms后执行 此function 一次
- }()
- </script>
- </body>
- </html>
|
40行版本去除注释
1500字符
- <!doctype html>
- <html>
- <body>
- <canvas id="1" width="400" height="400" ></canvas>
- <script>
- let ctx = document.getElementById("1").getContext("2d");
- let Len = 20, dir = 2, dirNow;
- let food = [2, 0];
- let Snake = [[0, 0], [1, 0]];
- let Map = {‘0,0‘:1,‘1,0‘:1};
- let dirMat = [[-1, 0], [0, -1], [1, 0], [0, 1]];
- let pairEqual = ((p1, p2) => p1[0] == p2[0] && p1[1] == p2[1]);
- document.onkeydown = function (env) {
- arr = env.keyCode - 37;
- if (0 <= arr == arr < 4 && dirNow !== (arr + 2) % 4)
- dir = arr;
- };
- !function () {
- let Head = Snake[Snake.length-1].map((x, i) => x + dirMat[dirNow=dir][i]);
- if (!pairEqual(Head, food)) {
- Map[Snake.shift()] = 0;
- if (Snake.some(x=>pairEqual(x,Head)) || !Head.every(x => 0<=x == x < Len))
- return document.write("Game Over");
- }
- Snake.push(Head);
- Map[Head] = 1;
- while (Snake.some(x => pairEqual(x, food)))
- food = [~~(Math.random() * Len), ~~(Math.random() * Len)];
- Map[food] = 2;
- for(let i =0;i<Len ;i++)
- for(let j =0;j<Len ;j++){
- switch (Map[[i,j]]) {
- case 1:ctx.fillStyle= ‘purple‘;break;
- case 2:ctx.fillStyle= ‘green‘;break;
- default:ctx.fillStyle= ‘grey‘;break;
- }
- ctx.fillRect(i*Len,j*Len, Len, Len)
- }
- setTimeout(arguments.callee, 100);
- }()
- </script>
- </body>
- </html>
|
20行版本
- <!doctype html>
- <html>
- <body>
- <canvas id="can" width="400" height="400" style="background: Black"></canvas>
- <script>
- var sn = [ 42, 41 ], dz = 43, fx = 1, n, ctx = document.getElementById("can").getContext("2d");
- function draw(t, c) {
- ctx.fillStyle = c;
- ctx.fillRect(t % 20 * 20 + 1, ~~(t / 20) * 20 + 1, 18, 18);
- }
- document.onkeydown = function(e) {
- fx = sn[1] - sn[0] == (n = [ -1, -20, 1, 20 ][(e || event).keyCode - 37] || fx) ? fx : n
- };
- !function() {
- sn.unshift(n = sn[0] + fx);
- if (sn.indexOf(n, 1) > 0 || n<0||n>399 || fx == 1 && n % 20 == 0 || fx == -1 && n % 20 == 19)
- return alert("GAME OVER");
- draw(n, "Lime");
- if (n == dz) {
- while (sn.indexOf(dz = ~~(Math.random() * 400)) >= 0);
- draw(dz, "Yellow");
- } else draw(sn.pop(), "Black");
- setTimeout(arguments.callee, 130);
- }();
- </script>
- </body>
- </html>
|
几个常见问题
- 蛇尾应该比蛇头先消失,蛇头应该比食物先生成,
- 蛇不能走 当前相反的方向,可以用长度为4的蛇进行测试
40行贪吃蛇 原生js
原文地址:https://www.cnblogs.com/migeater/p/9286849.html