This blog post is the second update about my Tic-tac-toe game, being written in Swift. The source code is available on GitHub:
Over the past week I wrote an intelligent agent which implements the Tic-tac-toe strategy devised by Allen Newell and Herbert Simon in 1972, as explained here. This algorithm is supposed to be a perfect player, meaning it will defeat an imperfect opponent and tie a perfect opponent.
I wrote a method to test that my implementation of the Newell and Simon algorithm is correct when playing against itself. This method is found in GameTests:
As seen above, the Game initializer requires a strategy for each player (X and O). Those arguments must adopt the TicTacToeStrategy protocol:
It might seem odd that the chosen position is passed to a completion handler, instead of simply being returned from the method, but this design will be necessary later to accommodate a human player.
This protocol is adopted by the intelligent agent:
An instance of this class has an ordered sequence of tactics, each of which adopts the NewellAndSimonTactic protocol.
Note that the NewellAndSimonStrategy initializer defines a list of tactics as a default parameter value. This is a useful technique for enabling unit tests to inject mock objects, which is exactly what I did in NewellAndSimonStrategyTests:
A tactic is a means of determining which position to occupy on a game board. For example, CenterTactic is the simplest tactic in the Newell and Simon strategy:
The behavior of this tactic is verified by unit test methods defined in WinTacticTests:
In case you’re curious about that board3x3 function, it is part of a simple domain-specific language (DSL) I created for turning a text diagram of a Tic-tac-toe game into the equivalent GameBoard instance. That DSL code can be found in GameBoard+DSL.swift.
My next major milestone is to create an iOS app that consumes the Tic-tac-toe library I’ve written so far. See you next time!
Next article: Creating Tic-tac-toe in Swift: User Interface