In this post we'll 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.

I normally start with zero code written, and I don't normally use 3rd party libraries for these things. So feel free to follow along with this tutorial. All you will need is your hands and a notepad file.

Coding Tic Tac Toe In JavaScript
Name: Tic Tac Toe
Language: JavaScript
Estimated Completion Time: 1 hour

Sounds simple enough. But everything always does.

We all know what Tic Tac Toe is. 2 players take turns adding their token to a 3 x 3 (or N X N for the more ambitious) grid until one matches 3 (N) in a row in any direction. So let's set up a few basic variables to keep track of the game settings.


var numberOfPlayers = 2;
var currentPlayer = 0;
var move = 0;
var points1 = 0;    // player 1 points
var points2 = 0;    // player 2 points
var size = 3;

These are pretty self-explanatory. And by setting the size variable, I'll be able to either add more players to the game, or to make it a larger playing field. The move variable will simply keep track of the current iteration that we are in.

Next up I'll need to draw the tic tac toe board, which is an n x n table. In our case that n will be a 3. So something like the following should do the trick.


// HTML
<div id="game"></div>


// JavaScript
function drawBoard()
{
    var parent = document.getElementById("game");
    var counter = 1;

    for (var i = 0; i < 3; i++)
    {
        var row = document.createElement("tr");

        for(var x = 0; x < size; x++)
        {
            var col = document.createElement("td");
            col.innerHTML = counter;

            row.appendChild(col);
        }
        parent.appendChild(row);
    }
}

I make every step into its own function. It makes it easier to edit, and it 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 I have a board. And there's not much else to do with that really. I'll add a few basic game elements, like the scores to the page, and that will look something like this.


Player 1
0
1 2 3
4 5 6
7 8 9
Player 2
0

Something like this will do. After a win condition is met, the winning player will get a point added to their score and the game board will reset itself. Sounds simple enough.

I'll need to break down what happens when a user makes a selection first however. And I also need to figure out what a winning case is.

What is a winning condition

For an n x n tic tac toe game a win is matching n selections in a straight line either horizontal, vertical, or diagonal. I don't have to start checking for a win until a 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. I can see what those selections will look like. 1,2,3 or 4,5,6, or 7,8,9 are 3 examples.

So I 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. Easy enough. I'll add another variable to my list to keep these selections stored.


var winners = new Array();

function loadAnswers()
{
    winners.push([1, 2, 3]);
    winners.push([4, 5, 6]);
    winners.push([7, 8, 9]);
    winners.push([1, 4, 7]);
    winners.push([2, 5, 8]);
    winners.push([3, 6, 9]);
    winners.push([1, 5, 9]);
    winners.push([3, 5, 7]);
}

Ideally, I would want these permutations to be calculated automatically, as they only currently apply to a 3x3 grid.

that's a challenge for you

So now I have a way to check if a player has won the game. But I'll need to keep track of which selections each players has. I don't want to have to go through the entire grid each time a player picks something to check if it's an 'X' or a 'O'. So I'll add 2 new variables to my list.


var player1Selections = new Array();
var player2Selections = new Array();

These arrays will just keep track of which 'boxes' each user 'owns' as it were.

We're almost there. Up next I'll add an event handler to each cell click, alternating players after each one, until a winner is found and then resetting the game variables. Here's a new updated version of the drawBoard() function from above. I'll highlight the new parts.


