Creating Tic-tac-toe in JavaScript (and why I enjoyed it)

Tic-tac-toe is one of the simplest games around, yet it can be tricky to win. The concept of Tic-tac-toe is super simple: you have a 3×3 grid, and each player takes turns writing their respective symbol, either an X or O, in a square. The first person to get three Xs or Os in a row, be it horizontally, vertically, or diagonally, wins. Even a three-year old can play Tic-tac-toe. I remember as a small child on long road trips I played Tic-tac-toe. However, this almost ridiculously simple game has some interesting hidden logic. In order to be good at Tic-tac-toe, you have to analyze the entire board every time it is your turn, calculating the best possible move for you to win but also trying to predict your opponent’s next move and try to block it, and if all else fails make the game end in a tie. This logic can be rather complicated at times, despite the tiny playing field and few move combinations. Even though I am very a very analytical and technical thinker, I somehow loose to rioforce nearly every time we play Tic-tac-toe. It is both amusing and confusing, to be honest. ๐Ÿ˜›

On 9 September, I posted the following tweet.

Shortly thereafter, I started working on faithfully recreating Tic-tac-toe in JavaScript, the only real requirement being I was not permitted to use jQuery. After taking a cue from the Tic-tac-toe game that started this whole project, I started pounding out the code. By the next Monday before JavaScript class was over, I had a fully working Tic-tac-toe game completely written in JavaScript with a localStorage powered scoreboard. Through this quick project and the first game I have ever written, I learned some things I might not have learned otherwise.

  • I had to think how the brain plays the game rather than how I play the game.

    Playing Tic-tac-toe is super simple; I explained the whole thing in two sentences in the introduction. Playing Tic-tac-toe as our brain plays it and putting that logic into code down is a completely different experience. Our brains handle all of the necessary logic “behind the scenes”. In programming, you have to create that logic processing, which is in a way almost like recreating the brain. You do not think twice if there are three Xs or Os in a row, as you can clearly see that by looking at the board. A computer knows none of this already, you have to teach it. Checking if there were three items in a row was one of if not the hardest part about this project. What about stalemates or an incomplete game? Does the computer know the conditions for declaring a game ended in a tie automatically? Does the computer know a letter cannot be changed once it is written? These are valid questions we do not consider when playing, as the brain figures them and only provides the answer. Thus the real challenge behind developing Tic-tac-toe was thinking how to be the game; how to handle all the minute details and rules we would otherwise not bother considering, as our brain does it “subconsciously”.

  • I had to think it “all the way” though. Do not get me wrong, programming requires constant through thinking to complete something completely from start to finish. However, when we get accustomed to using libraries that legitimately make programming easier but do not go back and do the same things the “old-fashioned way” at times, we risk forgetting what is really going one behind the scenes. Some may say this was a crazy limitation and even crazier I am saying such, but not using jQuery for this helped me think through things with a different perspective. Instead of simply using $("td").on("click", makeMove); to make all buttons clickable and $(this).off("click"); to remove that handler or possibly even $("td").one("click", makeMove);, I had to employ more traditional techniques such as addEventListener and removeEventListener to accomplish the same thing (although I did use tad more modern selectors such as document.querySelector).

    Not using jQuery also made me think more architecturally. In the Tic-tac-toe game that started this project, the author used the :contains() selector to check the rows, columns, and diagonals for three in a row. Not wanting to reinvent the wheel, I decided to implement this system in my game. Because it was a jQuery selector, I had to devise a way to re-implement it myself. Although I read the documentation on it, it was a one time speed read without deeply consulting it. Instead, I stood right there in front of my advisor/class instructor as we talked about it and devised how to recreate it, going only by how it was used in the game. I did not even play with the selector in some test code first. As it would be, after a bit of revision my idea worked (you can discover how I did it in the source code). The point is I had to devise a blueprint in order to implement this key part in the game. jQuery, as any good library should do, hides the complicated process from you and makes programming easier. We, as constant students of programming by keeping up with the times and modern methods, have to be careful not to let abstraction make us lazy programmers and not really think about what going on behind the scenes.

  • Finally, I tried something I had not done before and had fun doing it. I have said before, I do not want to be a video game programmer. There are so many variables, events, reactions, and factors that must be considered to the point I would be utterly lost. Tic-tac-toe is not a too demanding game, but as I have explained it did cause me to think differently. I still do not want to program a game, but this was a new experience for me, and I took it with eagerness and fun. I read an article about things an experienced programmer tells beginners, and one of his pieces of advise was “You will never be bored programming.” This is true, but I would add you will mostly have fun programming as well. Yes, debugging is no fun at all, and neither is being stuck between compiling errors and fact of life issues.

    Yet if you take the whole project in stride and really enjoy what you are doing, you will have fun, and this is why I experienced. This was a brand new challenge with brand new obstacles, and what better way to beat them than with a positive attitude and a smile on your face? ๐Ÿ˜€

The game’s code may not be the best or most straightforward around, nor the best looking thing (the design was rioforce’s idea, save the Comic Sans ๐Ÿ˜› ), and it is completely broken on mobile devices, but it is a faithful recreation of Tic-tac-toe in pure JavaScript. If you like to play it, it is available at, with the source code at

That is why I had fun creating Tic-tac-toe in JavaScript.



4 thoughts on “Creating Tic-tac-toe in JavaScript (and why I enjoyed it)

  1. I did write Tetris in JS (mainly because a schoolmate wanted me to), it was a great experience either, and I realised working with canvas’ isn’t as hard as I thought it to be (I wouldn’t wanna code a 3D game using canvas, though).
    I also didn’t use any library (not even querySelector!), and my code is missing comments as always, but it works quite well.
    I’d recommend you to do a canvas game sometimes, too. Snake may be interesting as well, but currently I don’t have time for such things (as always…).


    * Up/W/Space: Turn block
    * Down/S: Fall faster
    * Left/A: Move to the left
    * Right/D: Move to the right

    1. I played a round of Tetris the other day and just scanned over your code. I’m impressed! I had a hard enough time creating Tic-tac-toe, I would not be able to make a canvas-based Tetris game!

      I am sure canvas is not near as hard as imagined once you use it, but I haven’t a good resource (aside from MDN/Web Platform) to learn from. Also, I’m not really a game writer. I do not know why, but I prefer processing and actions over user-actions and collection. I should write a canvas-based game sometime (and I agree, Snake sounds like an interesting challenge), but I too no not have the time to do such (classes started yesterday, and this is essentially my last semester before graduation, and I am competing in a programming competition this March). ๐Ÿ˜ฆ

      As for use of querySelector, I kinda prefer that over getElementBy*. I think the appeal comes from using one single method and CSS selectors to select any element vs using three different methods depending on the use-case.

      1. As I said, canvas-based (2D) games aren’t as hard as I thought them to be. It was literally my first game written in JS and yeah, I thought it to be harder. But the code is pretty ugly and uncommented … as always.

        Yeah, finding a good resource was actually tough, but I went with MDN in the end, after reading a little tutorial about the things you can do with canvas.

        It’s the same with me, I’m not a game writer at all. I only did this as saying “yeah, yesterday I wrote yet another random API that fetches data from some random API” (they asked me what I usually code) doesn’t sound appealing to my classmates. I still prefer my minor-ish contributions to Brackets ๐Ÿ™‚

        Re “querySelector”, yeah, it’s a nice function, but considering I only had 3 or 4 HTML elements I had to update, giving them IDs sounded like a reasonable solution to me. If I had more elements to update, I’d have gone with querySelector or jQuery (it’s more powerful) as well.

Comments are closed.