Home · Comment | 12/02 '17 · Tic Tac Toe

So You know about HTML, CSS and JavaScript? Want to build something with them? Those three web technologies can be used to create a web page. Have You done that? Want something more? How about creating a simple Tic Tac Toe game? This post explains how I build Tic Tac Toe Game In 3 simple steps




Code         Game


#1 The Board

The Board

Start with creating the board. In this case the game needs a board that has 3x3 grid, see The Board figure. Now, what can I do in order to get that look? I guess there are several ways to do that, it can be done using nested div, css, or javascript. But this time I will go with native HTML element. I decide to use HTML element to create base canvas for the game. The element I use is table along with its components tr and td. The reason I use table element is because the structure that match for this kind of situation.

<table>
3 times this block to create 3 rows
<tr>
    <td></td>
    <td></td>
    <td></td>
</tr>
...
</table>

I See Nothing

After writing that code, I open it in a browser. But there is something wrong, I don't see anything in the browser. I debug the problem and found some...

  1. No Content

    Insert some text inside td

  2. No Border

    Add border attribute with value 1 to the table tag, I drop the content from td because I can already see something

<table border="1">

reload, and...

what is that? I zoom in 500%...



#2 Prettify The Table

Now, I'm going to change the table styles, to be exactly like The Board figure. first thing to do is make the table data bigger, so I don't have to zoom. Let say I give 64px width and height using css and it is relative to a class given to the table.

<style>
table td {
    width: 64px;
    height: 64px;
}
</style>

<table border="1">

I notice something that the td element maybe not computed with width and height of 64px. This may cause issue that the block will not be square. To make life easier, lets give it CSS3 property box-sizing with value border-box to make life easier. This gives me easier calculation, the padding and border will be included in the width and height, so I will not worry about thinking of how I set width to 64px and get 74px.

* {
    box-sizing: border-box;
}

The next thing is border. I need to do some changes to the border because I don't really understand how the default border table work. So, to change the border I first add border to the td selector and remove default table border. I give it some width to get bigger look ~ border: 8px solid black;

OK. Now, the problem for me is there is gap between blocks. After debug, I find that there are property called border-spacing in the table style and it has 2px default value. So, I override the value with 0.

But now another problem appear, the border between tds not the same. The logic is because joining border between tds in the middle. How do I solve this? With another border for the table.

table, table td {
  border: 8px solid black;
}
table {
  border-spacing: 0;
}
table td{
  width: 64px;
  height: 64px;
}


#3 The Action

The Board is ready, now is the time for some actions. This is the time when JavaScript enter. What kind of action I am going to handle? onclick? Yes, exactly! Where do I need to put the onclick action? It can be in the html, body, td (the blocks). The most logical answer is in the td because that is where I need to click, but the problem is I need to give each td onclick code and that is not very effective. The solution for this is I put the onclick in the table element.

<table id="board">
<script>
  console.log(board);
  board.onclick = function(e) {
    console.log(e);
  };
</script>

board variable automatically generated for the page script. I can use it and it points to the table element. Now, how I detect the td elements being clicked? See the variable called e from the function onclick. The e variable has bunch of properties, one of them I can verify which td is clicked . The problem is every browser has different value and ways to access it. Below is the code to handle for some browsers.

function getClickedElement(e) {
    if (e.path) { // chrome
        return e.path[0];
    }
    if (e.explicitOriginalTarget) { // firefox
        return e.explicitOriginalTarget;
    }
    if (e.target) { // edge, internet explorer
        return e.target;
    }
    console.error("can't find element!");
}

Next, I need to assign something to the clicked element. I simply put an "X" or "O" inside the td element to mark the moves. Once block clicked, it can't be clicked again, so I add a property to the element so it knows not to make another action. Another thing is it will take turns between X and O, to handle this I create a variable called current it will change between X and O every successful new click.

var x = "X", o = "O";
var current = x;
board.onclick = function(e) {
    var td = getClickedElement(e);
    if (td && !td.clicked) {
        td.clicked = true;
        td.innerText = current;
        current = current==x?o:x;
    }
};

Alright, the game is ready! Although there are more improvements can be added but right now I can play the game. Refresh the page to get initial state, and for the win, you can see for yourself, haha!