13 lines greedy snake js

Keywords: Google github

Source code first, version is ES6

13 lines regular (700bytes)

shortest snake game.html

Compressed 500bytes (of course, two document s can be compressed with eval)

index.500bytes.html

Previous hot 20 line code address (with BUG)(900bytes)

hj7jay/article/details/51011269

One dimensional array 700char

The snake body at (0,0) position is represented by 0, (0,1) by 1, (1,0) by 10, and so on

Because just 13 lines of js,

Line 4 is the declaration

Line 5 is difficult to understand. You can split the?: operator into four if lines. Please refer to the following version of 2D array

Line 9: 0|x and ~ ~ x and x > > 0 can remove the mantissa of x(number)

It should be easy to read

<!DOCTYPE html>
<canvas id="1" width="400" height="400"></canvas>
<script>
let dir=1,food=3,snk=[1,0],ctx=document.getElementById("1").getContext("2d")
document.onkeydown=e=>{dir =  snk[0]-snk[1]==-(tmp = [-1,-10,1,10][e.keyCode-37]||dir)?dir:tmp}
setInterval(()=>{
    snk.unshift(Head = snk[0] + dir)
    if(Head!=food) snk.pop()
    else while(snk.includes(food=0|Math.random()*10*10)) ;
    if(snk.indexOf(Head,1)!=-1||(dir==1&&Head%10==0)||(dir==-1&&Head%10==9)||Head<0||Head>=100)
        return document.write(0&snk.shift()) //Death record snake length
    for(let i=0; i<100; i++){
        ctx.fillStyle = '#0'+(food==i)*9910+snk.includes(i)*1990
        ctx.fillRect(i%10*40,(i-i%10)*4, 40,40)
    }
},100)
</script>

Click to run

Color effect

<!DOCTYPE html>
<canvas id="1" width="400" height="400"></canvas>
<script>
let dir=1,food=3,snk=[1,0],n_=0, ctx=document.getElementById("1").getContext("2d")
document.onkeydown=e=>{ dir =snk[0]-snk[1]==-(tmp = [-1,-10,1,10][e.keyCode-37]||dir)?dir:tmp}
setInterval(()=>{
    snk.unshift(Head = snk[0] + dir)
    if(Head!=food) snk.pop()
    else while(snk.includes(food=0|Math.random()*10*10)) ;
    if(snk.indexOf(Head,1)!=-1||(dir==1&&Head%10==0)||(dir==-1&&Head%10==9)||Head<0||Head>=100)
        return alert("died"+ ++n_+"times") //Number of deaths recorded
    for(let i=0 ; i<100; i++){
        ctx.fillStyle = '#0'+~~((food===i)*13000*Math.random())+~~(snk.includes(i)*3000*Math.random())
        ctx.fillRect(i%10*40,(i-i%10)*4, 40,40)
    }
},120)
</script>

Click to run

Explain

If you want to write by yourself: pay attention to two points

  1. The snake's tail should disappear before the snake's head. The snake's head should be more mature than the food man,
  2. Snakes can't go in the opposite direction

    It can be tested with a snake of length 4

Code style

  1. Eliminate unnecessary labels

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

  2. if() return uses only one line

    https://google.github.io/styleguide/cppguide.html

  3. Except for the keyboard response where three lines can be saved by using the three item operator, there is no need to use

       

Two-dimensional array

All of the above are implemented with one-dimensional arrays, and the following are written with two-dimensional arrays. To simplify, you can also simplify it to within 17 lines and within 900 chars (shorter than that of 20 lines), but it is unnecessary

1100char with notes

<!DOCTYPE html>
<canvas id="1" width="400" height="400" style="border: 1px solid "></canvas>
<script>
    ctx = document.getElementById("1").getContext("2d") //CanvasRenderingContext2D inferface
    let Len = 10, dir = 2, dirNow ; //Explain after dirNow
    food = [3, 0]; Snake = [[0, 0], [1, 0]] //The coordinates of food and Snake are recorded by Snake array
    Map = {'0,0':'#52a', '1,0':'#52a '} / / map used to record drawing colors
    dirMat = [[-1, 0], [0, -1], [1, 0], [0, 1]] //Directional matrix
    pairEq = ((p1, p2) => p1[0] == p2[0] && p1[1] == p2[1]) //A function that detects whether two pairs of numbers are equal
    document.onkeydown = e =>{
        if (37 <= e.keyCode == e.keyCode < 41 && dirNow != ( (e.keyCode - 35) % 4) ) //Confirm that it is the direction key and ensure that the direction is opposite to the current movement direction
            dir = e.keyCode -37
    }
    !function () {
        Head = Snake[Snake.length-1].map((x, i) => x + dirMat[dirNow=dir][i]); //Get the next movement of the head
        if (!pairEq(Head, food))
            Map[Snake.shift()]='#fff '/ / the tail must be removed before the head can be added. Eating or not eating food is the only criterion
        if (Snake.some(x=>pairEq(x,Head)) || !Head.every(x => 0<=x == x < Len)) //Determine if the head of the snake hits the body or the wall
            return document.write("Game Over") //In this way, calling document.write will empty all pages
        Snake.push(Head); //Can be added to the head
        while (Snake.some(x => pairEq(x, food))) //It is more convenient to produce food after adding new head
            food = [~~(Math.random() * Len), ~~(Math.random() * Len)]; //Because js has no concept of shaping, ~ ~ now it is equivalent to rounding off to the origin
        Map[Head] = '#52a' ; Map[food] = '#ad5'
        for( k in Map){
            ctx.fillStyle= Map[k]
            ctx.fillRect(parseInt(k[0])*40,parseInt(k[2])*40,40,40) //e.g. k="1,3", so the map size is limited to 10
        }
        setTimeout(arguments.callee, 100); //This function is called once after 100ms.
    }()
</script>


Colorful (mainly pretty) 1100char

<!DOCTYPE html>
<canvas id="1" width="400" height="400" style="border: 1px solid " ></canvas>
<script>
    ctx = document.getElementById("1").getContext("2d")
    let Len = 10, dir = 2, dirNow ;
food = [3, 0]; Snake = [[0, 0], [1, 0]]
    Map = {'0,0':'fff', '1,0':'fff'}
    dirMat = [[-1, 0], [0, -1], [1, 0], [0, 1]]
    pairEq = ((p1, p2) => p1[0] == p2[0] && p1[1] == p2[1])
    document.onkeydown = e =>{
        if (37 <= e.keyCode == e.keyCode < 41 && dirNow != ( (e.keyCode - 35) % 4) )
dir = e.keyCode -37
    }
    !function () {
        Head = Snake[Snake.length-1].map((x, i) => x + dirMat[dirNow=dir][i]);
        if (!pairEq(Head, food)) Map[Snake.shift()]='0'
        if (Snake.some(x=>pairEq(x,Head)) || !Head.every(x => 0<=x == x < Len))
            return document.write("Game Over")
        Snake.push(Head);
        while (Snake.some(x => pairEq(x, food)))
food = [~~(Math.random() * Len), ~~(Math.random() * Len)];
        Map[Head] = Map[food] = 'fff'
        for( k in Map){
            ctx.fillStyle='#'+(0xfff-~~(parseInt(Map[k],16)*Math.random())).toString(16)
            ctx.fillRect(parseInt(k[0])*40,parseInt(k[2])*40,46,43)
        }
        setTimeout(arguments.callee, 100);
    }()
</script>   

Posted by forzatio on Sat, 15 Feb 2020 12:42:51 -0800