如何只用一个div实现原生js贪吃蛇(附源码 + 详细教程)

前言

闲来无聊想写一个贪吃蛇试试自己的js水平,那么如题所示要怎么只用一个div实现贪吃蛇呢。

首先canvas肯定是可以实现的,但是那就没意思啦。

其次动态生成div也不是不行,但是这样还是有多个div,而且频繁操作如此多的dom对性能影响很大。

这里通过一个神奇的属性实现效果 ------ box-shadow

box-shadow

box-shadow相信大家都很熟悉,阴影,其有5个可选参数,具体含义如下:

/* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 */
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);

值得注意的是其可以一次性写多个阴影,只需要通过逗号分隔即可:

/* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 */
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2), 2px 2px 2px 1px rgba(0, 0, 0, 0.2);

重点来了,如果我们将阴影模糊半径阴影扩散半径设置为0,那么会产生一个神奇的效果,形成一个个像素块

image.png

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    .box {
      width: 30px;
      height: 30px;
      background: linear-gradient(to right, red, blue);
      box-shadow: 30px 30px 0 red,90px 30px 0 blue;
    }
  </style>
</head>
<body>
  <div class="box"></div>
</body>
</html>

利用这个特性,我们只要改变div的box-shadow属性,就可以渲染出n个像素块,我们只需要关心box-shaow的值是什么。

贪吃蛇

项目地址: https://github.com/pengzhijian/tan-chi-she/tree/main 只有一个html文件,不想看的可以直接去文章底部复制完整代码。

详细教程如下:

1.html和css代码

html只要新增一个div标签即可:

<body>
    <div class="game-box"></div>
</body>

css主要设置了div的宽高,以及left、width、color属性,box-shaow的初始值只是为了方便查看效果,
body设置了宽高和边框,body就是贪吃蛇的场地:

        * {
            margin: 0;
            padding: 0;
        }
        .game-box {
            position: absolute;
            left: -20px;
            width: 20px;
            height: 20px;
            color: rgba(red, green, blue, 1);
            box-shadow: 20px 20px 0 red,20px 80px 0 red;
        }
        body {
            position: relative;
            margin-left: 20px;
            border: 1px solid black;
            width: 95vw;
            height: 95vh;
        }

2. js代码

1. 初始化

这里我通过一个Snake类去实现贪吃蛇,构造函数的参数有三个分别是 speed(蛇的速度),long(蛇初始长度),width(单个方块的宽度),此外添加了一个snake属性,作为dom节点,一个snakeArr属性去存储蛇各个节点信息:

    class Snake {
        /***
         * speed:蛇速度
         * long:蛇初始长度
         * width:单个方块宽度
         * ***/
        constructor(speed, long, width) {
            this.speed = speed;
            this.long = long;
            this.width = width;
            // 添加一个snake属性,作为dom节点:
            this.snake = document.querySelector('.game-box');
        }
        // 蛇dom
        snake = null
        // 蛇节点存放
        snakeArr = []
    }

然后根据传参width去设置div宽高及初始的left,此处默认蛇从左上角出现,
场地的大小默认是width的n倍,且根据窗口的大小动态调整,具体实现如下:

    this.snake.style.width = width + 'px';
    this.snake.style.height = width + 'px';
    this.snake.style.left = -width + 'px';
    // 自动设置场地大小
    document.body.style.width = Math.floor(document.body.clientWidth / this.width) * this.width + 'px';
    document.body.style.height = Math.floor(document.body.clientHeight / this.width) * this.width + 'px';

最后根据传参long设置初始的蛇节点,蛇节点有4个属性x(节点的x坐标)、y(节点的y坐标)、color(节点的颜色)、direction(节点的运动方向):

    for (let i = 0; i < this.long; i++) {
        if (i == this.long - 1) {
            this.snakeArr.push({
                x: i,
                y: 0,
                color: 'orange',
                direction: 'right'
            })
        } else {
            this.snakeArr.push({
                x: i,
                y: 0,
                color: 'red',
                direction: 'right'
            })
        }
    }
2. 更新视图元素

