Free Code Camp is a demanding and time-consuming development course that aims to teach JavaScript code. To gain my Front-End Certification I have to complete two last projects. One of which is JavaScript game of Tic Tac Toe.

Tic Tac Toe – Basics

The game itself is quite simple. But the concept of programming it is not. The computer must recognize the moves of the player and act accordingly to player’s strategy using a MiniMax algorithm. This is quite complicated and actually not needed to finish this assignment.

All I have to create is a simple game that will allow my users to check the which figure they want to be playing, and play the game against the computer.

First steps

Naturally the first thing to do is create a simple html markup for the website (in this challenge I’m using Bootstrap and Font-Awesome).

The starting point look like that:

<div class="container">

  <div class="modal fade" id="myModal" tabindex="-1" role="dialog">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
          <h4 class="modal-title text-center">Tic Tac Toe Game</h4>
        </div>
        <div class="modal-body">
          <h3>Welcome to the Tic Tac Toe Game!</h3>
          <p>It’s time to choose your figure.</p>
          <p id="test"></p>
        </div>
        <div class="modal-footer">
          <button type="button" id="x" class="btn" data-dismiss="modal" onClick="setFig(this.id)"><span class="fa fa-times"><span></button>
          <button type="button" id="o" class="btn" data-dismiss="modal" onClick="setFig(this.id)"><span class="fa fa-circle-o"><span></button>
        </div>
      </div>
    </div>
  </div>

  <div class="game">
    <div id="first" onClick="icon(this.id)" class="game-field"></div>
    <div id="second" onClick="icon(this.id)" class="game-field"></div>
    <div id="third" onClick="icon(this.id)" class="game-field"></div>
    <div id="fourth" onClick="icon(this.id)" class="game-field"></div>
    <div id="fifth" onClick="icon(this.id)" class="game-field"></div>
    <div id="sixth" onClick="icon(this.id)" class="game-field"></div>
    <div id="seventh" onClick="icon(this.id)" class="game-field"></div>
    <div id="eight" onClick="icon(this.id)" class="game-field"></div>
    <div id="nineth" onClick="icon(this.id)" class="game-field"></div>
  </div>
  
  </div>
</div>

The modal element on top of the page is responsible for displaying a box to user at the beginning of each game. This way we enable user to choose which figure he or she wants to play.

Next element is .game div. It wraps all of .game-field elements, that takes part in tic tac toe game.

After creating basic HTML code it’s time to add styles.

@import url(https://fonts.googleapis.com/css?family=Source Sans Pro:400,600);
body {
  font-family: 'Source Sans Pro';
  background: #29335C;
  background-size: cover;
}

.game {
  background-color: transparent;
  width: 402px;
  height: 402px;
  margin: 50px auto;
}

.game-field {
  width: 134px;
  height: 134px;
  display: block;
  float: left;
  color: #EAEAEA;
  font-size: 6.3em;
  padding: 1px 27px;
}

.win {
  color: #E4572E;
  transition: 200ms;
}

#first, #second, #third {
  border-bottom: 3px solid #525B76;
}

#second {
  border-left: 3px solid #525B76;
  border-right: 3px solid #525B76;
}

#fourth, #fifth, #sixth {
  border-bottom: 3px solid #525B76;
}

#fifth {
  border-left: 3px solid #525B76;
  border-right: 3px solid #525B76;
}

#eight {
  border-left: 3px solid #525B76;
  border-right: 3px solid #525B76;
}

.modal-content {
  background-color: #EAEAEA;
}

.modal-header {
  background-color: #29335C;
  width: 100%;
  height: 100%;
  color: #EAEAEA;
}
.modal-header button {
  color: #EAEAEA;
}
.modal-header button:hover {
  color: #EAEAEA;
}
.modal-header h4 {
  font-size: 2.3em;
}

.modal-body {
  padding: 30px;
  margin: 10px 0;
  text-align: center;
}

.modal-footer {
  padding: 10px 80px 10px 0px;
}
.modal-footer button {
  background-color: white;
  color: black;
  width: 40%;
  font-size: 2em;
  transition: 500ms;
}
.modal-footer button:hover {
  background-color: #E4572E;
  color: white;
}

.signature {
  padding-top: 10px;
}

Now we have a perfect ground to start building the logic behind this game. Now let’s take a look at the JavaScript code.

JavaScript behind Tic Tac Toe

The first step to build a working Tic Tac Toe game is to create a game object to store all information needed.

var game = {
  user: '',
  computer: '',
  currentPlayer: '',
  moves: 1,
};

As you can see object stores 4 basic properties – user, computer, currentPlayer and moves. All of those properties are needed for the game to work properly, although you could also use variables to achieve the same result.

The most basic function within the code is a start() function that is responsible for showing the modal to the user. Within start function there’s a single line of code – $('#myModal').modal('show');.

After creating object and showing our modal to the user it’s time to set user’s figure. This task is completed by setFig function.

function setFig(id) {
  if (id === 'x') {
    game.user = '<span class="fa fa-times"></span>';
    game.computer = '<span class="fa fa-circle-o"></span>';
  } else if (id === 'o') {
    game.user = '<span class="fa fa-circle-o"></span>';
    game.computer = '<span class="fa fa-times"></span>';
  }
  firstMove();
  setCurrPl('user');
}

This function takes 1 argument – which is the id of the clicked button. Then it sets the figures to user and computer players by passing to those properties the correct Font-awesome icon (X or O). Then it calls 2 functions – firstMove and setCurrPl.

The firstMove function is responsible for making a first move in game for the computer.

function firstMove() {
  $('#fifth').html(game.computer);
  $('#fifth').removeAttr('onClick');
}

It adds the icon to the center .game-field div and deletes attribute onClick to lock this position.

