As valuable as it is to understand the theory behind the code we write, nothing is more important than just writing code! So, as part of the blog, I am aiming to do at least one "project" every month. This will range from small, refactoring projects to bigger, more ambitious builds.

Project overview

For my first project, I decided to build a game of tic tac toe using JavaScript & jQuery. I have seen a few of these around, but most of them are two human-player games. What I wanted to build was a single player game, with the program as the opposition. This meant that the program had to be smart enough, not only to know when there was a win/lose/draw, but also to play tactically.

My solution

You can view the full code on my github repository, as well as play the game yourself. I thought I would share with you here the pseudocode to show the basic logic of the program.

The solution I came up with used classes on each of the tiles to determine when there was a win/lose/draw state. First, I created the actual playing board, which was just a bunch of <div>s.

<div class="tic-tac-toe">  
  <div id="square1" class="tile free"></div>
  <div id="square2" class="tile free"></div>
  <div id="square3" class="tile free"></div>
  <div id="square4" class="tile free"></div>
  <div id="square5" class="tile free"></div>
  <div id="square6" class="tile free"></div>
  <div id="square7" class="tile free"></div>
  <div id="square8" class="tile free"></div>
  <div id="square9" class="tile free"></div>
</div>  

Next, I mapped out what every winning state could be.

Tic Tac Toe Numbered

In total there were 8 winning states, e.g. 1-2-3 or 1-5-9. When the user clicked on a tile, it added the class 'X-play', and when the program played, it added the class 'O-play'. With this, I could write a statement like:

if ( sq1.hasClass('X-play') && sq2.hasClass('X-play') && sq3.hasClass('X-play') ) {  
    // X wins
}

This method involved a lot of hard-coding to enable the program to determine the winning states and also how to play tactically. I had 9 functions in total -

function validatePlay {  
    // check if the square attempted has already been played
    // if square is available
        // return true
    // else
        // return false
}

function clearBoard {  
    // resets the board to blank state
}

function winAlert {  
    // alerts who won the game
    // calls clearBoard
}

function checkWin {  
    // checks if any of the winning states were played by the same player
    // if true
        // call winAlert
}    

function checkDraw {  
    // checks if all the tiles were played, but there is no win
    // if true
        // alert that there has been a draw
        // call clearBoard
}

function Oplay {  
    function Oplaying {
        // call validatePlay on square passed
        // if play is valid
            // play square
        // else
            // call Orandomplay
    }

    function Orandomplay {
        // loop through numbers 1 to 9 to find a square to play
            // call validatePlay
            // if play is valid
                // play square and break loop
            // else
                // continue loop
    }

// Check for tactical play option
    // Check which squares have been played and which O should play in response
    // e.g. if square 1 and square 2 have been played by X, O should play square 3
    // If tactical option available
        // call Oplaying(tacticalsquare)
    // If no tactical option, 
        // call Orandomplay

// call checkDraw
// call checkWin
}

function Xplay {  
    // check which square was played by user
    // call validatePlay on square played
    // if play is valid
        // play square
        // call checkDraw
        // call checkWin 
        // call Oplay
}

That's the basic idea! Although this might not be the most elegant solution, it works well enough for the moment. There are still some bugs and other things that I will like to improve on in the future. One thing I would definitely like to do is to re-write the program without jQuery in order to get more comfortable writing pure JavaScript.

If you have any suggestions, please do leave a comment below.

 

Update: I rebuilt this game again, 8 months later. Read the new article.