渲染视图只需要把每个蛇节点坐标和颜色赋值给 boxShadow即可,注意的是最后一个元素不加逗号:

  // 更新视图元素
  updateSnake() {
      let boxShadow = this.snakeArr.reduce((pre, cur, index) => {
          if (index == this.snakeArr.length - 1) {
              return pre + `${cur.x * this.width}px ${cur.y * this.width}px 0 ${cur.color}`
          }
          return pre + `${cur.x * this.width}px ${cur.y * this.width}px 0 ${cur.color},`
      }, '')
      this.snake.style.boxShadow = boxShadow;
  }

尝试运行效果如下:

image.png

  <script>
    class Snake {
      /***
       * speed:蛇速度
       * long:蛇初始长度
       * width:单个方块宽度
       * ***/
      constructor(speed, long, width) {
        this.speed = speed;
        this.long = long;
        this.width = width;
        // 添加一个snake属性,作为dom节点:
        this.snake = document.querySelector('.game-box');
        this.snake.style.width = width + 'px';
        this.snake.style.height = width + 'px';
        this.snake.style.left = -width + 'px';
        // 自动设置场地大小
        document.body.style.width = Math.floor(document.body.clientWidth / this.width) * this.width + 'px';
        document.body.style.height = Math.floor(document.body.clientHeight / this.width) * this.width + 'px';
        for (let i = 0; i < this.long; i++) {
          if (i == this.long - 1) {
            this.snakeArr.push({
              x: i,
              y: 0,
              color: 'orange',
              direction: 'right'
            })
          } else {
            this.snakeArr.push({
              x: i,
              y: 0,
              color: 'red',
              direction: 'right'
            })
          }
        }
        this.updateSnake();
      }
      // 蛇dom
      snake = null
      // 蛇节点存放
      snakeArr = []

      // 更新视图元素
      updateSnake() {
          let boxShadow = this.snakeArr.reduce((pre, cur, index) => {
              if (index == this.snakeArr.length - 1) {
                  return pre + `${cur.x * this.width}px ${cur.y * this.width}px 0 ${cur.color}`
              }
              return pre + `${cur.x * this.width}px ${cur.y * this.width}px 0 ${cur.color},`
          }, '')
          this.snake.style.boxShadow = boxShadow;
      }
    }

    let snake = new Snake(1, 5, 50);
  </script>
3. 运动逻辑

蛇的运动整体逻辑也很简单,只要判断前进的方向,然后将蛇最后一个节点的位置移动到第一个节点的位置即可,俗称头插法,值得注意的有还需要改变之前头部的颜色和方向,蛇的速度通过setInterval的触发时间实现,具体实现。

重点:运行的方向不能和之前的方向相反,要做一个判断。

      // 蛇头的方向
      direction = 'right'
      beforeDirection = 'right'
      // 运行状态
      moveTimer = null
      // 蛇运动控制
      move() {
        this.moveTimer = setInterval(() => {
          // 将最后一个删掉,插入第一个,变化颜色和位置即可
          let startBody = this.snakeArr.shift();
          let lastBody = this.snakeArr.at(-1);
          startBody.color = 'orange';
          lastBody.color = 'red';
          if (this.beforeDirection == 'right' && this.direction == 'left' || this.beforeDirection == 'up' && this.direction == 'down' || this.beforeDirection == 'left' && this.direction == 'right' || this.beforeDirection == 'down' && this.direction == 'up') {
            this.direction = this.beforeDirection;
          }
          if (this.direction === 'right') {
            startBody.x = lastBody.x + 1;
            startBody.y = lastBody.y;
          } else if (this.direction === 'left') {
            startBody.x = lastBody.x - 1;
            startBody.y = lastBody.y;
          } else if (this.direction === 'down') {
            startBody.x = lastBody.x;
            startBody.y = lastBody.y + 1;
          } else if (this.direction === 'up') {
            startBody.x = lastBody.x;
            startBody.y = lastBody.y - 1;
          }
          startBody.direction = this.direction;
          this.beforeDirection = this.direction;
          this.snakeArr.push(startBody);
          this.updateSnake();
        }, 500 / this.speed)
      }

在构造函数加上 this.move()后,效果如下:

蛇运动.gif

4. 游戏控制器(上下左右移动)

核心思路:按下按键添加方向,松开按键删除方向,以最后按下的按键为主,允许中途切换方向。

