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
#1 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>
<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...
-
No Content
Insert some text inside
td
-
No Border
Add
border
attribute with value1
to thetable
tag, I drop the content fromtd
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 td
s not the same.
The logic is because joining border between td
s 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!