This post was originally posted on The Algorithmic Cookbook under Tic Tac Fail: How I Tried (and Failed) to make Tik Tac Toe in an Hour
This post is also on YouTube
I’ve started the Hour Makes series in which I try to make stuff in an hour and stream it on Twitch. That’s roughly the time for a tech interview. The first thing I tried was Tic Tac Toe and it turned out to be a Tic Tac Fail. Funny enough, I thought it would be easy; at least compared to my other ideas like Pong, a Twitter Bot, Snake, Snakes and Ladders and Cornway’s Game of Life (R.I.P John).
As embarrassed as I am to not be able to make such a simple project in an hour, I learned things which will help me with future Hour Makes and my programming skills in general.
As I was brain storming this series, I googled “Tic Tac Toe” and before the first search result was… a game of Tic Tac Toe.
Talk about Google having too much power.
With the stream setup and my introduction given, I started making Tic Tac Toe by setting up the document and browser sync to sync my changes. I then added a player picker for the user to choose if they want to play as X or O (it was Y, but the game is X and Os, not X and Ys). I didn’t keep it for very long since there wasn’t any point to it. I also put a scoreboard which wasn’t necessary and should have been removed with the player picker. Not sure why I started adding these things (and others) which are more enhancements than essential, costing me a good 10 minutes.
There wouldn’t be any Tic Tac Toe without the grid, which I represented with 9 buttons in rows of 3, along with a
data-cell attribute made up of the row (a, b, c) and column (1, 2, 3).
I then had to add my script with the game logic. Having added some initial variables to define the player and CPU state, I added a
while(true) statement which hanged the browser. After blaming Browser Sync for my crappy code, I removed the
while(true) and discovered why event driven architecture is a good idea, especially in a single-threaded, event driven programming language.
Realizing my mistake, I moved onto setting up the grid which corresponds to the buttons. I then tried to add an event listener to said buttons to drive the game once a button is clicked. I initially put it on the array which obviously didn’t work and some finicking later, the event listeners were in place.
Here I also discovered that there’s
target is where the event was dispatched and
currentTarget is the element which has the event listener. Search for “event propagation” to learn more about the differences.
At this point, I was 25 minutes in and I hadn’t started making the game itself. I then started to plan the actual game logic (the only planning I’ve done so far) and decided to work on checking if the user won.
I spent 30 minutes trying to figure this out. Half of that was trying to think of a way to determine a win condition. I contemplated recursion at some point, but I didn’t explore that idea further than the function signature. I settled on trying to see if three things in a row (or column) are equal. I expected a three way equal to work, like
a === b === c, but it took far too long for me to realize that no, it won’t. That’s because of how the statement is evaluated. I’d love to write a sermon1 on operator precedence, but for simplicity’s sake, just know that the statement is being interpreted as
(a === b) === c, so it’ll always turn false since a boolean can’t equal a string2. Ok fine,
== might make that (and other things) possible, but
- I’m using
- even if I did use it, I’m certain
What a tangent. I eventually realized that I could do it like
a === b && a === c. I did that and it didn’t work. Turns out it did and much like most things in this project so far, it took me too long to realize my equality operation was fine, but the case handling
"1" wasn’t being triggered since I put
1 (as a number) instead of
"1" (as a string). Just before I figured this out, I logged “Fucking hell” which seemed apt once I realized this silly mistake.
I got to rap <!-- raw HTML omitted -->Nonstop<!-- raw HTML omitted --> by Drake and <!-- raw HTML omitted -->6 Foot 7 Foot<!-- raw HTML omitted --> by Lil Wayne while figuring this out however. By the time I had figured out my mistake, I had just over a minute left and I decided to quit and discuss what I learned from this.
My takeaways from this Hour Make experiment are:
- Plan before you code
- Debug properly
- Set up the coding environment properly
The biggest thing I learned from all this is to plan how you’ll code something. Instead of starting with the game itself, I tried to add a bunch of enhancements which should have been done after the core game. Had I outline features I wanted, along with the actual steps to make that happen, I would have had a much easier time implementing the game.
The next thing I learned is the importance of debugging properly. Sure
printf (more like just
There’s more to this I’m sure, but even my limited experience has proved to be much better than
console.log("Fucking hell!"). Of course, a debugger is just one part of debugging code—I need to develop a systematic approach for addressing bugs and fixing it. There’s supposedly a scientific method to debugging I should try out.
Finally I need a better way to set up my stream and coding environment. I’ve rarely made live-streams so I’ve never done much preparation for them, but this has shown me just how much I need to have a systematic approach to content creation, along with some good graphic design.
And that’s how my attempt to make Tic Tac Toe became a massive Tic Tac Fail. I’ve put this Tic Tac Fail online if you wanna try it for whatever reason. I’ll probably do these hour makes monthly which will hopefully do better than this. I’ll also give Tic Tac Toe another shot after a while.
I learned about this during my Programming Languages class. Did you know that Swift let’s you change the precedence of an overloaded operator? ↩︎
Thanks for reading! If you’ve enjoyed this post, you can support me by