A snake game is a classic programming exercise you can use to improve your programming and problem-solving skills. You can create the game in a web browser using HTML, CSS, and JavaScript.

In the game, you control a snake that moves around a board. The snake grows in size as you collect food. The game will end if you collide with your own tail or any of the walls.

How to Create the UI for the Canvas

Use HTML and CSS to add the canvas for the snake to move around on. There are many other HTML and CSS projects you can practice on, if you need to revise any basic concepts.

You can refer to this project’s GitHub repository for the full source code.

  1. Create a new file called "index.html".
  2. Open the file using any text editor such as Visual Code or Atom. Add the basic HTML code structure:
            <!doctype html>
    <html lang="en-US">
      <head>
        <title>Snake Game</title>
      </head>
      <body>

      </body>
    </html>
  3. Inside the body tag, add a canvas to represent the game board for the snake.
            <h2>Snake Game</h2>
    <div id="game">
      <canvas id="snake"></canvas>
    </div>
  4. In the same folder as your HTML file, create a new file called "styles.css".
  5. Inside, add some CSS for the overall web page. You can also style your website using other essential CSS tips and tricks.
            #game {
      width:400px;
      height:400px;
      margin:0 auto;
      background-color:#eee;
    }
    h2 {
      text-align:center;
      font-family:Arial;
      font-size:36px;
    }
  6. Inside your HTML file, add a link to the CSS in the head tag:
            <link rel="stylesheet" type="text/css" href="styles.css">
        
  7. To view the canvas, open your "index.html" file in a web browser.
    Snake game with empty canvas

How to Draw the Snake

In the example below, the black line represents the snake:

Snake game with snake example

