move(direction) {
    // end::description[]
    // tag::solution[]
    let [r, c] = this.snake.back(); // head of the snake
    [r, c] = [r + this.dirs[direction][0], c + this.dirs[direction][1]];

    // check wall collision
    if (r < 0 || c < 0 || r >= this.height || c >= this.width) return -1;

    const [fr, fc] = this.food.front() || []; // peek
    if (r === fr && c === fc) {
      this.food.dequeue(); // remove eaten food.
    } else {
      this.snake.dequeue(); // remove snake's if not food was eaten
      this.tail.delete(this.tail.keys().next().value);
    }

    // check collision with snake's tail
    if (this.tail.has(`${r},${c}`)) return -1; // O(1)

    this.snake.enqueue([r, c]); // add new position
    this.tail.add(`${r},${c}`);

    return this.snake.size - 1; // return score (length of the snake - 1)
    // end::solution[]
    // tag::description[]
  }
Move snake 1 position into the given direction.
It returns the score or game over (-1) if the snake go out of bound or hit itself.
@param {string} direction - 'U' = Up, 'L' = Left, 'R' = Right, 'D' = Down.
@returns {number} - The current score (snake.length - 1).