这里我通过一个数组存储按下的按键,然后遍历数组有相同的设置方向即可,具体实现如下:

      gameTimer = null
      // 游戏控制器,上下左右控制
      gameControl() {
        let keyCodes = []
        // 模式2为 wasd控制,模式1为 上下左右控制
        let model = 1;
        document.addEventListener('keydown', function (event) {
          keyCodes.includes(event.keyCode) ? '' : keyCodes.push(event.keyCode)
          console.log('down_key', keyCodes)
        })
        document.addEventListener('keyup', function (event) {
          keyCodes.splice(keyCodes.indexOf(event.keyCode), 1)
        })
        this.gameTimer = setInterval(() => {
          if (model === 1 && keyCodes.length > 0) {
            keyCodes.forEach(item => {
              switch (item) {
                case 37:
                  this.direction = 'left';
                  break;
                case 38:
                  this.direction = 'up';
                  break;
                case 39:
                  this.direction = 'right';
                  break;
                case 40:
                  this.direction = 'down';
                  break;
              }
            })
          }
          if (model === 2 && keyCodes.length > 0) {
            keyCodes.forEach(item => {
              switch (item) {
                case 65:
                  this.direction = 'left';
                  break;
                case 87:
                  this.direction = 'up';
                  break;
                case 68:
                  this.direction = 'right';
                  break;
                case 83:
                  this.direction = 'down';
                  break;
              }
            })
          }
        }, 20)
      }

在构造函数加上 this.gameControl()后,效果如下:

控制运动.gif

5. 死亡检测

死亡情况有两种:

  1. 头和身子合并,判断死亡。
  2. 头碰到墙壁,判断死亡。
      // 死亡检测
      deadControl() {
          // 1.当头和身子合并,判断死亡
          let head = this.snakeArr.at(-1)
          let isDead = false
          isDead = this.snakeArr.some((item, index) => {
              if (head.x === item.x && head.y === item.y && index != this.snakeArr.length - 1) {
                  item.color = 'blue';
                  this.updateSnake();
                  return true
              }
              return false;
          })

          // 2.当碰到墙壁时,判断死亡
          let sceneWidthCount = Math.floor(document.body.clientWidth / this.width);
          let sceneHightCount = Math.floor(document.body.clientHeight / this.width);
          // y要大于等于,x要小于1,实测得出结论
          if (head.x < 1 || head.y < 0 || head.x > sceneWidthCount || head.y >= sceneHightCount) {
              isDead = true;
          }
          return isDead;
      }

在move函数的updateSnake()之前添加死亡检测代码:

      // 死亡检测
      if (this.deadControl()) {
        console.log('dead!!!!!!')
        alert('你挂了!!!!!!');
        clearInterval(this.moveTimer);
        clearInterval(this.controlTimer);
        clearInterval(this.gameTimer);
        this.moveTimer = null;
        this.controlTimer = null;
        this.gameTimer = null;
        return;
      }
      this.updateSnake();

效果如下:

死亡检测.gif

6. 生成食物

需求:每次屏幕只有一个食物,被吃完了继续生成一个食物。

生成食物的重点是要在非蛇身的地方随机生成食物,此处实现思路为将游戏场景抽象为 1----n 的方格,根据每个方格的数字去算出x和y,比如 5 * 4 的场景,那么最后一个方格的数字就是20。

      foodArr = []
      // 被吃完了生成一个食物
      foodControl() {
        if (this.foodArr.length < 1) {
          let sceneWidthCount = Math.floor(document.body.clientWidth / this.width);
          let sceneHightCount = Math.floor(document.body.clientHeight / this.width);
          // 场景总共的格子数
          let countSum = sceneWidthCount * sceneHightCount;
          // 排除有食物和身子的格子
          let countArr = [];
          for (let i = 0; i < countSum; i++) {
            countArr.push(i + 1);
            for (let j = 0; j < this.snakeArr.length; j++) {
              if (this.snakeArr[j].x + sceneWidthCount * this.snakeArr[j].y == i + 1) {
                countArr.splice(countArr.indexOf(i + 1), 1)
                break;
              }
            }
          }
          let randomNum = Math.floor(Math.random() * countArr.length);
          let newX = parseInt(countArr[randomNum] % sceneWidthCount);
          let newY = countArr[randomNum] % sceneWidthCount == 0 ? Math.floor((countArr[randomNum]) / sceneWidthCount) - 1 : Math.floor((countArr[randomNum]) / sceneWidthCount);
          this.foodArr.push({
            x: newX == 0 ? 9 : newX,
            y: newY,
            color: 'pink'
          })
        }
      }

