Creating a simple Tic-Tac-Toe (or Naughts and Crosses) game in Javascript and jQuery

css html javascript jquery

In this tutorial, I will show you how to create a Tic Tac Toe game using Javascript and jQuery.

When we are complete, it will look something like the following:

 

I’ll explain how I did this, step by step, so that you can create a Tic Tac Toes game too!

If you’re time poor, and just want to skip to the facts, I got you, use the links below to skip to the relevant part for you, or read on to continue.

Lets go!

The concept, how does the game work?

The first thing to think about is the layout of the game as HTML. I’ve seen other examples on the web using a table to layout the ‘panels’ (as I called them) of the game. And while it’s a relatively straightforward way to visualise the game, its not really necessary, and its actually a problem to try and understand the games logic.

Instead, this example will use a linear sequence of “panels”, floated left within a fixed width container to simulate the appearance of a game grid. This will then enable us to conceptualise the games options in a linear way. If this doesn’t make sense right away, stick with me, it will eventually.

So, with that in mind, lets work out all the possible winning combinations.

As we can see, there are 8 possible winning combinations, pretty straightforward so far.
back to top

Create the necessary files

Now that we understand how the game works, lets create all the files we will need for our game.

File name Description
game.htm The HMTL file that contains most of the content of the game.
css/game.css All css styles are contained within this file.
js/jquery.js The javascript library that game.js refers to.
js/game.js The main javascript file, contains most of the code for the functionality of the game.

Lets break down what these files actually do.
back to top

Creating the HTML elements of the game (game.htm)

The first thing we want to do, us to create our standard HTML markup, linking in our jQuery library, our game.js Javascript file and our game.css stylesheet file. We also need to create a container to store all the required elements of our game (we will call this our “game-container“):

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>TIC TAC TOE - Adam Lemmo</title>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/game.js"></script>
<link href="css/game.css" rel="stylesheet"/>
</head>
<body>
	<div id="game-container">
	</div>
</body>
</html>

Within the “game-container“, we will create an introduction message, that will also contain our character selections, like this:

<div id="game-container">
  <div id="introduction">
    <h1>TIC TAC TOE</h1>
    <p>Try to beat the computer!</p>
    <p>Select your character:</p>
    <form id="character-selections">
      <input type="radio" id="X" name="selections" value="X" checked="yes"/>
      <label for="X">X</label>
      <input type="radio" id="O" name="selections" value="O"/>
      <label for="O">O</label>
    </form>
    <a href="#" id="startBtn">Start game</a>
  </div>
</div>	

Next, we will add our game panels (the actual Tic Tac Toe board), and a “Feedback” screen (to display Game Over man!) and finally, a score element, to track the players score:

<div id="game-container">
  <div id="introduction">
    <h1>TIC TAC TOE</h1>
    <p>Try to beat the computer!</p>
    <p>Select your character:</p>
    <form id="character-selections">
      <input type="radio" id="X" name="selections" value="X" checked="yes"/>
      <label for="X">X</label>
      <input type="radio" id="O" name="selections" value="O"/>
      <label for="O">O</label>
    </form>
    <a href="#" id="startBtn">Start game</a> </div>
	<div id="game-area">
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
	</div>
  <div id="feedback">
    <h1>GAME OVER</h1>
    <p></p>
    <a href="#" id="startAgainBtn">Start again</a> </div>
</div>
</div>
<div class="container">
  <div id="score">
    <p>Score: 0</p>
  </div>
</div>

As you can see here, we have also created the player selections (X or O) and the startBtn button, which will as it suggests, start our game!

If you have followed this far, the complete HTML file should look as follows:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>TIC TAC TOE - Adam Lemmo</title>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/game.js"></script>
<link href="css/game.css" rel="stylesheet"/>
</head>

<body>
<div id="game-container">
  <div id="introduction">
    <h1>TIC TAC TOE</h1>
    <p>Try to beat the computer!</p>
    <p>Select your character:</p>
    <form id="character-selections">
      <input type="radio" id="X" name="selections" value="X" checked="yes"/>
      <label for="X">X</label>
      <input type="radio" id="O" name="selections" value="O"/>
      <label for="O">O</label>
    </form>
    <a href="#" id="startBtn">Start game</a> </div>
	<div id="game-area">
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
		<a href="#" class="panel"></a>
	</div>
  <div id="feedback">
    <h1>GAME OVER</h1>
    <p></p>
    <a href="#" id="startAgainBtn">Start again</a> </div>
</div>
</div>
<div class="container">
  <div id="score">
    <p>Score: 0</p>
  </div>
</div>
</body>
</html>

Now that we have our HTML sorted, lets get stuck into writing the Javascript code of our game.
back to top

The Javascript functions of the game (game.js)

The Javascript of the game has four custom functions:

Function Description
startGame() This function as it states, starts the game, it is triggered from the startBtn link.
selectPanel() This function is triggered from the panels in the layout of the game, it is a central function to the game, and represents the users actions in the game.
computerMove() This function represents the actions of the computer, and it follows the order of the aiOrder[] array.
checkCombination() This function is the most generic function in the code, but also the most complex, it checks the users and computers progress in the game, and compares it to the list of valid combinations in the game rules. This function also determines the completion of the game, whether it’s the user or the computer that wins, or if a draw, or ‘tie’ is encountered.

back to top

Initialising the game

The first thing we do, is to initialise some variables that will be used in our game:

//player characters, can be changed if needed...
var userChar = "X";
var computerChar = "O";
var gameOver = false;//gets set to the true when the game is over.
var scoreCount = 0;//set to zero initially, increments by 1 for every winning game.

And now we want to create and store the winning combinations of the game.

Rererring to our earlier breakdown of the winning combinations, we can represent as a linear sequence, in the following way:

We can then use this representation of the winning combinations as a series of arrays:

//all the possible ways to win/winning combinations...
var row1 = [1, 2, 3];
var row2 = [4, 5, 6];
var row3 = [7, 8, 9];
var col1 = [1, 4, 7];
var col2 = [2, 5, 8];
var col3 = [3, 6, 9];
var diag1 = [1, 5, 9];
var diag2 = [3, 5, 7];
//collect all winning combinations...
var rules = [row1, row2, row3, col1, col2, col3, diag1, diag2];
//
var aiOrder = [4, 0, 8, 5, 1, 7, 2, 6, 3];//an array to store the order of the computers turns...

Now that we have all of our variables initialised, we can now focus on initialising the screen.

Because we are using jQuery, we will use the $(document).ready() function:

$(document).ready(function() {//when the document is ready/loaded...	
	$("#game-area").hide();
	$("#score p").hide();
        $("#feedback").hide();
        //
	$("#introduction #startBtn").bind("click", startGame);
	$("#game-area .panel").each(function(i){//apply an id to all the panels...
		$(this).addClass("enabled").attr("id", "panel"+i);
	});
	$("#game-area .panel.enabled").bind("click", selectPanel);//apply a click event to all the panels...
	//
	//the click event for the start again button within the feedback div.
	$("#feedback #startAgainBtn").click(function(){
		$(this).parent().fadeOut();//hide thefeedback div once selected..
		$("#game-area .panel").empty().bind("click", selectPanel).css({"cursor":"pointer"}).removeClass("winner").addClass("enabled");//reset the games state to start again...
		gameOver = false;
	});
});

As you can see, this will hide the game area, the score, and the feedback.

It also binds the startGame function to the #startBtn button, loops over all the panels, and gives them an id, and assigns a click event to the #startAgainBtn button, for when the game is complete.
back to top

The startGame() function

This function is executed when the player selects the #startBtn button in the #introduction screen.

The startGame() function checks which character the player selected, fades the introduction screen out, and shows the score.

function startGame(){	
	$(this).parent().fadeOut();//hide thefeedback div once selected..	
	$("#game-area").fadeIn();
	if($('input[name=selections]:checked', '#character-selections').val() === "X"){
		userChar = "X";
		computerChar = "O";
	} else {
		userChar = "O";
		computerChar = "X";
	}
	$("#score p").show();		
}

back to top

The selectPanel() function

This function is executed when the player selects one of the panels.

Once this is done, the panel is disabled (using the jQuery unbind method to remove the click event).

It also loops over the rules (a collection of the winning combination arrays) and runs the checkCombination() function, passing in the rules iterator to check all combinations.

function selectPanel(e){//invoked when the panel is selected, in this case, from a click event...	
	//this panel has it's click event removed, it's cursor set to default and it's no longer enabled, so this class is removed...
	$(this).text(userChar).unbind("click").css({"cursor":"default"}).removeClass("enabled");
	//loop over all of our rules...
	for (var i = 0;i<rules.length;i++){
		checkCombination(rules[i], userChar);//and execute our function to check all the combinations...
	}
	if(!gameOver){//if it isnt game over, then let the computer have a turn.
		computerMove();//the computers turn is executed with this function.
	}
	//
	e.preventDefault();//prevent the default behaviour of the a tag selected.
}

