TicTacToe: Extracting the winning lines with Ruby
In order for TicTacToe to work, you require some kind of mechanism to find out whether or not a player has won. I had a Board
object with a winner
and won?
method to work out whether or not there was a winner.
My Board object consists of a 1D array called positions
which keeps track of which marks are present in which position. So a 3x3 board is a 9-element array, where the first element represents the top left position, and the last element represents the bottom right position.
Initially, in order to find a winner, I had a simple loop that iterated across all possible winning configurations. For example I had the following array (of arrays), and found the winner by indexing positions
array and checked if the same mark existed on every position;
WINNING POSITIONS = [[0, 1, 2], [3, 4, 5], [6, 7, 8], ...]
This works fine for 3x3, but if you want to have a board with an arbitrary size, this doesn’t work. Instead of hard coding the winning positions, Ruby’s Enumerable Module provides some powerful ways of manipulating arrays.
To extract the rows, the each_slice
method splits the array into slices by a particular size. Here, I split it into slices where the size is the square root of the number of positions on the board (i.e. a board with 9 positions will have a row size of 3)
To extract the columns, the transpose method takes a 2d array, and swaps the rows and columns.
Diagonal lines are slightly trickier, but with the collect
method, you can build a new array to pull out the diagonal lines from positions
Now that you have all of these winning lines, you can use the find
method to find which line, if any, on the board has the same mark sitting on them. My winner method ended up looking something like this;
The result is I can create a board size with any size, and these methods will always be able to extract the correct winning lines.
This blog post only scratches the surface regarding the methods which are available in the Enumerable module, but it is well worth a read to see what is possible.