在每次刷新视图时将食物数组加进去一起刷新:

      // 更新视图元素
      updateSnake() {
          this.foodControl();
          let allArr = this.foodArr.concat(this.snakeArr)
          let boxShadow = allArr.reduce((pre, cur, index) => {
              if (index == allArr.length - 1) {
                  return pre + `${cur.x * this.width}px ${cur.y * this.width}px 0 ${cur.color}`
              }
              return pre + `${cur.x * this.width}px ${cur.y * this.width}px 0 ${cur.color},`
          }, '')
          this.snake.style.boxShadow = boxShadow;
      }
7. 吃食物判定

当头部位置和食物位置重合时判定,吃完了在尾巴处添加一个新的节点,新节点的位置需要根据尾巴节点的位置判断。(尾插法?)

      // 吃食物判定
      eatControl() {
        // 头部和食物的位置判断,食物目前是每次只有一个,吃完了再生成,吃了在尾部插入一个新的身体,根据尾部节点的位置判断
        if (this.snakeArr.at(-1).x == this.foodArr[0].x && this.snakeArr.at(-1).y == this.foodArr[0].y) {
          let newX = '';
          let newY = '';
          if (this.snakeArr[0].direction == 'left') {
            newX = this.snakeArr[0].x + 1;
            newY = this.snakeArr[0].y;
          } else if (this.snakeArr[0].direction == 'right') {
            newX = this.snakeArr[0].x - 1;
            newY = this.snakeArr[0].y;
          } else if (this.snakeArr[0].direction == 'top') {
            newX = this.snakeArr[0].x;
            newY = this.snakeArr[0].y + 1;
          } else if (this.snakeArr[0].direction == 'down') {
            newX = this.snakeArr[0].x;
            newY = this.snakeArr[0].y - 1;
          }
          this.snakeArr.unshift({
            x: newX,
            y: newY,
            color: 'red'
          });
          this.foodArr.splice(0, 1);
        }
      }

在每次运动刷新前添加吃食物判定(move函数中):

      // 食物检测
      this.eatControl();

完整.gif

8. 胜利检测

当蛇节点数量等于场景格子数时判断胜利:

if (this.snakeArr.length == Math.floor(document.body.clientWidth / this.width) * Math.floor(document.body.clientHeight / this.width)) {
    console.log('win!!!!!!!')
    alert('游戏通关!!!!!!!!')
    clearInterval(this.moveTimer)
    clearInterval(this.controlTimer)
    this.moveTimer = null;
    this.controlTimer = null;
    return;
}

完整html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>贪吃蛇</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .game-box {
            position: absolute;
            left: -20px;
            width: 20px;
            height: 20px;
            color: rgba(red, green, blue, 1);
            box-shadow: 20px 20px 0 red,20px 80px 0 red;
        }
        body {
            position: relative;
            margin-left: 20px;
            border: 1px solid black;
            width: 95vw;
            height: 95vh;
        }
    </style>