The last thing this function does, is to check if the game isn’t over, by checking the gameOver variable. The gameOver variable is set by the previously mentioned checkCombination() function.

if the game isn’t over  (gameOver is false), then the computerMove() function is executed.
back to top

The computerMove() function

This function executes when the game isn’t over. It loops over the aiOrder array, checks to see if the panel referred to in the loop is empty (“”) and if so, it applies the computer character to the panel.

function computerMove() {	
	for (var i = 0;i<aiOrder.length;i++){//loop over the order array...
		if($("#game-area #panel"+aiOrder[i]).text()=== ""){//if the panel selected in this loop is empty...
			//...then apply the computers character to the panel, take away its click event, set the cursor to default, and remove the enabled class...
			$("#game-area #panel"+aiOrder[i]).text(computerChar).unbind("click").css({"cursor":"default"}).removeClass("enabled");
			break;//stop further execution of the outer loop.
		}
	}
	for (var j = 0;j<rules.length;j++){
		checkCombination(rules[j], computerChar);//check the combinations of the computer player...
	}
}

The function then loops over the rules array, and executes the checkCombination() function.
back to top

The checkCombination() function

This function checks all of the panels to see if there are any winning combinations, updates the score and checks if the game is a tie game.

Check the comments in the following code, for a step by step breakdown of this function:

//generic function to check either players progress in the game...
function checkCombination(arr, playerChar){	
	var correctNum = 0;//stores the correct number selected by the player.
	var panelCount = 0;//stores the panel count selected.
	var thisNum;//refers to the current number selected
	$("#game-area .panel").each(function(i){//iterate over the panels...
		thisNum = (i+1);//increment our thisNum var, it's 0 based.
		if($("#game-area .panel").eq(i).text() === playerChar){//check if the current panel has the players char in it.
			for (var j = 0;j<arr.length;j++){//loop over the length of the array passed into this function...
				if(thisNum === arr[j]){//check this num against the passed in array...
					correctNum += 1;//test is true, we are correct, increment our correctnum var.
				}
			}
		}
	});
	if(correctNum === arr.length){//if correct num is equal to the arrays length, we are all correct	!		
		$("#feedback").fadeIn().children("p").text('"'+playerChar+'"'+' has won!');//show the feedback message, indicating which player has won!
		$("#game-area .panel.enabled").unbind("click").css({"cursor":"default"}).removeClass("enabled");//disable all the panels, game is over!
		for (var k = 0;k<arr.length;k++){//loop over the winning array found...
			$("#game-area #panel"+(arr[k]-1)).addClass("winner");//add a class to the winning panels! 
		}
		scoreCount +=1;
		$("#score p").text("Score: "+scoreCount);
		gameOver = true;		
	}	
	//determine if game is a tie...
	$("#game-area .panel").each(function(){//loop over all the panels...
		if($(this).text()!==""){//check if the current iterator of the loop is not an empty string...
			panelCount+= 1;//add to our panel count.
		}		
	});//show the feedback indicating game is a tie...
	if(panelCount === $("#game-area .panel").length){//if panel count indicates that all panels are filled, then...
		$("#feedback").fadeIn().children("p").text("Game is a tie!");//show the message that the game is a tie!
	}
}

back to top

The CSS of the game (game.css)

Most of the games CSS is contained within a single rule called #game-container. With the exception of the score, which is separate to the major elements of the game.

If you were to include this on your own page, you would need to wrap it all in another container, and because a combination of relative and absolute positioning is used, it should work reasonably well within another context.

Feel free to modify this to your own designs!

Conclusion

All going well, you should have a complete Tic Tac Toe game written in Javscript/jQuery!

References

The following sites were used as references and inspiration for this game.

File name Description
Javascript Kit – Tic Tac Toe credit: Cory Fogliani  This page gave me insight into the rules of the computer player/AI, I was a bit disappointed with the repetitious code however, so I made my logic loop through the rules instead.
Compare array in Javascript on Stackoverflow  Compare array in javascript
How to know if two arrays have the same-values on Stackoverflow  How to know if two arrays have the same values
Javascript array comparison by vikasrao  JavaScript – Common Array operations

I hope you enjoyed this tutorial, please let me know in the comments if you have any observations on this post!

You can download a complete .zip file of the game here lemmoscripts-tic-tac-toe.
back to top