Snakes and Ladders Game using Vanilla JS - A Tutorial

Snakes and Ladders Game using Vanilla JS - A Tutorial

·

10 min read

Hey everyone, If you are trying to master Javascript, there is no better way to do it than making projects. The Snakes and Ladders game will help you build your foundation strong and it is completely beginner friendly.

Snakes and Ladders is a classic Indian board game. It is played on a game board with numbered and gridded squares. As the name suggests a number of "snakes" and "ladders" are pictured throughout the board, each of them connecting two blocks. The goal of the game is to take your game piece from the start (bottom block) to the finish (top block) by taking advantage of the ladders and avoiding those pesky snakes. As simple as it sounds it is a cool and fun game.

In this tutorial, I'll show you how to create your Snakes and Ladders game step-by-step. But before moving further, I would suggest that you should have a basic understanding of HTML, CSS and Javascript.

These are the steps we will be going through:

  1. Create the HTML page.

  2. Create Dice.

  3. Create a 6*6 matrix with numbers.

  4. Change player position based on current dice value.

  5. Add Snakes and Ladders.

Step 1: Create the HTML Page

For the starters, we will have to create our index.html page with 2 divs:

  1. The first div will be our container to store the game board. Here we are giving it the CSS class as "parent-div" to further select the div through document.querySelector()

  2. The second div will hold the dice button and a span to display the rolled number.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Snake and Ladders</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div class="parent-div"></div>
    <div class="dice-game">
        <button id="dice">Roll the Dice</button>
        <span id="dice-count" class="result"></span>
    </div>
</body>
<script src="myscript.js"></script>
</html>

Step 2: Create Dice

As we are done with our HTML part, we will dive into Javascript which will be the soul of our game. First, we will create our dice. Rolling dice gives us random numbers to move our game piece forward.

Function: rollDice()

We will wrap all our dice-related operations in a new function called rollDice() to keep the logic separate.

Tip💡: Making a dedicated function for each operation helps to separate the logic and increases code readability.

We will use the button element which we already have created in our HTML document.

function rollDice() {
    const result = document.querySelector('#dice-count')
    const randomNumber = Math.floor(Math.random() * 6) + 1
    result.innerHTML = "You rolled " + randomNumber
    // Here we will insert images in our dice button
    // Here we will use conditional statements to move our game piece forward
}

In the above code, we are generating random numbers and displaying them in the innerHTML of the span which is a sibling to our button element.

We will add an event listener on our dice and give the reference of rollDice function so that whenever it gets clicked, the same process of generating a new number and adding it to the innerHTML of span repeats.

const dice = document.getElementById('dice')
dice.addEventListener('click', rollDice)

Note: Don't stress about the formula for generating random numbers, you can easily get that on Google :)

Add Images on Dice

As we have our dice ready to generate random values, we will add different images to our dice to display according to the rolled number.

Our dice rolls numbers from 1 to 6, so we need a total of 6 images to represent each side of a dice. I have already saved 6 images in a folder named Images.

We will use an array with 6 items (image names) to change images according to the rolled number.

const IMAGE_URL = ["dice1.png", "dice2.png", "dice3.png", "dice4.png", "dice5.png", "dice6.png"]

We have our array ready and we will code our image-changing mechanism inside the rollDice() function as I mentioned earlier in the comments in the JS file.

function rollDice() {
    // The code above will remain as it is
    dice.style.backgroundImage = `url(Images/${IMAGE_URL[randomNumber - 1]})`
    dice.innerHTML = ""
}

I will use string interpolation like the above to change images. There are many other ways to do the same as I have saved my images in a pattern. Try to figure those out yourself after going through this tutorial.

We will also have to replace our text node "Roll the Dice" with an empty string once the dice get clicked.

Step 3: Create a 6*6 Matrix with Numbers

As we are done with our dice, it's time to get our hands busier and create our game board.

Create the board

For this tutorial, we will take a 6*6 board.

To not overcomplicate things I will take a premade array called NUMBERS holding 6 more arrays inside which are representing rows. Each row consists of 6 numbers, the numbers in the odd row are in descending order and vice versa.

