DEV Community

Alexya
Alexya

Posted on

The old school snake game with just 100 lines of JS code

If you grew up in the late '90s or early 2000s, you probably remember the classic Snake game.

It was simple, addictive, and a PUBG of early mobile gaming. I recently decided to recreate it using just 100 lines of Javascript.

Here is the HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Snake Game</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div class="container">
    <h1>Snake Game</h1>
    <div id="score">Score: 0</div>
    <div id="game-board"></div>
    <button id="start-restart">Start / Restart</button>
  </div>
  <script src="script.js"></script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

CSS:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: Arial, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #f3f3f3;
}

.container {
  text-align: center;
}

#game-board {
  display: grid;
  grid-template-columns: repeat(20, 20px);
  grid-template-rows: repeat(20, 20px);
  gap: 1px;
  background-color: #e0e0e0;
  margin: 20px auto;
  width: 400px;
  height: 400px;
  position: relative;
}

.cell {
  width: 20px;
  height: 20px;
  background-color: #f3f3f3;
}

.snake {
  background-color: green;
}

.food {
  background-color: red;
}

#score {
  font-size: 20px;
  margin: 10px 0;
}

button {
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
  border: none;
  background-color: #007BFF;
  color: white;
  border-radius: 5px;
}

button:hover {
  background-color: #0056b3;
}

Enter fullscreen mode Exit fullscreen mode

JS:

const board = document.getElementById('game-board');
const scoreDisplay = document.getElementById('score');
const startRestartButton = document.getElementById('start-restart');

const gridSize = 20;
const boardSize = gridSize * gridSize;
let snake = [42, 41, 40]; // Starting position
let direction = 1; // Moving right
let nextDirection = 1; // Buffer for next direction
let food = null;
let score = 0;
let intervalId = null;
const speed = 100;

function createBoard() {
  board.innerHTML = '';
  for (let i = 0; i < boardSize; i++) {
    const cell = document.createElement('div');
    cell.classList.add('cell');
    board.appendChild(cell);
  }
}

function updateBoard() {
  const cells = document.querySelectorAll('.cell');
  cells.forEach(cell => cell.classList.remove('snake', 'food'));

  snake.forEach(index => cells[index].classList.add('snake'));
  if (food !== null) cells[food].classList.add('food');
}

function spawnFood() {
  let newFood;
  do {
    newFood = Math.floor(Math.random() * boardSize);
  } while (snake.includes(newFood));
  food = newFood;
}

function moveSnake() {
  const head = snake[0];
  const newHead = getNewHead(head);

  // Check for collisions with itself
  if (snake.includes(newHead)) {
    clearInterval(intervalId);
    alert(`Game Over! Your final score is ${score}.`);
    return;
  }

  // Move snake
  snake.unshift(newHead);
  if (newHead === food) {
    score++;
    scoreDisplay.textContent = `Score: ${score}`;
    spawnFood();
  } else {
    snake.pop();
  }
  direction = nextDirection;
  updateBoard();
}

function getNewHead(head) {
  let newHead = head + nextDirection;

  if (nextDirection === 1 && head % gridSize === gridSize - 1) {
    newHead = head - (gridSize - 1); // Wrap to the left
  } else if (nextDirection === -1 && head % gridSize === 0) {
    newHead = head + (gridSize - 1); // Wrap to the right
  } else if (nextDirection === gridSize && head + gridSize >= boardSize) {
    newHead = head % gridSize; // Wrap to the top
  } else if (nextDirection === -gridSize && head - gridSize < 0) {
    newHead = head + boardSize - gridSize; // Wrap to the bottom
  }

  return newHead;
}

function changeDirection(e) {
  const key = e.key;

  // Prevent reversing direction
  if (key === 'ArrowUp' && direction !== gridSize) nextDirection = -gridSize;
  if (key === 'ArrowDown' && direction !== -gridSize) nextDirection = gridSize;
  if (key === 'ArrowLeft' && direction !== 1) nextDirection = -1;
  if (key === 'ArrowRight' && direction !== -1) nextDirection = 1;
}

function startGame() {
  snake = [42, 41, 40];
  direction = 1;
  nextDirection = 1;
  score = 0;
  scoreDisplay.textContent = `Score: ${score}`;
  spawnFood();
  updateBoard();

  if (intervalId) clearInterval(intervalId);
  intervalId = setInterval(moveSnake, speed);
}

createBoard();
startRestartButton.addEventListener('click', startGame);
document.addEventListener('keydown', changeDirection);

Enter fullscreen mode Exit fullscreen mode

You can make changes to above code according to what more creativity you can add.

Try playing here: https://codepen.io/alexya99/pen/EaYbaxo

As a game developer I have worked on many gaming projects. You can review our one of gaming portfolio site such as geometry dash spam full of such web based games.

Top comments (0)