Multiple squares or "segments" make up the snake. As the snake grows, the number of squares also increases. At the beginning of the game, the snake’s length is one piece.

  1. Inside your HTML file, link to a new JavaScript file at the bottom of the body tag:
            <body>
      <!-- Your code here -->
      <script src="script.js"></script>
    </body>
  2. Create script.js and start by getting the DOM element of the canvas:
            var canvas = document.getElementById("snake");
        
  3. Set the context for the canvas HTML element. In this case, you want the game to render a 2d canvas. This will allow you to draw multiple shapes or images onto the HTML element.
            var canvas2d = canvas.getContext("2d");
        
  4. Set other in-game variables such as whether the game has ended, and the height and width of the canvas:
            var gameEnded = false;
    canvas.width = 400;
    canvas.height = 400;
  5. Declare a variable called "snakeSegments". This will hold the number of "squares" that the snake will take up. You can also create a variable to keep track of the snake's length:
            var snakeSegments = [];
    var snakeLength = 1;
  6. Declare the initial X and Y position of the snake:
            var snakeX = 0;
    var snakeY = 0;
  7. Create a new function. Inside, add the starting snake piece to the snakeSegments array, with its starting X and Y coordinates:
            function moveSnake() {
      snakeSegments.unshift({ x: snakeX, y: snakeY });
    }
  8. Create a new function. Inside, set the fill style to black. This is the color it will use to draw the snake:
            function drawSnake() {
      canvas2d.fillStyle = "black";
    }
  9. For every segment that makes up the snake's size, draw a square with a width and height of 10 pixels:
              for (var i = 0; i < snakeSegments.length; i++) {
        canvas2d.fillRect(snakeSegments[i].x, snakeSegments[i].y, 10, 10);
      }
  10. Create a game loop that will run every 100 milliseconds. This will cause the game to constantly draw the snake in its new position, which will be very important when the snake starts moving:
            function gameLoop() {
      moveSnake();
     drawSnake();
  11. Open the "index.html" file in a web browser to see the snake at its smallest size in its starting position.
    Snake game with snake in starting position

How to Make the Snake Move

Add some logic to move the snake in different directions, depending on what button the player presses on the keyboard.

  1. At the top of the file, declare the initial direction of the snake:
            var directionX = 10;
    var directionY = 0;
  2. Add an event handler that fires when the player presses a key:
            document.onkeydown = function(event) {

    };
  3. Inside the event handler, change the direction that the snake is moving, based on the pressed key:
            switch (event.keyCode) {
      case 37: // Left arrow
        directionX = -10;
        directionY = 0;
        break;
      case 38: // Up arrow
        directionX = 0;
        directionY = -10;
        break;
      case 39: // Right arrow
        directionX = 10;
        directionY = 0;
        break;
      case 40: // Down arrow
        directionX = 0;
        directionY = 10;
        break;
    }
  4. In the moveSnake() function, use the direction to update the X and Y coordinates of the snake. For example, if the snake needs to move left, the X direction will be "-10". This will update the X coordinate to remove 10 pixels for every frame of the game:
            function moveSnake() {
      snakeSegments.unshift({ x: snakeX, y: snakeY });
      snakeX += directionX;
      snakeY += directionY;
    }
  5. The game currently does not remove previous segments while the snake is moving. This will make the snake look like this:
  6. Snake example without deleting segments
    To fix this, clear the canvas before drawing the new snake in each frame, at the beginning of the drawSnake() function:
            canvas2d.clearRect(0, 0, canvas.width, canvas.height);
        
  7. You will also need to remove the last element of the snakeSegments array, inside the moveSnake() function:
            while (snakeSegments.length > snakeLength) {
      snakeSegments.pop();
    }
  8. Open the "index.html" file and press the left, right, up, or down keys to move the snake.
    Single snake piece moving around board

How to Add Food Onto the Canvas

Add dots to the board game to represent food pieces for the snake.

  1. Declare a new variable at the top of the file to store an array of food pieces:
            var dots = [];
        
  2. Create a new function. Inside, generate random X and Y coordinates for the dots. You can also ensure that only 10 dots are on the board at any time:
            function spawnDots() {
      if(dots.length < 10) {
        var dotX = Math.floor(Math.random() * canvas.width);
        var dotY = Math.floor(Math.random() * canvas.height);
        dots.push({ x: dotX, y: dotY });
      }
    }
  3. After generating the X and Y coordinates for the food, draw them onto the canvas using a red color:
            for (var i = 0; i < dots.length; i++) {
      canvas2d.fillStyle = "red";
      canvas2d.fillRect(dots[i].x, dots[i].y, 10, 10);
    }
  4. Call the new spawnDots() function inside the game loop:
            function gameLoop() {
      moveSnake();
      drawSnake();
      spawnDots();
      if(!gameEnded) {
        setTimeout(gameLoop, 100);
      }
    }
  5. Open the "index.html" file to view the food on the game board.
    Snake game with food pieces on board

How to Make the Snake Grow

You can make the snake grow by incrementing its length when it collides with a food dot.

  1. Create a new function. Inside it, loop through every element in the dots array:
            function checkCollision() {
      for (var i = 0; i < dots.length; i++) {
            
      }
    }
  2. If the snake's position matches the coordinates of any dots, increment the snake's length, and delete the dot:
            if (snakeX < dots[i].x + 10 && 
      snakeX + 10 > dots[i].x &&
      snakeY < dots[i].y + 10 &&
      snakeY + 10 > dots[i].y) {
        snakeLength++;
        dots.splice(i, 1);
    }
  3. Call the new checkCollision() function in the game loop:
            function gameLoop() {
      moveSnake();
      drawSnake();
      spawnDots();
      checkCollision();
      if(!gameEnded) {
        setTimeout(gameLoop, 100);
      }
    }
  4. Open the "index.html" file in a web browser. Move the snake using the keyboard to collect the food pieces and grow the snake.
    Snake game with final game board

How to End the Game

To end the game, check if the snake collided with its own tail, or any of the walls.

  1. Create a new function to print a "Game Over" alert.
            function gameOver() {
      setTimeout(function() {
        alert("Game over!");
      }, 500);
      gameEnded = true
    }
  2. Inside the checkCollision() function, check if the snake hit any of the canvas' walls. If so, call the gameOver() function:
            if (snakeX < -10 || 
      snakeY < -10 ||
      snakeX > canvas.width+10 ||
      snakeY > canvas.height+10) {
        gameOver();
    }
  3. To check if the head of the snake collided with any of the tail segments, loop through each piece of the snake:
            for (var i = 1; i < snakeSegments.length; i++) {

    }
  4. Inside the for-loop, check if the location of the snake's head matches any of the tail segments. If so, this means the head collided with a tail, so end the game:
            if (snakeX === snakeSegments[i].x && snakeY === snakeSegments[i].y) {
      gameOver();
    }
  5. Open the "index.html" file in a web browser. Try to hit a wall or your own tail to end the game.
    Game over alert in snake game

Learning JavaScript Concepts Through Games

Creating games can be a great way to make your learning experience more enjoyable. Keep making more games to continue improving your JavaScript knowledge.