</head>
<body>
    <div class="game-box"></div>
    <script>
        class Snake {
            /***
             * speed:蛇速度
             * long:蛇初始长度
             * width:单个方块宽度
             * ***/
            constructor(speed, long, width) {
                this.speed = speed;
                this.long = long;
                this.width = width;
                // 添加一个snake属性,作为dom节点:
                this.snake = document.querySelector('.game-box');
                this.snake.style.width = width + 'px';
                this.snake.style.height = width + 'px';
                this.snake.style.left = -width + 'px';
                // 自动设置场地大小
                document.body.style.width = Math.floor(document.body.clientWidth / this.width) * this.width + 'px';
                document.body.style.height = Math.floor(document.body.clientHeight / this.width) * this.width + 'px';
                for (let i = 0; i < this.long; i++) {
                    if (i == this.long - 1) {
                        this.snakeArr.push({
                            x: i,
                            y: 0,
                            color: 'orange',
                            direction: 'right'
                        })
                    } else {
                        this.snakeArr.push({
                            x: i,
                            y: 0,
                            color: 'red',
                            direction: 'right'
                        })
                    }
                }
                this.updateSnake()
                this.move()
                this.gameControl()
            }
            // 蛇头的方向
            direction = 'right'
            beforeDirection = 'right'
            // 蛇节点存放
            snakeArr = []
            // 蛇dom
            snake = null
            // 运行状态
            moveTimer = null
            controlTime = null
            gameTimer = null
            // 食物存储
            foodArr = []

            // 更新视图元素
            updateSnake() {
                this.foodControl();
                let allArr = this.foodArr.concat(this.snakeArr)
                let boxShadow = allArr.reduce((pre, cur, index) => {
                    if (index == allArr.length - 1) {
                        return pre + `${cur.x * this.width}px ${cur.y * this.width}px 0 ${cur.color}`
                    }
                    return pre + `${cur.x * this.width}px ${cur.y * this.width}px 0 ${cur.color},`
                }, '')
                this.snake.style.boxShadow = boxShadow;
            }

            // 蛇运动控制
            move() {
                this.moveTimer = setInterval(() => {
                    // 将最后一个删掉,插入第一个,变化颜色和位置即可
                    let startBody = this.snakeArr.shift();
                    let lastBody = this.snakeArr.at(-1)
                    startBody.color = 'orange';
                    lastBody.color = 'red';
                    // console.log(11111112222222222, this.direction)
                    if (this.beforeDirection == 'right' && this.direction == 'left' || this.beforeDirection == 'up' && this.direction == 'down' || this.beforeDirection == 'left' && this.direction == 'right' || this.beforeDirection == 'down' && this.direction == 'up') {
                        this.direction = this.beforeDirection;
                    }
                    if (this.direction === 'right') {
                        startBody.x = lastBody.x + 1;
                        startBody.y = lastBody.y;
                    } else if (this.direction === 'left') {
                        startBody.x = lastBody.x - 1;
                        startBody.y = lastBody.y;
                    } else if (this.direction === 'down') {
                        startBody.x = lastBody.x;
                        startBody.y = lastBody.y + 1;
                    } else if (this.direction === 'up') {
                        startBody.x = lastBody.x;
                        startBody.y = lastBody.y - 1;
                    }
                    startBody.direction = this.direction;
                    this.beforeDirection = this.direction;
                    this.snakeArr.push(startBody);
                    if (this.snakeArr.length == Math.floor(document.body.clientWidth / this.width) * Math.floor(document.body.clientHeight / this.width)) {
                        console.log('win!!!!!!!')
                        alert('游戏通关!!!!!!!!')
                        clearInterval(this.moveTimer)
                        clearInterval(this.controlTimer)
                        this.moveTimer = null;
                        this.controlTimer = null;
                        return;
                    }
                    // 死亡检测
                    if (this.deadControl()) {
                        console.log('dead!!!!!!')
                        alert('你挂了!!!!!!');
                        clearInterval(this.moveTimer);
                        clearInterval(this.controlTimer);
                        clearInterval(this.gameTimer);
                        this.moveTimer = null;
                        this.controlTimer = null;
                        this.gameTimer = null;
                        return;
                    }
                    // 食物检测
                    this.eatControl();
                    this.updateSnake();
                }, 500 / this.speed)
            }

            // 游戏控制器,上下左右控制
            gameControl() {
                let keyCodes = []
                let model = 1;
                document.addEventListener('keydown',function (event) {
                    keyCodes.includes(event.keyCode) ? '' : keyCodes.push(event.keyCode)
                    console.log('down_key', keyCodes)
                })
                document.addEventListener('keyup',function (event) {
                    keyCodes.splice(keyCodes.indexOf(event.keyCode), 1)
                })
                this.gameTimer = setInterval(() => {
                    if (model === 1 && keyCodes.length > 0) {
                        keyCodes.forEach(item => {
                            switch (item) {
                            case 37:
                                this.direction = 'left';
                                break;
                            case 38:
                                this.direction = 'up';
                                break;
                            case 39:
                                this.direction = 'right';
                                break;
                            case 40:
                                this.direction = 'down';
                                break;
                            }
                        })
                    }
                    if (model === 2 && keyCodes.length > 0) {
                        keyCodes.forEach(item => {
                            switch (item) {
                            case 65:
                                this.direction = 'left';
                                break;
                            case 87:
                                this.direction = 'up';
                                break;
                            case 68:
                                this.direction = 'right';
                                break;
                            case 83:
                                this.direction = 'down';
                                break;
                            }
                        })
                    }
                }, 20)
            }

            // 死亡检测
            deadControl() {
                // 1.当头和身子合并,判断死亡
                let head = this.snakeArr.at(-1)
                let isDead = false
                isDead = this.snakeArr.some((item, index) => {
                    if (head.x === item.x && head.y === item.y && index != this.snakeArr.length - 1) {
                        item.color = 'blue';
                        this.updateSnake();
                        return true
                    }
                    return false;
                })
                // console.log(111111111111111, isDead)

                // 2.当碰到墙壁时,判断死亡
                let sceneWidthCount = Math.floor(document.body.clientWidth / this.width);
                let sceneHightCount = Math.floor(document.body.clientHeight / this.width);
                // console.log(77777777777, head)
                // y要大于等于,x要小于1,实测得出结论
                if (head.x < 1 || head.y < 0 || head.x > sceneWidthCount || head.y >= sceneHightCount) {
                    // console.log(2222222222, isDead)
                    isDead = true;
                }
                return isDead;
            }

            // 被吃完了生成一个食物
            foodControl() {
                if (this.foodArr.length < 1) {
                    let sceneWidthCount = Math.floor(document.body.clientWidth / this.width);
                    let sceneHightCount = Math.floor(document.body.clientHeight / this.width);
                    // 场景总共的格子数
                    let countSum = sceneWidthCount * sceneHightCount;
                    // 排除有食物和身子的格子
                    let countArr = [];
                    for (let i = 0; i < countSum; i ++) {
                        countArr.push(i + 1);
                        // console.log(66666666, JSON.stringify(countArr))
                        for (let j = 0; j < this.snakeArr.length; j ++) {
                            if (this.snakeArr[j].x + sceneWidthCount * this.snakeArr[j].y == i + 1) {
                                countArr.splice(countArr.indexOf(i + 1), 1)
                                // console.log(9999999999, this.snakeArr[j], i, JSON.stringify(countArr))
                                break;
                            }
                        }
                    }
                    let randomNum = Math.floor(Math.random() * countArr.length);
                    let newX = parseInt(countArr[randomNum] % sceneWidthCount);
                    let newY = countArr[randomNum] % sceneWidthCount == 0 ? Math.floor((countArr[randomNum]) / sceneWidthCount) - 1 : Math.floor((countArr[randomNum]) / sceneWidthCount);
                    this.foodArr.push({
                        x: newX == 0 ? 9 : newX,
                        y: newY,
                        color: 'yellow'
                    })
                    // console.log(88888777777777,randomNum,countArr[randomNum], this.foodArr)
                }
            }

            // 吃食物判定
            eatControl() {
                // 头部和食物的位置判断,食物目前是每次只有一个,吃完了再生成,吃了在尾部插入一个新的身体,根据尾部节点的位置判断
                if (this.snakeArr.at(-1).x == this.foodArr[0].x && this.snakeArr.at(-1).y == this.foodArr[0].y) {
                    let newX = '';
                    let newY = '';
                    if (this.snakeArr[0].direction == 'left') {
                        newX = this.snakeArr[0].x + 1;
                        newY = this.snakeArr[0].y;
                    } else if (this.snakeArr[0].direction == 'right') {
                        newX = this.snakeArr[0].x - 1;
                        newY = this.snakeArr[0].y;
                    } else if (this.snakeArr[0].direction == 'top') {
                        newX = this.snakeArr[0].x;
                        newY = this.snakeArr[0].y + 1;
                    } else if (this.snakeArr[0].direction == 'down') {
                        newX = this.snakeArr[0].x;
                        newY = this.snakeArr[0].y - 1;
                    }
                    this.snakeArr.unshift({
                        x: newX,
                        y: newY,
                        color: 'red'
                    });
                    this.foodArr.splice(0, 1);
                    // console.log(333333333333, JSON.stringify(this.snakeArr), this.foodArr)
                }
            }
        }

        let snake = new Snake(1, 5, 50);
    </script>
</body>
</html>
  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值