The array for a 4*4 matrix with the same logic will look like:

[ [16, 15, 14, 13],
[9, 10, 11, 12],
[8, 7, 6, 5],
[1, 2, 3, 4] ]

We will select our "parent-div" with the document.querySelector() and store it in a variable called div.

Now we will have to run 2 loops on our NUMBERS array:

  1. The first loop will run to create rows with the class "rows" and inside it, we will run our second loop.

  2. The second loop will run to create squares inside those rows with the class "buttons" and a data attribute named "data-count" to distinguish each block from one another based on their unique numbers.

As there are 6 arrays inside our NUMBERS array and each array has 6 items (numbers) in it, there will be 6 rows and a total of 36 blocks.

Look at this for a better understanding

const NUMBERS = [
    [36, 35, 34, 33, 32, 31],
    [25, 26, 27, 28, 29, 30],
    [24, 23, 22, 21, 20, 19],
    [13, 14, 15, 16, 17, 18],
    [12, 11, 10, 9, 8, 7],
    [1, 2, 3, 4, 5, 6]
];

Function: createBoard()

Just like earlier, we will wrap all our board-related operations in the createBoard() function.

function createBoard () { 
const div = document.querySelector('.parent-div')
for (let i = 0; i < NUMBERS.length; i++) {
        const rowDiv = document.createElement('div')
        rowDiv.classList.add('rows')
        for (let j = 0; j < NUMBERS[i].length; j++) {
            const count = NUMBERS[i][j];
            const boardDiv = document.createElement('div')
            boardDiv.classList.add('buttons')
            boardDiv.setAttribute('data-count', count)
            boardDiv.innerHTML = count
            // Here we will use conditional statements to add our snakes and ladders
            rowDiv.appendChild(boardDiv)
        }
        div.appendChild(rowDiv)
    }
}

In the code above we created our game board and appended it to our parent div.

Now when the code is wrapped in a function. We will use an event listener on the window and give the reference of our createBoard() function so that the game board generates as soon as the page loads.

window.addEventListener("load", createBoard)

Step 4: Change Player Position

Our game board and dice are ready and now it is time for the task of adding a moving game piece mechanism to let the player change the position of its game piece on the board according to the rolled number.

We will add a CSS class active on the active block to distinguish it from the other blocks and show the player's actual position.

Function: startGame()

Normally the Snakes and Ladders game doesn't start until you roll 6 on the dice. So we will create a function to start the game and use a conditional statement on it later to trigger it as soon as the player rolls 6 on the dice.

function startGame() {
    const blockToBeActive = document.querySelector(`[data-count='1']`)
    blockToBeActive.classList.add('active')
}

Once the game starts, active class will be applied to the first block(bottom block) of our game board.

Function: continueGame()

As the name suggests the continueGame() function will hold all our operations to let us continue our game until we reach the finish line.

function continueGame(diceValue) {
    const activeBlock = document.querySelector('.active');
    const activeNumber = Number(activeBlock.dataset.count);
    let newPosition = activeNumber + diceValue;

    // We will add conditional statements here for snakes and ladders functionality

    if (newPosition <= 36) {
        activeBlock.classList.remove('active');
        const newActiveBlock = document.querySelector(`[data-count='${newPosition}']`);
        newActiveBlock.classList.add('active');
    }

    if (newPosition === 36) {
        endGame();
    }
}

Inside the continueGame() function:

  • We will take diceValue as an argument.

  • Then we will define a variable activeBlock and store all the blocks having active class inside it.

  • Then we will define a variable activeNumber and inside it we will store the dataset-count of the activeBlock after parsing it into a number.

  • Next, we will define a variable newPosition which will be equal to activeNumber + diceValue (randomly rolled dice number)

We are done defining variables now and it's time to use conditional statements.

