How I Made a Snake Game Out of Checkboxes

Recreating the snake game in JavaScript

Ferenc Almasi
Jan 22 · 7 min read
Snake Game in JavaScript made with checkboxes
Snake Game in JavaScript made with checkboxes

I always liked the idea of experimenting with classic games and recreating them in the browser. They always seem to offer some new challenges and it’s interesting to see what can be achieved inside the browser.

This time, I had an idea about recreating the snake game out of checkboxes that are chasing a radio button; the apple.

It was fascinating to see what the logic is behind it and how this can be translated into JavaScript. Since I’m also into animation, I finished the whole project with a nice CSS transformation when the game is over.

Here is the end result and with that said, let’s see how the game was created.

Playing the snake game
Playing the snake game
The output of this tutorial

Creating the Index File

The very first thing was of course to create the HTML file:

I broke down the whole project into four different files:

I also added some minor styles for aligning the world into the center of the screen:


Defining Configurations

I made a separate configuration file so I can tweak around with some of the numbers that make up the game, without having to touch the logic. Let’s take a look at what is inside:

Here, I defined the variables that are playing a key part in making up the game, such as:

The value of the snake
The value of the snake
The content of the snake variable holding the coordinates for each segment

Generating the World

To get things started, I first generated some checkboxes on the screen. This is where I used the worldSize variable.

I’ve created two loops inside each other. One for the rows and one for the columns. Inside each, I’ve created a div for each row containing exactly 10 checkboxes; the value of worldSize.

After this, you’ll end up with a 10x10 grid. After this, we can start working on the core game logic.


Adding Helper Functions

But before doing that, I created some helper functions that come in handy later on.

Like getting a checkbox by (x, y) position, making it checked/unchecked or placing an apple in the world, which will be represented by a radio button.

Getting the position of the apple

We also need a function for getting the position of the apple, since we want to know when the snake picks up one.

To know that, I simply looped through each row and column and checked if the type of the input is a radio. Note that I also needed to convert row.children into an array since you can’t call forEach on an HTMLCollection.

When the snake retrieves the apple, we want to display it in another random position.

Get a random position

For this, I’ve created a separate function called getRandomPosition:

It gets all the available positions in the world by looping through each row and column and checking if the current item is an unchecked checkbox.

We don’t want to add the position of the apple into the availablePositions array so we need to check specifically if it’s a checkbox. If the position is free, I push it into the array and choose a random index from it to return a random position.

Increasing score

And of course, every player wants the reward. Once the snake collects an apple we should reward the player with a score. I’ve put the scoring into a separate function:

Using the functions in the snake game
Using the functions in the snake game
Easily get positions and set scores with the set of functions

Handling User Input

With all this in place, the next step was to handle user input. I wanted to make the snake move with arrow keys. The configuration file holds all key code for this.

So, I attached a keydown event listener on the document and switched between the key codes to set the direction either to up, down, left, or right.

I also checked for the current direction. If the snake already moves upwards and the player presses the down key, we don’t want to switch directions as that would mean the snake can collide with itself simply by moving around.

And here I set the moveInterval to a setInterval calling the move function which will actually make the snake move. But before taking a look into how the function handles the movement, I quickly set up the game.js file:

We start at the startPoint which is defined in the config file. Remember that since the variable is an array, and the checkItemAt function expects two parameters (x, y), we need to use spread.

And of course, we also want to place the apple in a random position each time the game begins.


Adding Movement

So, finally, the core logic of the game that checks the appropriate checkboxes. To fully understand how the implementation works, let’s first see what the logic is behind checking the checkboxes.

Here is the flow we want to follow:

The reason we only care about the position of the head and the very last element, but not the intermediate checkboxes is the following:

The calculation between each step
The calculation between each step

We only need to get the new position of the head and place it at the very beginning of the array. This is what array.unshift does.

Then we simply get rid of the last segment with array.pop. So, now every coordinate in the array is updated with just two lines.

I defined a variable for each position and created a function for updating the position of the snake.

Here, I simply loop the snake array and check each checkbox at the given position. Then comes the part where I update the position of the head:

Since I wanted the snake to wrap around the world and not die if it hits the edges, I checked whether it reaches the end of the world. If it does, I simply move it to the other end, either pos1 or pos10, depending on the direction.

Lastly, we also need to check if the position of the head matches the position of the apple. That means we need to add a new segment to the snake as well as placing the apple somewhere else.

In that case, since the length of the snake increases, we don’t need to remove the very last item from the array. Otherwise, we do.


Game Over

Now, if the snake hits itself and nothing happens, then there’s no challenge. So by adding the following if statement to the move function, we can clear the map, write out Game Over…, and play a nice animation.

We simply need to check if the next position of the head is a checkbox and if that position is already checked.

I’ve also added a playWave function that first animates the head and then the rest of the inputs. The animation is simple: scale the input to 200% then scale it back to its original size:

Whenever an input gets the wave class, it will be animated.

Playing the wave animation
Playing the wave animation

The trick here is to delay the animation for each row. We want to get each input starting from (1, 1) all the way to (10, 10) in order. Then we can loop through them and delay the animation by their index:

And now the game is ready to be played.


Conclusion

Experimenting with the creation of games is a great way to tackle logic problems that you rarely come across as a front-end developer.

If you would like to get the full source code in one, you can do so in my GitHub repo. If you’d rather just try out the game and debug it online, I’ve also made it available under my domain.

Did you have some fun recreating a famous game that required you to think outside the box? Let me know in the comments down below.

Playing the snake game
Playing the snake game

Better Programming

Advice for programmers.

Thanks to Zack Shapiro

Ferenc Almasi

Written by

Frontend dev with a passion for beautiful code and simple yet attractive designs. Get in touch by saying hello@allma.si or visit allma.si directly 👋

Better Programming

Advice for programmers.

More From Medium

More from Better Programming

More from Better Programming

More from Better Programming

Why Do Incompetent Managers Get Promoted?

903

More from Better Programming

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade