30行到17行原生js写(变色)贪吃蛇

相比于网上很火的20行贪吃蛇,这个版本主要是用二维数组改写增加了可读性, 同时也只有1100个字符原版900个字符,不像某篇宣称17行的博客,有1400个字符

环境是ES6

   

相较于20行版本

  1. 此版本用的是二维数组,而不是一维,因此更好调试,可读性也更强,并且没有3目运算符
  2. 这个版本没有BUG,原版: 蛇身长为4,也会碰到自己;大部分博文都会犯这个小错误
  3. 按谷歌的说法能省的标签的都省了

    https://google.github.io/styleguide/htmlcssguide.html#Optional_Tags

       

2维数组版本和注释1100 char 26 line

  1. <!DOCTYPE html>
  2. <canvas id="1" width="400" height="400" style="border: 1px solid "></canvas>
  3. <script>
  4.     ctx = document.getElementById("1").getContext("2d") //CanvasRenderingContext2D inferface
  5.     let Len = 10, dir = 2, dirNow ; //dirNow 后面解释
  6.     food = [3, 0]; Snake = [[0, 0], [1, 0]] //食物的坐标,蛇身的坐标用Snake数组记录
  7.     Map = {'0,0':'#52a', '1,0':'#52a'} //用来记录绘图颜色的 地图
  8.     dirMat = [[-1, 0], [0, -1], [1, 0], [0, 1]] //方向矩阵
  9.     pairEq = ((p1, p2) => p1[0] == p2[0] && p1[1] == p2[1]) //检测 两数对 是否相等的函数
  10.     document.onkeydown = e =>{
  11.         if (37 <= e.keyCode == e.keyCode < 41 && dirNow != ( (e.keyCode - 35) % 4) ) //确定是 方向键 并且 保证方向与当前运动方向相反
  12.             dir = e.keyCode -37
  13.     }
  14.     !function () {
  15.         Head = Snake[Snake.length-1].map((x, i) => x + dirMat[dirNow=dir][i]); //得到头部接下来的移动位置
  16.         if (!pairEq(Head, food))
  17.             Map[Snake.shift()]='#fff' //必须先删尾巴,才能加入头部,吃没吃到食物是唯一判断标准
  18.         if (Snake.some(x=>pairEq(x,Head)) || !Head.every(x => 0<=x == x < Len)) //判断蛇头是否撞到蛇身或墙壁
  19.             return document.write("Game Over") //这样调用document.write会把页面全部清空
  20.         Snake.push(Head); //可以加入头部
  21.         while (Snake.some(x => pairEq(x, food))) //加入新头后, 生成食物更方便
  22.             food = [0|Math.random() * Len, 0|Math.random() * Len]; //因为js没有整形的概念, ~~ 现在相当于向原点舍去
  23.         Map[Head] = '#52a' ; Map[food] = '#ad5'
  24.         for( k in Map){
  25.             ctx.fillStyle= Map[k]
  26.             ctx.fillRect(parseInt(k[0])*40,parseInt(k[2])*40,40,40) //e.g. k="1,3",也因此地图大小限制为10
  27.         }
  28.         setTimeout(arguments.callee, 100); //100ms后调用此函数一次
  29.     }()
  30. </script>