In the above code we have used 2 conditional statements :

  1. In the first statement, we are passing a condition that whether the value of the newPosition is less than 36.

    • If it's true then we will remove the active class from the activeBlock

    • Then we will create a new variable newActiveBlock and inside it we will store the block whose dataset-count matches the value of newPosition with the help of document.querySelector()

    • Then we will add the active CSS class on newActiveBlock

  2. In the second statement, we are passing a condition that whether the value of the newPosition is equal to 36.
    If the condition is true then we will trigger the endGame() function.

Function: endGame()

The endGame() function will end the game with an alert message as soon as the value of the newPosition is equal to 36, which is the last block.

function endGame() {
    alert('Congratulations, You won the game.')
}

Shifting the code inside rollDice() function

function rollDice() {
    // The above code will remain as it is
    const isGameActive = document.querySelector(`.active`)
    if (randomNumber === 6 && !isGameActive) {
        alert("Game Begins")
        startGame()
    } else {
        continueGame(randomNumber)
    }
}

Step 5: Add Snakes and Ladders

Now when our game board is ready, it is time to do justice to the game's name and add snakes and ladders which will add the fun element.

For that, we will make 2 objects named SNAKES and LADDERS respectively.
The key of the object will be the number of the blocks on which we want snakes or ladders and its value will be the number of blocks on which we want our player to get promoted or demoted.

const LADDERS = {
    3 : 7,
    10 : 14,
    17 : 22,
    21 : 26,
    30 : 35
}

const SNAKES = {
    8 : 2,
    16 : 6,
    23 : 15,
    28 : 18,
    33 : 25
}

Now we have our objects to give reference to, we will use conditional statements inside the second loop of our createBoard() function before appending it to rowDiv.
So that whenever a block gets created, it goes through our SNAKES and LADDERS object and if the dataset-count of a block matches with the key of an object, it prints either a snake or a ladder on that block.

if (LADDERS[count]) {
                const ladderSpan = document.createElement('span');
                ladderSpan.setAttribute('class', 'ladder')
                ladderSpan.innerHTML = "🚪"
                boardDiv.appendChild(ladderSpan)
            }

if (SNAKES[count]) {
                const snakeSpan = document.createElement('span');
                snakeSpan.setAttribute('class', 'snakes')
                snakeSpan.innerHTML = "🐍"
                boardDiv.appendChild(snakeSpan)
            }

My browser is not reading the ladder emoji for some reason, that's why I have used a door emoji instead.

Handling Snakes and Ladders

We printed snakes and ladders on the game board but they should also function to manipulate the game piece position whenever they get stepped on.

We will use 2 conditional statements inside the continueGame() function for the same.

 if (LADDERS[newPosition]) {
        const ladderEnd = LADDERS[newPosition]
        alert(`You've found a ladder! Climbing from ${newPosition} to ${ladderEnd}`);
        newPosition = ladderEnd;
    }

 if (SNAKES[newPosition]) {
        const snakesEnd = SNAKES[newPosition]
        alert(`You got bit by a snake! Descending from ${newPosition} to ${snakesEnd}`)
        newPosition = snakesEnd;
    }
  1. In the first statement, we are passing a condition that whether the newPosition matches with any of the keys of the LADDERS object.
    If it does then we have defined a variable ladderEnd inside that statement in which we will store the value of that particular key.
    After that, we will alert the user they have climbed a ladder from newPosition to ladderEnd using string interpolation.
    Then we will change the value of the newPosition which will be equal to ladderEnd

  2. The second statement is almost the same as the first, we will perform the same actions but this time on the SNAKES object.

    Similarly, we will alert the user they got bit by a snake and are going down from newPosition to snakesEnd using string interpolation.
    We are replacing all the operations on ladderEnd with snakesEnd here.
    As a result the value of the newPosition here will be equal to snakesEnd

Note: We will insert these 2 conditional statements before our existing 2 to make it work. The correct order of the conditional statements plays an important role in Javascript.

Wrapping up

Alright folks!
We have successfully created our Snakes and Ladders Game. Wasn't it fun?
I hope you enjoyed making this simple project with me :)

Thanks for reading, you can follow me on Twitter if you liked this article.