This was my first web app. Designed using vanilla Javascript with a Rails back-end to store user and game state.
As a budding developer, this project was quite an undertaking. Trying to come up with an elegant solution for
calculating game logic was by far the most rewarding challenge of making this app. This is where Math.js came in use.
Knowing a little about linear algebra, I knew that if I could represent the game-board as a 3x3 matrix, I could use vector addition
to elegantly solve for each win condition. By representing each player as a +1 or -1 and unmarked cells as 0, this allowed
me to add up each cell that had been marked and simply check if any sum added up to an absolute value of 3, which would indicate
that there was 3 of the same type of mark on each cell in a row (or column, or diagonal).
This was trivial on rows and columns, but the diagonals presented a more difficult challenge.
A diagonal in matrix algebra is not something you can easily sum across, because it has elements from each row and column.
However, using the MathJS library, which is where I used the Math.Matrix object to represent my game board, I found a
method that calculated the trace of a matrix. The trace is a property of a matrix that is just the sum of the elements on
the main diagonal, which is the diagonal starting at the top-left corner. Easy-peasy.
But what about the other diagonal...
It turns out that the so-called "minor-diagonal," the one starting on the top-right, is not nearly as significant
in linear algebra, and so no one had written a function for calculating the 'other' trace (I was not even able to find
a mathematical term describing the sum of minor-diagonal elements). After messing around with trying to manually rotate my
game-board matrix by 90 degrees using rotation matrices (so I could then re-use the trace function), I kept on realizing that
none of my expected results were working, so I decided to hard-code a solution for the 'other' diagonal due to time constraints.
I was not done with this problem however. Having used Python's NumPy library before, I knew that it had a rich library of matrix methods,
so that is where I looked next. I eventually found that there was still no method for calculating an inverse trace, but there was one for
flipping a matrix about the vertical axis. This allowed me to use a trace method after flipping, which converts the minor diagonal to the
main diagonal.
After all was said and done, using Python I was able to get my entire game logic down to about 5 lines of code, and I have now begun reconstructing
my back-end in Django so I can calculate game-logic on the server-side using Python.