七彩蛇1100char 22line||20行版本900 char 19line

  1. <!DOCTYPE html>
  2. <canvas id="1" width="400" height="400" style="border: 1px solid " ></canvas>
  3. <script>
  4.     ctx = document.getElementById("1").getContext("2d")
  5.     let Len = 10, dir = 2, dirNow ;food = [3, 0]; Snake = [[0, 0], [1, 0]]
  6.     Map = {'0,0':'fff', '1,0':'fff'}
  7.     dirMat = [[-1, 0], [0, -1], [1, 0], [0, 1]]
  8.     pairEq = ((p1, p2) => p1[0] == p2[0] && p1[1] == p2[1])
  9.     document.onkeydown = e =>{
  10.         if (37 <= e.keyCode == e.keyCode < 41 && dirNow != ( (e.keyCode - 35) % 4) ) dir = e.keyCode -37
  11.     }
  12.     !function () {
  13.         Head = Snake[Snake.length-1].map((x, i) => x + dirMat[dirNow=dir][i]);
  14.         if (!pairEq(Head, food)) Map[Snake.shift()]='0'
  15.         if (Snake.some(x=>pairEq(x,Head)) || !Head.every(x => 0<=x == x < Len))
  16.             return document.write("Game Over")
  17.         Snake.push(Head);
  18.         while (Snake.some(x => pairEq(x, food))) food = [0|Math.random() * Len, 0|Math.random() * Len];
  19.         Map[Head] = Map[food] = 'fff'
  20.         for( k in Map){
  21.             ctx.fillStyle='#'+(0xfff- (0|parseInt(Map[k],16)*Math.random())).toString(16)
  22.             ctx.fillRect(parseInt(k[0])*40,parseInt(k[2])*40,46,43)
  23.         }
  24.         setTimeout(arguments.callee, 100);
  25.     }()
  26. </script>
  1. <!doctype html>
  2. <canvas id="can" width="400" height="400" style="background: Black"></canvas>
  3. <script>
  4.     var sn = [ 42, 41 ], dz = 43, fx = 1, n, ctx = document.getElementById("can").getContext("2d");
  5.     function draw(t, c) {
  6.         ctx.fillStyle = c;
  7.         ctx.fillRect(t % 20 * 20 + 1, ~~(t / 20) * 20 + 1, 18, 18);
  8.     }
  9.     document.onkeydown = function(e) {
  10.         fx = sn[1] - sn[0] == (n = [ -1, -20, 1, 20 ][(e || event).keyCode - 37] || fx) ? fx : n
  11.     };
  12.     !function() {
  13.         sn.unshift(n = sn[0] + fx);
  14.         if (sn.indexOf(n, 1) > 0 || n<0||n>399 || fx == 1 && n % 20 == 0 || fx == -1 && n % 20 == 19)
  15.             return alert("GAME OVER");
  16.         draw(n, "Lime");
  17.         if (n == dz) {
  18.             while (sn.indexOf(dz = ~~(Math.random() * 400)) >= 0);
  19.             draw(dz, "Yellow");
  20.         } else draw(sn.pop(), "Black");
  21.         setTimeout(arguments.callee, 130);
  22.     }();
  23. </script>

二维数组再简化860char 18line ||一维数组再简化700char 17line

  1. <!DOCTYPE html>
  2. <canvas id="1" width="400" height="400" style="border: 1px solid "></canvas>
  3. <script>
  4.     let d = 2, dN,f = [3, 0],S = [[0, 0]],M = {},C = document.getElementById("1").getContext("2d")
  5.     Eq = ((p1, p2) => p1[0] == p2[0] && p1[1] == p2[1]);
  6.     document.onkeydown = e => {a = e.keyCode - 37;if (0 <= a == a < 4 && dN != ((a + 2) % 4)) d = a}
  7.     !function () {
  8.         H = S[S.length - 1].map((x, i) => x + [[-1, 0], [0, -1], [1, 0], [0, 1]][dN = d][i])
  9.         if (!Eq(H, f)) M[S.shift()] = '#fff'
  10.         if (S.some(x => Eq(x, H)) || !H.every(x => 0 <= x == x < 10))
  11.             return document.write("Game Over")
  12.         S.push(H)
  13.         while (S.some(x => Eq(x, f)))
  14.             f = [0 | Math.random() * 10, 0 | Math.random() * 10]
  15.         M[H] = '#52a';M[f] = '#ad5'
  16.         for (k in M) {
  17.             C.fillStyle = M[k]
  18.             C.fillRect(parseInt(k[0]) * 40, parseInt(k[2]) * 40, 40, 40)
  19.         }
  20.         setTimeout(arguments.callee, 100)
  21.     }()
  22. </script>

     

  1. <!DOCTYPE html>
  2. <canvas id="1" width="400" height="400"></canvas>
  3. <script>
  4.     let dir=1,food=3,snk=[1,0], ctx=document.getElementById("1").getContext("2d")
  5.     document.onkeydown=e=>{
  6.         dir =((snk[0]-snk[1]==-(tmp = [-1,-10,1,10][e.keyCode-37]||dir))?dir:tmp
  7.     }
  8.     !function () {
  9.         snk.unshift(Head = snk[0] + dir)
  10.         if(Head!=food) snk.pop()
  11.         else while(snk.includes(food=0|Math.random()*10*10)) ;
  12.         if( snk.indexOf(Head,1)!=-1||(dir ==1&& Head%10==0)||(dir==-1&& Head%10==9)||Head<0||Head>=100) {
  13.             return document.write("Game Over")
  14.         }
  15.         for(let i =0 ;i< 100 ; i++){
  16.             ctx.fillStyle = '#0'+(food===i)*9910+snk.includes(i)*1990
  17.             ctx.fillRect(i%10*40,(i-i%10)*4, 40,40)
  18.         }
  19.         setTimeout(arguments.callee, 100);
  20.     }()
  21. </script>

   

   

几个常见问题

  1. 蛇尾应该比蛇头先消失,蛇头应该比食物先生成,
  2. 蛇不能走当前相反的方向,可以用长度为4的蛇进行测试

猜你喜欢

转载自www.cnblogs.com/migeater/p/9292629.html