In this post we will be building the ever popular Tic Tac Toe game in JavaScript. It's a relatively simple implementation and the most complex portion is the calculation of a win scenario. If you are relatively new to JavaScript, then I highly recommend Web Design with HTML, CSS, JavaScript and jQuery as a good starting point.
I normally start with zero code written, and I don't normally use 3rd party libraries for these things. So there are no 3rd party libraries or frameworks to setup. All you will need is your favorite coding editor, like VS Code.
Before we get into the code, here is a running version of what we will be building.
The rules of the game are as follows.
In Tic Tac Toe, 2 players take turns adding their token (an X or a O) to a 3 x 3 (or N X N, for the more ambitious) grid until one player matches 3 (N) in a row in any direction.
Let's set up a few basic variables to keep track of the game settings.
Variable Declaration
Here is a breakdown of each of the variables.
winners - This variable will be an array containing all of the possible combinations that are considered 'winning'.
player1Selections - We will use this array to store the blocks that player1/player2 have selected.
currentPlayer - This is the index of the player currently in play, starting with 0.
points1/points2 - These variables will be used to keep track of the ongoing games player scores.
size - This is the size of the playing board measure in width * height.
Next up let us draw the tic tac toe board, which is an n x n table. In this case that n will be a 3. The CSS for the elements can be found after the post at the bottom of the page.
And the following function will be in charge of rendering the n x n grid onto the webpage.
Every major step in the game is its own function. It makes it easier to edit, as changing certain parts doesn't interfere with the rest of the game elements. It also makes it much easier to test in the debugger when you can just call a function and see the outcome of that snippet immediately.
So now we have a game board. And there's not much else to do with that really. We can add a few basic game elements, like the user scores and that will look something like this.
After a win condition is met, the winning player will get a point added to their score and the game board will reset itself.
Let's break down what happens when a user makes a selection first, however. And we also need to figure out what a winning case actually is, so let's start there.
What is a winning condition?
For an n x n tic tac toe game, a winning condition is matching n selections in a straight line either horizontal, vertical, or diagonal. We don't have to start checking for a win until any user has selected 3 or more cells however, because you obviously can't win with just 2 or less elements placed on the board.
And here's the easy part. For a 3 x 3 grid, we can see what those selections will look like the following. 1,2,3 or 4,5,6, or 7,8,9.
So we have 3 sets of cells to compare against.
Horizontal: [1, 2, 3] [4, 5, 6] [7, 8, 9]
Vertical: [1, 4, 7] [2, 5, 8] [3, 6, 9]
Diagonal: [1, 5, 9] [3, 5, 7]
Any user having any of these at any point is the winner and gets a point. We'll add another variable to the list to keep these winning selections stored.
Ideally, we would want these permutations to be calculated automatically, as they only currently apply to a 3 x 3 grid. If we wanted create a 4 x 4 grid for example, the amount of permutations would be much too high to calculate by hand.
We'll leave that as a challenge for you to take on.
So now we have a way to check if a player has won the game. But we'll need to keep track of which selections each players has. We don't want to have to go through the entire grid each time a player makes a selection to check if it's an 'X' or a 'O'. So we'll add 2 new variables to my list.
These arrays will keep track of which 'boxes' each user has selected.
Up next we will add an event handler to each cell click, alternating players after each one, until a winner is found, or until we run out of cells to click on. Here's a new updated version of the drawBoard() function from above.
The main additions to the function are the ability to store the players selections, adding the event handlers and checking for a winning condition. If a winning condition is found, the points get updated and then we reset the game variables and redraw the board as mentioned above.
This is why it's useful to break down the steps into as many functions as possible. Because drawBoard does one thing, it doesn't interfere with anything else in the game. If no win condition is found, we switch the current active player and removed the click event so that no player could click on that particular box again.
Here is the function that checks for a winning combination. It checks the players array and compares it with the list of predefined winners.
Detecting a Draw
Last on the list is detecting if we have a draw. That is, if no winning rows have been detected. And we can do that simply by checking the number of selections that the players have made. If we see that we have reached (n * n) selections, then we can assume that we have taken the board completely. We can add this check after each user plays their turn, by adding a conditional statement before control switches over to the next player.
Reset
And lastly, once the current game is over, we want to go ahead and reset the screen and its elements.
The full source code can be found down below. There's always room for improvement, and new features can always be added. If you like the code and use it somewhere online, feel free to link back to me and let me know. Not required, but it is always appreciated.
Full Source