Problem Statement – Snake Game LLD Question
Design a Snake Game where a snake moves on a 2D board, eats food to grow, and the game ends when the snake either collides with the wall or with itself. Provide a class-based object-oriented low-level design (LLD) for the snake game that includes class diagrams, key responsibilities, and game loop architecture.
This question is a popular low-level design interview question asked in system design rounds at product-based companies.
Functional Requirements
- A snake moves in four directions (up, down, left, right).
- The snake can eat food and grow longer.
- The game ends if the snake hits the wall or itself.
- Display the current score (length of the snake).
- Allow game reset/restart.
Core Classes in Snake Game LLD
We’ll break the system into multiple OOP components for clean modular design. These are the main classes:

Cell
Represents each cell on the game board.
public class Cell {
private int row, col;
// Constructor
public Cell(int row, int col) {
this.row = row;
this.col = col;
}
// Getters and setters
}
Direction(Enum)
public enum Direction {
UP, DOWN, LEFT, RIGHT
}
Snake
Manages the body, movement, and collision of the snake.
public class Snake {
private Deque<Cell> body;
private Direction currentDirection;
public Snake(Cell initialPosition) {
body = new LinkedList<>();
body.addFirst(initialPosition);
currentDirection = Direction.RIGHT;
}
public void move(Cell nextCell, boolean hasEaten) {
body.addFirst(nextCell);
if (!hasEaten) {
body.removeLast();
}
}
public boolean checkCollision(Cell cell) {
return body.contains(cell);
}
public void setDirection(Direction dir) {
currentDirection = dir;
}
public Direction getDirection() {
return currentDirection;
}
public Cell getHead() {
return body.peekFirst();
}
}
Food
Handles food generation logic.
public class Food {
private Cell position;
public Food(Cell position) {
this.position = position;
}
public Cell getPosition() {
return position;
}
public void generateNewPosition(Set<Cell> occupiedCells, int rows, int cols) {
// Avoid placing on snake body
// Implement random generation logic
}
}
Board
Manages board dimensions and valid positions.
public class Board {
private int rows, cols;
public Board(int rows, int cols) {
this.rows = rows;
this.cols = cols;
}
public boolean isWithinBounds(Cell cell) {
return cell.row >= 0 && cell.row < rows && cell.col >= 0 && cell.col < cols;
}
}
GameEngine
Controls the game loop, score tracking, and interactions.
public class GameEngine {
private Board board;
private Snake snake;
private Food food;
private boolean isGameOver;
private int score;
public GameEngine(int rows, int cols) {
board = new Board(rows, cols);
snake = new Snake(new Cell(rows / 2, cols / 2));
food = new Food(generateFoodPosition());
isGameOver = false;
score = 0;
}
public void update() {
if (isGameOver) return;
Cell nextCell = calculateNextCell(snake.getHead(), snake.getDirection());
if (!board.isWithinBounds(nextCell) || snake.checkCollision(nextCell)) {
isGameOver = true;
return;
}
boolean hasEaten = nextCell.equals(food.getPosition());
snake.move(nextCell, hasEaten);
if (hasEaten) {
score++;
food.generateNewPosition(getOccupiedCells(), board.getRows(), board.getCols());
}
}
private Set<Cell> getOccupiedCells() {
// Return snake body set for food generation
}
private Cell calculateNextCell(Cell head, Direction dir) {
// Calculate next head position
}
}
Key LLD Concepts Demonstrated:
- Encapsulation: Logic for snake, board, food, and game loop is modular.
- Responsibility Segregation: Each class does one job.
- Extensibility: Easy to add features like levels, powerups, and scoring UI.
- Real-time design pattern: Game loop with update logic.
Conclusion
Designing a Snake Game using low-level design principles is a great way to demonstrate object-oriented programming, modularity, and real-time systems architecture. Understanding such LLD questions prepares you well for interviews at companies like Amazon, Microsoft, and Atlassian.