|
| 1 | +/** |
| 2 | + * 353. Design Snake Game |
| 3 | + * https://leetcode.com/problems/design-snake-game/ |
| 4 | + * Difficulty: Medium |
| 5 | + * |
| 6 | + * Design a Snake game that is played on a device with screen size height x width. Play the |
| 7 | + * game online if you are not familiar with the game. |
| 8 | + * |
| 9 | + * The snake is initially positioned at the top left corner (0, 0) with a length of 1 unit. |
| 10 | + * |
| 11 | + * You are given an array food where food[i] = (ri, ci) is the row and column position of a |
| 12 | + * piece of food that the snake can eat. When a snake eats a piece of food, its length and |
| 13 | + * the game's score both increase by 1. |
| 14 | + * |
| 15 | + * Each piece of food appears one by one on the screen, meaning the second piece of food will |
| 16 | + * not appear until the snake eats the first piece of food. |
| 17 | + * |
| 18 | + * When a piece of food appears on the screen, it is guaranteed that it will not appear on a |
| 19 | + * block occupied by the snake. |
| 20 | + * |
| 21 | + * The game is over if the snake goes out of bounds (hits a wall) or if its head occupies a |
| 22 | + * space that its body occupies after moving (i.e. a snake of length 4 cannot run into itself). |
| 23 | + * |
| 24 | + * Implement the SnakeGame class: |
| 25 | + * - SnakeGame(int width, int height, int[][] food) Initializes the object with a screen of size |
| 26 | + * height x width and the positions of the food. |
| 27 | + * - int move(String direction) Returns the score of the game after applying one direction move |
| 28 | + * by the snake. If the game is over, return -1. |
| 29 | + */ |
| 30 | + |
| 31 | +/** |
| 32 | + * @param {number} width |
| 33 | + * @param {number} height |
| 34 | + * @param {number[][]} food |
| 35 | + */ |
| 36 | +var SnakeGame = function(width, height, food) { |
| 37 | + this.width = width; |
| 38 | + this.height = height; |
| 39 | + this.food = food; |
| 40 | + this.foodIndex = 0; |
| 41 | + this.score = 0; |
| 42 | + this.snake = [[0, 0]]; |
| 43 | + this.bodySet = new Set(['0,0']); |
| 44 | +}; |
| 45 | + |
| 46 | +/** |
| 47 | + * @param {string} direction |
| 48 | + * @return {number} |
| 49 | + */ |
| 50 | +SnakeGame.prototype.move = function(direction) { |
| 51 | + const head = [...this.snake[0]]; |
| 52 | + |
| 53 | + if (direction === 'U') head[0]--; |
| 54 | + else if (direction === 'D') head[0]++; |
| 55 | + else if (direction === 'L') head[1]--; |
| 56 | + else if (direction === 'R') head[1]++; |
| 57 | + |
| 58 | + if (head[0] < 0 || head[0] >= this.height || head[1] < 0 || head[1] >= this.width) { |
| 59 | + return -1; |
| 60 | + } |
| 61 | + |
| 62 | + const tail = this.snake.pop(); |
| 63 | + this.bodySet.delete(`${tail[0]},${tail[1]}`); |
| 64 | + |
| 65 | + const headKey = `${head[0]},${head[1]}`; |
| 66 | + if (this.bodySet.has(headKey)) { |
| 67 | + return -1; |
| 68 | + } |
| 69 | + |
| 70 | + this.snake.unshift(head); |
| 71 | + this.bodySet.add(headKey); |
| 72 | + |
| 73 | + if (this.foodIndex < this.food.length && head[0] === this.food[this.foodIndex][0] |
| 74 | + && head[1] === this.food[this.foodIndex][1]) { |
| 75 | + this.snake.push(tail); |
| 76 | + this.bodySet.add(`${tail[0]},${tail[1]}`); |
| 77 | + this.foodIndex++; |
| 78 | + this.score++; |
| 79 | + } |
| 80 | + |
| 81 | + return this.score; |
| 82 | +}; |
0 commit comments