Game Development 12 min read

How to Build a Classic Snake Game with MVC and Efficient Data Structures

This article explains how to implement the classic Snake game using the MVC pattern, detailing the model's grid representation, chain‑list versus array for the snake body, random food placement algorithms, view rendering optimizations with PIXI, and control APIs for game interaction.

Aotu Lab
Aotu Lab
Aotu Lab
How to Build a Classic Snake Game with MVC and Efficient Data Structures

MVC Architecture

The game follows the Model‑View‑Control pattern: the Model stores the game state, the View renders the state, and the Control processes user input and updates the Model.

Model

The playing field is an m × n grid (called zone) stored as a one‑dimensional array. Each cell holds 0 (empty), F (food) or S (snake). The snake itself is represented by a linked list of cell indices; food is a single index pointing to an empty cell.

Snake movement

Moving the snake consists of inserting a new head node and removing the tail node. A naïve array implementation uses unshift and pop:

function move(next) {
  snake.pop() && snake.unshift(next);
}

Because unshift is O(n), a true linked list with O(1) insert/delete is preferred. The author provides a Chain class (see https://github.com/leeenx/es6-utils#chain) that implements unshift and pop in constant time.

let snake = new Chain();

Random food placement

Three strategies are discussed:

Gambling algorithm : pick a random index; if occupied, retry. Expected O(1) but may loop indefinitely.

Safe linear scan : count empty cells, pick the rnd ‑th empty cell. Average complexity O(n/2).

Bet algorithm : pick a random index; if occupied return -1, then fall back to the safe scan. Average complexity O(n/4).

Safe linear‑scan implementation:

function feed() {
  let len = zone.length - snake.length;
  if (len === 0) return;
  let index = 0, count = 0;
  let rnd = (Math.random() * len >> 0) + 1;
  while (count !== rnd) {
    if (zone[index++] === 0) ++count;
  }
  return index - 1; // index of the new food
}

Bet algorithm (fallback to safe scan when the random pick fails):

function bet() {
  let rnd = Math.random() * zone.length >> 0;
  return zone[rnd] === 0 ? rnd : -1;
}
function feed() {
  let food = bet();
  if (food === -1) food = feed(); // safe scan as fallback
  return food;
}

View

The View uses the PIXI rendering engine. To keep rendering cheap, only the changed head or tail nodes are updated (incremental rendering), reducing the update cost to O(1)O(2).

// Incremental update example
let modelSnake = model.snake, viewSnake = view.snake;
while (viewSnake.length <= modelSnake.length) {
  let headA = modelSnake.next();
  if (headA.data === viewSnake.head.data) break;
  if (modelSnake.HEAD === headA.index) {
    viewSnake.unshift(headA.data);
  } else {
    viewSnake.insertAfter(0, headA.data);
  }
}

Control

Control exposes game APIs (init, start, pause, turn, etc.) and emits events (countdown, eat, before‑eat, gameover). Example of subscribing to an event:

snake.event.on("countdown", time => console.log("Remaining time:", time));

During each tick Control determines the next cell index ( next) and dispatches based on its content:

// B represents a wall collision
let cell = next === -1 ? B : zone[next];
switch (cell) {
  case F:  eat(); break;          // food
  case S:  collision(S); break;   // self‑collision
  case B:  collision(B); break;   // wall
  default: move(next); break;      // normal move
}

Source code

The complete implementation is available at https://github.com/leeenx/snake.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

algorithmJavaScriptMVCGame DevelopmentSnake
Aotu Lab
Written by

Aotu Lab

Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.