andrew paradis
Scientist. Educator. Gourmand.

code projects: tic-tac-toe

So, the motivation here was to learn some jQuery, but also do something relatively fun and with a small footprint. The only possible conclusion is Tic-Tac-Toe!

Here is my working demo. The plan is to add some basic AI so that you can play against the computer, but at the moment it is a two-human game.

I found a tutorial that looked promising, and had at it. I won't repeat the explanations from the tutorial - you can see them for yourself at the link.

However, I didn't like their solution to detecting a winning move... it seemed awfully cumbersome to actually scan all rows, columns, and diagonals looking for the same player "mark." Granted, it was a neat use of jQuery filters, but like I said, it seemed cumbersome. As a math geek, I much prefer elegant solutions!

So I thought about it, searched the Intertubes, and decided to use a strategy involving N-bit bitwise comparisons. Let's say we have two binary strings:
A: 1 0 1 1 0
B: 1 0 0 1 0

If we do an AND on these (AND means, if the bits in the same location are both 1, then the result is also 1, otherwise the result is 0), we get:
C: 1 0 0 1 0

Do you see that our result, C, is actually the same as binary string B? That's pretty cool, because it means we can take advantage of this to use in the game!

Here's how it works. We assign numbers to each square on the game board. jQuery makes this possible through a neat trick... you can assign arbitrary data values to any DOM element!

So, while creating the playing area, I assign the next power of 2 to each of the squares. This gives us (for a 3x3 game) a 9-bit string. Visually, it would be:

          1  |   2 |   4
       -------------------
          8  |  16 |  32
       -------------------
         64  | 128 | 256
      

Now, we can just add up each row and column and diagonal, and find the sums that represent all the winning states. When a player clicks on any square to claim it, we take the value of that square and add it to the player's running sum. After each click, all we have to do is do a bitwise comparison between the collection of winning sums and the player's current sum. If the result spits out the winning sum, then that move resulted in a win!

For example, the top row has a winning sum of 1 + 2 + 4 = 7. So, when we're checking for a win, if we find that 7 & playerScore = 7 then that player has just made a winning move in the top row.

To keep things general, I actually have made the game board not have to be 3x3. You'll see in the JavaScript file that the number of rows is variable, and that we construct an array of "winning sums" based on the size of the board. Eventually, I'll add a control to the UI that let's you select the size of the board. For now, if you want to try it, just pull the HTML and JS files locally to play around with the variables.