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.

Other Atlassian Questions asked:

References:

Categorized in:

LLD, Must Know LLD,