Design Snake Game

Let us see how to design a basic Snake Game which provides the following functionalities:

• Snake can move in a given direction and when it eats the food, the length of snake increases.
• When snake crosses itself, the game will over.
• Food will be generated at given interval.

Asked In: Amazon, Microsoft, and many more interviews
This question is asked in interviews to Judge the Object Oriented Design skill of a candidate. So, first of all we should think about the classes.

The main classes will be:

1. Snake
2. Cell
3. Board
4. Game

The class Game represents the body of our program. It stores information about the snake and the board.

The Cell class represents the one point of display / board. It contains the row no, column no and the information about it i.e. it is empty or there is a food on it or is it a part of snake body?

filter_none

edit
close

play_arrow

link
brightness_4
code

// To represent a cell of display board.
public class Cell {
  
    private final int row, col;
    private CellType cellType;
  
    public Cell(int row, int col)
    {
        this.row = row;
        this.col = col;
    }
  
    public CellType getCellType()
    {
        return cellType;
    }
  
    public void setCellType(CellType cellType)
    {
        this.cellType = cellType;
    }
  
    public int getRow()
    {
        return row;
    }
  
    public int getCol()
    {
        return col;
    }
}

chevron_right


filter_none

edit
close

play_arrow

link
brightness_4
code

// Enum for different cell types
  
public enum CellType {
  
    EMPTY,
    FOOD,
    SNAKE_NODE;
}

chevron_right


Now, the Snake class, which contains the body and head.
We have used LinkedList to store the body because we can add a cell in O(1).
Grow method will be called when it eats the food. Other methods are self-explanatory.

filter_none

edit
close

play_arrow

link
brightness_4
code

// To represent a snake
import java.util.LinkedList;
  
public class Snake {
  
    private LinkedList<Cell> snakePartList = new LinkedList<>();
    private Cell head;
  
    public Snake(Cell initPos)
    {
        head = initPos;
        snakePartList.add(head);
    }
  
    public void grow()
    {
        snakePartList.add(head);
    }
  
    public void move(Cell nextCell)
    {
        System.out.println("Snake is moving to " +
             nextCell.getRow() + " " + nextCell.getCol());
        Cell tail = snakePartList.removeLast();
        tail.setCellType(CellType.EMPTY);
  
        head = nextCell;
        snakePartList.addFirst(head);
    }
  
    public boolean checkCrash(Cell nextCell)
    {
        System.out.println("Going to check for Crash");
        for (Cell cell : snakePartList) {
            if (cell == nextCell) {
                return true;
            }
        }
  
        return false;
    }
  
    public LinkedList<Cell> getSnakePartList()
    {
        return snakePartList;
    }
  
    public void setSnakePartList(LinkedList<Cell> snakePartList)
    {
        this.snakePartList = snakePartList;
    }
  
    public Cell getHead()
    {
        return head;
    }
  
    public void setHead(Cell head)
    {
        this.head = head;
    }
}

chevron_right


The Board class represents the display. It is a matrix of Cells. It has a method generateFood which generates the
food at random position.

filter_none

edit
close

play_arrow

link
brightness_4
code

public class Board {
  
    final int ROW_COUNT, COL_COUNT;
    private Cell[][] cells;
  
    public Board(int rowCount, int columnCount)
    {
        ROW_COUNT = rowCount;
        COL_COUNT = columnCount;
  
        cells = new Cell[ROW_COUNT][COL_COUNT];
        for (int row = 0; row < ROW_COUNT; row++) {
            for (int column = 0; column < COL_COUNT; column++) {
                cells[row][column] = new Cell(row, column);
            }
        }
    }
  
    public Cell[][] getCells()
    {
        return cells;
    }
  
    public void setCells(Cell[][] cells)
    {
        this.cells = cells;
    }
  
    public void generateFood()
    {
        System.out.println("Going to generate food");
        int row = (int)(Math.random() * ROW_COUNT);
        int column = (int)(Math.random() * COL_COUNT);
  
        cells[row][column].setCellType(CellType.FOOD);
        System.out.println("Food is generated at: " + row + " " + column);
    }
}

chevron_right


The main class (Game) which keeps the instance of Snake and Board. It’s method “update” needs to be called at a fixed intervals (with the help of user input).

filter_none

edit
close

play_arrow

link
brightness_4
code

// To represent Snake Game
public class Game {
  
    public static final int DIRECTION_NONE = 0, DIRECTION_RIGHT = 1
         DIRECTION_LEFT = -1, DIRECTION_UP = 2, DIRECTION_DOWN = -2;
    private Snake snake;
    private Board board;
    private int direction;
    private boolean gameOver;
  
    public Game(Snake snake, Board board)
    {
        this.snake = snake;
        this.board = board;
    }
  
    public Snake getSnake()
    {
        return snake;
    }
  
    public void setSnake(Snake snake)
    {
        this.snake = snake;
    }
  
    public Board getBoard()
    {
        return board;
    }
  
    public void setBoard(Board board)
    {
        this.board = board;
    }
  
    public boolean isGameOver()
    {
        return gameOver;
    }
  
    public void setGameOver(boolean gameOver)
    {
        this.gameOver = gameOver;
    }
  
    public int getDirection()
    {
        return direction;
    }
  
    public void setDirection(int direction)
    {
        this.direction = direction;
    }
  
    // We need to update the game at regular intervals,
    // and accept user input from the Keyboard.
    public void update()
    {
        System.out.println("Going to update the game");
        if (!gameOver) {
            if (direction != DIRECTION_NONE) {
                Cell nextCell = getNextCell(snake.getHead());
  
                if (snake.checkCrash(nextCell)) {
                    setDirection(DIRECTION_NONE);
                    gameOver = true;
                }
                else {
                    snake.move(nextCell);
                    if (nextCell.getCellType() == CellType.FOOD) {
                        snake.grow();
                        board.generateFood();
                    }
                }
            }
        }
    }
  
    private Cell getNextCell(Cell currentPosition)
    {
        System.out.println("Going to find next cell");
        int row = currentPosition.getRow();
        int col = currentPosition.getCol();
  
        if (direction == DIRECTION_RIGHT) {
            col++;
        }
        else if (direction == DIRECTION_LEFT) {
            col--;
        }
        else if (direction == DIRECTION_UP) {
            row--;
        }
        else if (direction == DIRECTION_DOWN) {
            row++;
        }
  
        Cell nextCell = board.getCells()[row][col];
  
        return nextCell;
    }
  
    public static void main(String[] args)
    {
  
        System.out.println("Going to start game");
  
        Cell initPos = new Cell(0, 0);
        Snake initSnake = new Snake(initPos);
        Board board = new Board(10, 10);
        Game newGame = new Game(initSnake, board);
        newGame.gameOver = false;
        newGame.direction = DIRECTION_RIGHT;
  
        // We need to update the game at regular intervals,
        // and accept user input from the Keyboard.
  
        // here I have just called the different methods
        // to show the functionality
        for (int i = 0; i < 5; i++) {
            if (i == 2)
                newGame.board.generateFood();
            newGame.update();
            if (i == 3)
                newGame.direction = DIRECTION_RIGHT;
            if (newGame.gameOver == true)
                break;
        }
    }
}

chevron_right


Reference:
http://massivetechinterview.blogspot.com/2015/10/snake-game-design.html



My Personal Notes arrow_drop_up

SDE 2 at Adobe || Ex - Paytm || NIT Allahabad

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.