DevSupporter
DevSupporter

Welcome back

Please enter your details to sign in to your account

Forgot password?
Sign in

Snake

QueueLinked ListBeginner

Classic snake game. Grow your snake using Queue data structure.

(Enter/Space)
๐ŸŽฏ Score0
โญ Best0
๐Ÿ“ Length3

  • Use Arrow Keys or WASD to control the snake
  • Eat the red food to grow longer and score points
  • Avoid hitting the walls or your own body
  • The snake speeds up as your score increases
  • On mobile, use swipe gestures or the on-screen D-pad

1. Queue Data Structure

The snake's body is implemented as a Queue. When the snake moves, we enqueue a new head at the front and dequeue the tail from the back. When food is eaten, we skip the dequeue โ€” making the snake grow. This gives us O(1) move operations regardless of snake length.

interface Point { x: number; y: number; }

class SnakeQueue {
  private body: Point[] = [];

  enqueue(point: Point): void {
    this.body.unshift(point);
  }

  dequeue(): Point | undefined {
    return this.body.pop();
  }

  get head(): Point { return this.body[0]; }
  get length(): number { return this.body.length; }
  includes(point: Point): boolean {
    return this.body.some(p => p.x === point.x && p.y === point.y);
  }
}
2. Collision Detection

Wall collision is a simple boundary check. Self-collision uses Array.some() to check if the next head position already exists in the body array โ€” O(n) time.

function isWallCollision(point: Point): boolean {
  return point.x < 0 || point.x >= GRID_SIZE ||
         point.y < 0 || point.y >= GRID_SIZE;
}

function isSelfCollision(snake: SnakeQueue, next: Point): boolean {
  return snake.some(seg =>
    seg.x === next.x && seg.y === next.y
  );
}
3. Game Loop with setInterval

The game loop runs on a fixed interval (tick rate). Each tick: calculate next position โ†’ check collisions โ†’ update snake โ†’ check food โ†’ re-render canvas. React state is kept minimal; the canvas is updated imperatively via useRef for performance.

const intervalRef = useRef<NodeJS.Timeout>();

useEffect(() => {
  if (gameStatus !== 'playing') return;
  intervalRef.current = setInterval(tick, speed);
  return () => clearInterval(intervalRef.current);
}, [gameStatus, speed]);

2026 ยฉ DevSupporter - Playground for Developers by DevSupporter