setCurrPl function on the other hand is responsible for setting the current player.

function setCurrPl(curr) {
  game.currentPlayer = curr;
}

Function takes one argument which is the name of the current player that in this case is ‚user’ or ‚computer’ string.

I clicked – what now?

After the first move has been made it’s the user’s turn to make a move. To handle that interaction each time user will click .game-field element it’s id will be send to icon function.

function icon(id) {
  if (game.currentPlayer == 'user') {
    $('#'   id).html(game.user);
    $('#'   id).removeAttr('onClick');
    gameStatus();
    setCurrPl('computer');
  } else if (game.currentPlayer == 'computer') {
    $('#'   id).html(game.computer);
    $('#'   id).removeAttr('onClick');
    gameStatus();
    setCurrPl('user');
  }
  game.moves  ;
  draw();

  if (game.currentPlayer == 'computer') {
    comp();
  }
}

This function takes only one argument – the id of an element. Then it uses this id to find the right .game-field div and place the icon of current player on that field.

It does so by checking which of the players has made a move, then it adds this player icon to the field and removes attribute onClick to prevent changing the field once more.

After that the function checks the status of the game to check whether the game should end or continue, and changes the current player to contrasting value. When the loop is finished we need to increment the value of game.moves property and check if the game ended in a draw (all of 9 moves were executed). The last task to execute is starting a function that makes a move for the computer. With if statement it checks if the current player is a computer, when it is the comp function is being called.

Hard part – make computer „think”

The comp function was one of the most difficult to make. The problem is making a computer decide what kind of move to make. I simplified it a little bit. Now the function checks every field possible from 1–9 and makes a move to in first available field. This makes it very easy to beat but it does the job quite well.

function comp() {
  switch (true) {
    case $('#first').html() != game.user && $('#first').html() != game.computer:
      icon('first');
      break;
    case $('#second').html() !== game.user && $('#second').html() !== game.computer:
      icon('second');
      break;
    case $('#third').html() !== game.user && $('#third').html() !== game.computer:
      icon('third');
      break;
    case $('#fourth').html() !== game.user && $('#fourth').html() !== game.computer:
      icon('fourth');
      break;
    case $('#fifth').html() !== game.user && $('#fifth').html() !== game.computer:
      icon('fifth');
      break;
    case $('#sixth').html() !== game.user && $('#sixth').html() !== game.computer:
      icon('sixth');
      break;
    case $('#seventh').html() !== game.user && $('#seventh').html() !== game.computer:
      icon('seventh');
      break;
    case $('#eight').html() !== game.user && $('#eight').html() !== game.computer:
      icon('eight');
      break;
    case $('nineth').html() !== game.user && $('#nineth').html() !== game.computer:
      icon('nineth');
      break;
  }
};

The function uses switch statement to check all of available spaces one by one and place the icon in the first available space.

Check the result

The before-mentioned gameStatus function is responsible for checking if the game has a winner. This function checks all possible result of Tic Tac Toe game and then changes the color of winning icons.

function gameStatus() {
  var curPlayer;

  if (game.currentPlayer == 'user') {
    curPlayer = game.user;
  } else if (game.currentPlayer == 'computer') {
    curPlayer = game.computer;
  }

  switch (true) {
    case $('#first').html() === curPlayer && $('#second').html() === curPlayer &&
    $('#third').html() === curPlayer:
      show('#first', '#second', '#third');
      break;
    case $('#fourth').html() === curPlayer && $('#fifth').html() === curPlayer &&
    $('#sixth').html() === curPlayer:
      show('#fourth', '#fifth', '#sixth');
      break;
    case $('#seventh').html() === curPlayer && $('#eight').html() === curPlayer &&
    $('#nineth').html() === curPlayer:
      show('#seventh', '#eight', '#nineth');
      break;
    case $('#first').html() === curPlayer && $('#fourth').html() === curPlayer &&
    $('#seventh').html() === curPlayer:
      show('#first', '#fourth', '#seventh');
      break;
    case $('#second').html() === curPlayer && $('#fifth').html() === curPlayer &&
    $('#eight').html() === curPlayer:
      show('#second', '#fifth', '#eight');
      break;
    case $('#third').html() === curPlayer && $('#sixth').html() === curPlayer &&
    $('#nineth').html() === curPlayer:
      show('#third', '#sixth', '#nineth');
      break;
    case $('#first').html() === curPlayer && $('#fifth').html() === curPlayer &&
    $('#nineth').html() === curPlayer:
      show('#first', '#fifth', '#nineth');
      break;
    case $('#third').html() === curPlayer && $('#fifth').html() === curPlayer &&
    $('#seventh').html() === curPlayer:
      show('#third', '#fifth', '#seventh');
      break;
    default:
      draw();
  }
};

Color of the winning icons is changed by show function. It takes 3 arguments – 3 id’s of winning elements and adds a .win class to them.

function show(x, y, z) {
  var x = $(x),
    y = $(y),
    z = $(z);
  x.addClass('win');
  y.addClass('win');
  z.addClass('win');
  lockAll();
  setTimeout(reset, 1500);
}

Resetting the game

The last function reverts everything back to the beginning except changing the figures of players.

function reset() {
  $('.game-field').html('');
  game.moves = 1;
  $('.game-field').attr('onClick', 'icon(this.id)');
  $('.win').removeClass('win');
  setTimeout(firstMove, 200);
}

Conclusion

The tic tac toe was fairly complicated little project. It could be much more difficult if the task was to create the unbeatable version of the game – check this one.

If you’d like to test out my version go ahead.

See the Pen Tic Tac Toe Game by @mrkaluzny (@mrkaluzny) on CodePen.

Or check the source code on GitHub. As always if you have any questions/comments – tweet @mrkaluzny or leave a comment below.