function drawBoard() {
    var Parent = document.getElementById("game");
    var counter = 1;
    
    while (Parent.hasChildNodes()) {
        Parent.removeChild(Parent.firstChild);
    }

    for (s = 0; s < 3; s++) {
        var row = document.createElement("tr");
        
        for (r = 0; r < 3; r++) {
            var col = document.createElement("td");
            col.id = counter;
            col.innerHTML = counter;

var handler = function(e) { if (currentPlayer == 0) { this.innerHTML = "X"; player1Selections.push(parseInt(this.id)); player1Selections.sort(function(a, b) { return a - b }); } else { this.innerHTML = "O"; player2Selections.push(parseInt(this.id)); player2Selections.sort(function(a, b) { return a - b }); } move++; var isWin = checkWinner(); if (isWin) { if(currentPlayer == 0) points1++; else points2++; document.getElementById("player1").innerHTML = points1; document.getElementById("player2").innerHTML = points2; reset(); drawBoard(); } else { if (currentPlayer == 0) currentPlayer = 1; else currentPlayer = 0; this.removeEventListener('click', arguments.callee); } }; col.addEventListener('click', handler);
row.appendChild(col); counter++; } Parent.appendChild(row); } loadAnswers(); }

I added the players selection to the their array variable and then checked for a winning condition. If a winning condition is found, I updated the points and reset the game variables and redrew the board.

This is why it's useful to break down the steps into as many functions as possible. Because drawBoard just does one thing, it doesn't interfere with anything else in the game. If no win condition is found, I switched the current active player and removed the click event so that no player could click on it again. Here is the function that checks for a winning combination. It just checks the players array, with the list of predefined winners. When both having matching arrays, we have a win!


function checkWinner() {
    // check if current player has a winning hand
    // only stsrt checking when player x has size number of selections
    var win = false;
    var playerSelections = new Array();

    if (currentPlayer == 0)
        playerSelections = player1Selections;
    else
	playerSelections = player2Selections;
    
    if (playerSelections.length >= size) {
        // check if any 'winners' are also in your selections
        
        for (i = 0; i < winners.length; i++) {
            var sets = winners[i];  // winning hand
            var setFound = true;
            
            for (r = 0; r < sets.length; r++) {
                // check if number is in current players hand
                // if not, break, not winner
                var found = false;
                
                // players hand
                for (s = 0; s < playerSelections.length; s++) {
                    if (sets[r] == playerSelections[s]) {
                        found = true;
                        break;
                    }
                }

                // value not found in players hand
                // not a valid set, move on
                if (found == false) {
                    setFound = false;
                    break;
                }
            }

            if (setFound == true) {
                win = true;
                break;
            }
        }
    }

    return win;
} 

It looks complex, but it's literally just comparing values one at a time and when any one doesn't match, returning false or returning true otherwise.

Detecting a Draw

Last on the list is detecting if we have a draw. And we can do that simply enough by comparing the number of moves that have taken place with the total number of options on the board. We can add this check after each user plays their turn, by adding a conditional statement before control switches to the next player.


if (isWin)
{
      if(currentPlayer == 0)
          points1++;
      else
          points2++;

      document.getElementById("player1").innerHTML = points1;
      document.getElementById("player2").innerHTML = points2;

      reset();
      drawBoard();
 }

else if (player2Selections.length + player1Selections.length == 9)
 {
     reset();
     drawBoard();
}

But there it is. Tic Tac Toe in all of its majesty. Here's the final playable version for your testing pleasure.


Player 1
0
Player 2
0

That was actually a fun quick project. Here is the full source for your tinkering. There's always room for improvement, and new features can be added. If you like the code and use, feel free to link back to me. That's always appreciated.

See the Pen WpzrKK by Walter G (@ThatSoftwareDude) on CodePen.

click to view source

Comments

Robert
"Hey, thanks for your tutorial. Could you please explain how can I remove the numbers from the table? Appreciate that."
You are very welcome! And absolutely. In the drawBoard() function, simply remove the following line:

col.innerHTML = counter;

And that should do it!
9/29/2017
kehlyn
"thanks for the code "
You are very much welcome!
9/27/2017
kehlyn
"can you make a code to show if the game has ended in a draw "
Absolutely can :) The post has been updated and the sample code too!
9/27/2017
keitumetse
"how do i run these codes,do i link them to an html file or what im confused"
If you copy and paste the full source into an html file, it will run. However, I will add this code to CodePen and include it on this post. Thanks for your comment!
9/7/2017