返回介绍

solution / 0300-0399 / 0353.Design Snake Game / README_EN

发布于 2024-06-17 01:04:01 字数 10274 浏览 0 评论 0 收藏 0

353. Design Snake Game

中文文档

Description

Design a Snake game that is played on a device with screen size height x width. Play the game online if you are not familiar with the game.

The snake is initially positioned at the top left corner (0, 0) with a length of 1 unit.

You are given an array food where food[i] = (ri, ci) is the row and column position of a piece of food that the snake can eat. When a snake eats a piece of food, its length and the game's score both increase by 1.

Each piece of food appears one by one on the screen, meaning the second piece of food will not appear until the snake eats the first piece of food.

When a piece of food appears on the screen, it is guaranteed that it will not appear on a block occupied by the snake.

The game is over if the snake goes out of bounds (hits a wall) or if its head occupies a space that its body occupies after moving (i.e. a snake of length 4 cannot run into itself).

Implement the SnakeGame class:

  • SnakeGame(int width, int height, int[][] food) Initializes the object with a screen of size height x width and the positions of the food.
  • int move(String direction) Returns the score of the game after applying one direction move by the snake. If the game is over, return -1.

 

Example 1:

Input
["SnakeGame", "move", "move", "move", "move", "move", "move"]
[[3, 2, [[1, 2], [0, 1]]], ["R"], ["D"], ["R"], ["U"], ["L"], ["U"]]
Output
[null, 0, 0, 1, 1, 2, -1]

Explanation
SnakeGame snakeGame = new SnakeGame(3, 2, [[1, 2], [0, 1]]);
snakeGame.move("R"); // return 0
snakeGame.move("D"); // return 0
snakeGame.move("R"); // return 1, snake eats the first piece of food. The second piece of food appears at (0, 1).
snakeGame.move("U"); // return 1
snakeGame.move("L"); // return 2, snake eats the second food. No more food appears.
snakeGame.move("U"); // return -1, game over because snake collides with border

 

Constraints:

  • 1 <= width, height <= 104
  • 1 <= food.length <= 50
  • food[i].length == 2
  • 0 <= ri < height
  • 0 <= ci < width
  • direction.length == 1
  • direction is 'U', 'D', 'L', or 'R'.
  • At most 104 calls will be made to move.

Solutions

Solution 1

class SnakeGame:
  def __init__(self, width: int, height: int, food: List[List[int]]):
    self.m = height
    self.n = width
    self.food = food
    self.score = 0
    self.idx = 0
    self.q = deque([(0, 0)])
    self.vis = {(0, 0)}

  def move(self, direction: str) -> int:
    i, j = self.q[0]
    x, y = i, j
    match direction:
      case "U":
        x -= 1
      case "D":
        x += 1
      case "L":
        y -= 1
      case "R":
        y += 1
    if x < 0 or x >= self.m or y < 0 or y >= self.n:
      return -1
    if (
      self.idx < len(self.food)
      and x == self.food[self.idx][0]
      and y == self.food[self.idx][1]
    ):
      self.score += 1
      self.idx += 1
    else:
      self.vis.remove(self.q.pop())
    if (x, y) in self.vis:
      return -1
    self.q.appendleft((x, y))
    self.vis.add((x, y))
    return self.score


# Your SnakeGame object will be instantiated and called as such:
# obj = SnakeGame(width, height, food)
# param_1 = obj.move(direction)
class SnakeGame {
  private int m;
  private int n;
  private int[][] food;
  private int score;
  private int idx;
  private Deque<Integer> q = new ArrayDeque<>();
  private Set<Integer> vis = new HashSet<>();

  public SnakeGame(int width, int height, int[][] food) {
    m = height;
    n = width;
    this.food = food;
    q.offer(0);
    vis.add(0);
  }

  public int move(String direction) {
    int p = q.peekFirst();
    int i = p / n, j = p % n;
    int x = i, y = j;
    if ("U".equals(direction)) {
      --x;
    } else if ("D".equals(direction)) {
      ++x;
    } else if ("L".equals(direction)) {
      --y;
    } else {
      ++y;
    }
    if (x < 0 || x >= m || y < 0 || y >= n) {
      return -1;
    }
    if (idx < food.length && x == food[idx][0] && y == food[idx][1]) {
      ++score;
      ++idx;
    } else {
      int t = q.pollLast();
      vis.remove(t);
    }
    int cur = f(x, y);
    if (vis.contains(cur)) {
      return -1;
    }
    q.offerFirst(cur);
    vis.add(cur);
    return score;
  }

