zoukankan      html  css  js  c++  java
  • 【贪吃蛇】canvas + 原生 JS, 10 行极限实现贪吃蛇

    上代码

    • html
      <canvas width="600" height="600">不支持 canvas</canvas>
      
    • css
      canvas {
           position: absolute;
           top: 50%;
           left: 50%;
           transform: translate(-50%, -50%);
           background-color: #ccc;
           border-radius: 10px;
           border: 1px solid #000;
       }
      
    • js
      var ctx = document.querySelector('canvas').getContext('2d'), direction = [{ x: -1, y: 0 }, { x: 0, y: -1 }, { x: 1, y: 0 }, { x: 0, y: 1 }], preDir = direction[1], food = { x: -1, y: -1 }, snkArr = [{ x: 14, y: 20 }, { x: 14, y: 21 }, { x: 14, y: 22 }];
      var draw = ({ x, y }, color) => (ctx.fillStyle = color, ctx.fillRect(x * 20, y * 20, 19, 19), 1);
      var changeDir = e => Math.abs((e.keyCode - 37) - direction.indexOf(preDir)) != 2 && (e.keyCode - 37) >= 0 && (e.keyCode - 37) <= 3 && (preDir = direction[e.keyCode - 37], document.removeEventListener('keydown', changeDir));
      setInterval(() => {
          if (document.addEventListener('keydown', changeDir) || snkArr.map((val, i) => { snkArr[0].x + preDir.x == val.x && snkArr[0].y + preDir.y == val.y && (snkArr[0].x = 31) }) && !(snkArr[0].x + preDir.x >= 30 || snkArr[0].y + preDir.y >= 30 || snkArr[0].x + preDir.x <= -1 || snkArr[0].y + preDir.y <= -1)) {
              snkArr.unshift({ x: snkArr[0].x + preDir.x, y: snkArr[0].y + preDir.y });
              draw({ x: snkArr[0].x, y: snkArr[0].y }, '#0aa');
              !(((snkArr[0].x == food.x && snkArr[0].y == food.y) || (food.x == -1 && draw(snkArr.pop(), '#ccc'))) && draw(((() => { while (snkArr.indexOf({ x: food.x = ~~(Math.random() * 29), y: food.y = ~~(Math.random() * 29) }) > -1); })(), food), 'orange')) && draw(snkArr.pop(), '#ccc');
          } else alert('Game over!', location.reload());
      }, 150);
      

    注释版

    var ctx = document.querySelector('canvas').getContext('2d'),
        // 2d 对象
    
        direction = [{ x: -1, y: 0 }, { x: 0, y: -1 }, { x: 1, y: 0 }, { x: 0, y: 1 }],
        // 方向列表,分别是 左 上 右 下 的位移增量,后面通过 keycode - 37 直接访问到该增量
    
        preDir = direction[1],
        // 当前方向,值为 direction 中四个元素之一
    
        food = { x: -1, y: -1 },
        // 食物的位置,初始化为 -1 ,第一次循环生成
    
        snkArr = [{ x: 14, y: 20 }, { x: 14, y: 21 }, { x: 14, y: 22 }];
    // 蛇身
    
    // 画方块,{x,y} 为方块的坐标,认为 20 * 20 为一个像素,实现中会做处理, color 为方块颜色
    var draw = ({ x, y }, color) => (ctx.fillStyle = color, ctx.fillRect(x * 20, y * 20, 19, 19), 1);
    // keydown 的回调
    var changeDir = e => {
        // 禁止同方向变化       
        Math.abs((e.keyCode - 37) - direction.indexOf(preDir)) != 2
            // 禁止其他按键影响
            && (e.keyCode - 37) >= 0
            // preDir 赋值
            && (e.keyCode - 37) <= 3 && (preDir = direction[e.keyCode - 37],
                // 移除事件监听,防止两帧之间连续改变方向
                document.removeEventListener('keydown', changeDir));
    }
    setInterval(() => {
        // 添加事件监听
        // map 判断有没有碰到蛇身,碰到后置蛇头超出范围 
        if (document.addEventListener('keydown', changeDir) || snkArr.map((val, i) => { snkArr[0].x + preDir.x == val.x && snkArr[0].y + preDir.y == val.y && (snkArr[0].x = 31) })
            // 判断蛇头有没有超出范围
            && !(snkArr[0].x + preDir.x >= 30 || snkArr[0].y + preDir.y >= 30 || snkArr[0].x + preDir.x <= -1 || snkArr[0].y + preDir.y <= -1)) {
    
            // snkArr 蛇身增加新蛇头
            snkArr.unshift({ x: snkArr[0].x + preDir.x, y: snkArr[0].y + preDir.y });
            // 画蛇头
            draw({ x: snkArr[0].x, y: snkArr[0].y }, '#0aa');
            // 条件:if 碰到食物,(同时判断若食物未初始化则画食物)
            !(((snkArr[0].x == food.x && snkArr[0].y == food.y) || (food.x == -1 && draw(snkArr.pop(), '#ccc')))
                // then 画食物
                && draw(((() => { while (snkArr.indexOf({ x: food.x = ~~(Math.random() * 29), y: food.y = ~~(Math.random() * 29) }) > -1); })(), food), '#fff'))
                // else 不去蛇尾(意为没碰到食物则去蛇尾)
                && draw(snkArr.pop(), '#ccc');
        } else {
            // 游戏结束
            alert('Game over!',
                location.reload()
            );
        }
    }, 150);
    
  • 相关阅读:
    BZOJ 3236: [Ahoi2013]作业
    BZOJ 3234: [Ahoi2013]立方体
    BZOJ 3235: [Ahoi2013]好方的蛇
    Hadoop 系列HDFS的Java API( Java API介绍)
    Hadoop 系列 HDFS 的JavaAPI Windows+IDEA+HDFS快速入门
    Hadoop 系列 HDFS:分布式文件系统(HDFS参数解读)
    Hadoop 系列 HDFS:分布式文件系统(HDFS集群模式)
    Hadoop 系列 HDFS:分布式文件系统(HDFS文件读写)
    Hadoop 系列 HDFS:分布式文件系统( HDFS概述)
    Hadoop中DataNode没有启动解决办法
  • 原文地址:https://www.cnblogs.com/gaolihai/p/13149750.html
Copyright © 2011-2022 走看看