🐍 Add a Classic Snake Game to Your Website

Following the massive success of the Dino game, why not try another classic that everybody loves? The iconic "Snake" game is perfect for keeping visitors on your page longer, challenging their reflexes. Discover how simple it is to build this game using only HTML and JavaScript!

πŸ•Ή️ Interactive Demo

Score: 0
Click the game or Press Enter/Space to Start

πŸ“„ Full Game Code

Copy and paste this code into an HTML page on your blog or platform. It works natively as a single script file, with no external images required!

<div style="text-align:center; font-family: monospace;">
  <canvas id="snakeCanvas" width="400" height="400" style="border:4px solid #333; background-color: #111; margin: 0 auto; display:block; border-radius: 4px;"></canvas>
  <div id="snakeScore" style="font-weight:bold; font-size:18px; margin-top: 10px;">Score: 0</div>
  <div id="snakeStartMsg" style="font-size:16px; color:#555;">Click the game or Press <strong>Enter</strong>/<strong>Space</strong> to Start</div>
  <div id="snakeGameOver" style="display:none; font-size:18px; color:red;">
    πŸ’₯ Game Over! Score: <span id="snakeFinalScore"></span><br />
    <button onclick="restartSnakeGame()" style="margin-top:10px; padding:8px 16px; cursor: pointer; background: #333; color: white; border: none; border-radius: 4px; font-weight: bold;">Play Again</button>
  </div>
</div>

<script>
const snakeCanvas = document.getElementById("snakeCanvas");
const snakeCtx = snakeCanvas.getContext("2d");

const gridSize = 20;
let snake = [];
let food = {};
let dx = 0, dy = 0, snakeScore = 0, gameInterval, snakeRunning = false, snakeGameOver = false;

function initSnakeGame() {
  snake = [ { x: 160, y: 160 }, { x: 140, y: 160 }, { x: 120, y: 160 } ];
  dx = gridSize; dy = 0; snakeScore = 0; snakeRunning = true; snakeGameOver = false;
  
  document.getElementById("snakeScore").textContent = "Score: 0";
  document.getElementById("snakeGameOver").style.display = "none";
  document.getElementById("snakeStartMsg").style.display = "none";
  
  spawnFood();
  clearInterval(gameInterval);
  gameInterval = setInterval(updateSnake, 100);
}

function spawnFood() {
  food = {
    x: Math.floor(Math.random() * (snakeCanvas.width / gridSize)) * gridSize,
    y: Math.floor(Math.random() * (snakeCanvas.height / gridSize)) * gridSize
  };
  snake.forEach(part => {
    if (part.x === food.x && part.y === food.y) spawnFood();
  });
}

function updateSnake() {
  if (!snakeRunning) return;
  const head = { x: snake[0].x + dx, y: snake[0].y + dy };

  if (head.x < 0 || head.x >= snakeCanvas.width || head.y < 0 || head.y >= snakeCanvas.height) {
    endSnakeGame(); return;
  }

  for (let i = 0; i < snake.length; i++) {
    if (snake[i].x === head.x && snake[i].y === head.y) {
      endSnakeGame(); return;
    }
  }

  snake.unshift(head);

  if (head.x === food.x && head.y === food.y) {
    snakeScore += 10;
    document.getElementById("snakeScore").textContent = "Score: " + snakeScore;
    spawnFood();
  } else {
    snake.pop();
  }
  drawSnakeGame();
}

function drawSnakeGame() {
  snakeCtx.fillStyle = "#111"; // Background
  snakeCtx.fillRect(0, 0, snakeCanvas.width, snakeCanvas.height);
  snakeCtx.fillStyle = "#ff4757"; // Apple
  snakeCtx.fillRect(food.x, food.y, gridSize - 1, gridSize - 1);
  snake.forEach((part, index) => {
    snakeCtx.fillStyle = index === 0 ? "#2ed573" : "#7bed9f"; // Head vs Body
    snakeCtx.fillRect(part.x, part.y, gridSize - 1, gridSize - 1);
  });
}

function endSnakeGame() {
  snakeRunning = false; snakeGameOver = true; clearInterval(gameInterval);
  document.getElementById("snakeFinalScore").textContent = snakeScore;
  document.getElementById("snakeGameOver").style.display = "block";
}

function restartSnakeGame() { initSnakeGame(); }

// Initial screen
snakeCtx.fillStyle = "#111";
snakeCtx.fillRect(0, 0, snakeCanvas.width, snakeCanvas.height);
snakeCtx.fillStyle = "#2ed573";
snakeCtx.font = "bold 24px monospace";
snakeCtx.textAlign = "center";
snakeCtx.fillText("SNAKE JS", snakeCanvas.width/2, snakeCanvas.height/2);
snakeCtx.font = "14px monospace";
snakeCtx.fillText("Click to start", snakeCanvas.width/2, snakeCanvas.height/2 + 30);

snakeCanvas.addEventListener("click", () => {
  if (!snakeRunning && !snakeGameOver) initSnakeGame();
});

document.addEventListener("keydown", (e) => {
  if (["Space", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.code) && (snakeRunning || !snakeGameOver)) e.preventDefault();
  
  if ((e.code === "Space" || e.code === "Enter" || e.key.includes("Arrow")) && !snakeRunning && !snakeGameOver) {
    initSnakeGame();
    if (e.code === "ArrowUp") { dx = 0; dy = -gridSize; }
    else if (e.code === "ArrowDown") { dx = 0; dy = gridSize; }
    else if (e.code === "ArrowLeft") { dx = -gridSize; dy = 0; }
  }

  if (!snakeRunning) return;
  const up = dy === -gridSize, down = dy === gridSize, right = dx === gridSize, left = dx === -gridSize;

  if (e.code === "ArrowLeft" && !right) { dx = -gridSize; dy = 0; }
  if (e.code === "ArrowUp" && !down) { dx = 0; dy = -gridSize; }
  if (e.code === "ArrowRight" && !left) { dx = gridSize; dy = 0; }
  if (e.code === "ArrowDown" && !up) { dx = 0; dy = gridSize; }
});
</script>

πŸ’‘ Developer Tip

In this code, we make sure that the arrow keys (ArrowUp, ArrowDown, etc.) do not scroll the page while the game is running. Adding e.preventDefault() to the key events is essential for the User Experience (UX), ensuring the page doesn't jump around when visitors are trying to beat their high score!

Comments

Popular posts from this blog

How to Compare Strings in C#: Best Practices

C# vs Rust: Performance Comparison Using a Real Algorithm Example

Is Python Becoming Obsolete? A Look at Its Limitations in the Modern Tech Stack