  private int f(int i, int j) {
    return i * n + j;
  }
}

/**
 * Your SnakeGame object will be instantiated and called as such:
 * SnakeGame obj = new SnakeGame(width, height, food);
 * int param_1 = obj.move(direction);
 */
class SnakeGame {
public:
  SnakeGame(int width, int height, vector<vector<int>>& food) {
    m = height;
    n = width;
    this->food = food;
    score = 0;
    idx = 0;
    q.push_back(0);
    vis.insert(0);
  }

  int move(string direction) {
    int p = q.front();
    int i = p / n, j = p % n;
    int x = i, y = j;
    if (direction == "U") {
      --x;
    } else if (direction == "D") {
      ++x;
    } else if (direction == "L") {
      --y;
    } else {
      ++y;
    }
    if (x < 0 || x >= m || y < 0 || y >= n) {
      return -1;
    }
    if (idx < food.size() && x == food[idx][0] && y == food[idx][1]) {
      ++score;
      ++idx;
    } else {
      int tail = q.back();
      q.pop_back();
      vis.erase(tail);
    }
    int cur = f(x, y);
    if (vis.count(cur)) {
      return -1;
    }
    q.push_front(cur);
    vis.insert(cur);
    return score;
  }

private:
  int m;
  int n;
  vector<vector<int>> food;
  int score;
  int idx;
  deque<int> q;
  unordered_set<int> vis;

  int f(int i, int j) {
    return i * n + j;
  }
};

/**
 * Your SnakeGame object will be instantiated and called as such:
 * SnakeGame* obj = new SnakeGame(width, height, food);
 * int param_1 = obj->move(direction);
 */
type SnakeGame struct {
  m   int
  n   int
  food  [][]int
  score int
  idx   int
  q   []int
  vis   map[int]bool
}

func Constructor(width int, height int, food [][]int) SnakeGame {
  return SnakeGame{height, width, food, 0, 0, []int{0}, map[int]bool{}}
}

func (this *SnakeGame) Move(direction string) int {
  f := func(i, j int) int {
    return i*this.n + j
  }
  p := this.q[0]
  i, j := p/this.n, p%this.n
  x, y := i, j
  if direction == "U" {
    x--
  } else if direction == "D" {
    x++
  } else if direction == "L" {
    y--
  } else {
    y++
  }
  if x < 0 || x >= this.m || y < 0 || y >= this.n {
    return -1
  }
  if this.idx < len(this.food) && x == this.food[this.idx][0] && y == this.food[this.idx][1] {
    this.score++
    this.idx++
  } else {
    t := this.q[len(this.q)-1]
    this.q = this.q[:len(this.q)-1]
    this.vis[t] = false
  }
  cur := f(x, y)
  if this.vis[cur] {
    return -1
  }
  this.q = append([]int{cur}, this.q...)
  this.vis[cur] = true
  return this.score
}

/**
 * Your SnakeGame object will be instantiated and called as such:
 * obj := Constructor(width, height, food);
 * param_1 := obj.Move(direction);
 */
class SnakeGame {
  private m: number;
  private n: number;
  private food: number[][];
  private score: number;
  private idx: number;
  private q: number[];
  private vis: Set<number>;

  constructor(width: number, height: number, food: number[][]) {
    this.m = height;
    this.n = width;
    this.food = food;
    this.score = 0;
    this.idx = 0;
    this.q = [0];
    this.vis = new Set([0]);
  }

  move(direction: string): number {
    const p = this.q[0];
    const i = Math.floor(p / this.n);
    const j = p % this.n;
    let x = i;
    let y = j;
    if (direction === 'U') {
      --x;
    } else if (direction === 'D') {
      ++x;
    } else if (direction === 'L') {
      --y;
    } else {
      ++y;
    }
    if (x < 0 || x >= this.m || y < 0 || y >= this.n) {
      return -1;
    }
    if (
      this.idx < this.food.length &&
      x === this.food[this.idx][0] &&
      y === this.food[this.idx][1]
    ) {
      ++this.score;
      ++this.idx;
    } else {
      const t = this.q.pop()!;
      this.vis.delete(t);
    }
    const cur = x * this.n + y;
    if (this.vis.has(cur)) {
      return -1;
    }
    this.q.unshift(cur);
    this.vis.add(cur);
    return this.score;
  }
}

/**
 * Your SnakeGame object will be instantiated and called as such:
 * var obj = new SnakeGame(width, height, food)
 * var param_1 = obj.move(direction)
 */

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文