XO is a reference to Xs and Os which is an alternative name for Tic-tac-toe.
Get the next player.
nextPlayer X == O
nextPlayer O == XKeeps track of the internal state of a game.
This state includes: who played first, who's the current player, and the configuration of the board.
A (row, column) position. Both coordinates are 0-based and should range from 0 to 2.
The possible errors that could occur while playing a game.
Make a move at the given position with the current player of a game.
Various rules that help determine how subsequent games are played.
By default, the winner plays first and when a game ends in a draw the other player who didn't play first, gets to play first in the next game.
The external state of a game.
Either there is a winner, the game ended in a draw, or it is undecided because the game is still in progress.
The three positions on the board that represent the winning line.
Get the unoccupied positions on the board of a game.
Represents which player, if any, is at a position on a Tic-tac-toe board.
There are 9 positions/tiles on a Tic-tac-toe board. Apply a function over those positions/tiles in row-major order.
map Tuple.pair (start X)
== [ ( ( 0, 0 ), Nothing )
, ( ( 0, 1 ), Nothing )
, ( ( 0, 2 ), Nothing )
, ( ( 1, 0 ), Nothing )
, ( ( 1, 1 ), Nothing )
, ( ( 1, 2 ), Nothing )
, ( ( 2, 0 ), Nothing )
, ( ( 2, 1 ), Nothing )
, ( ( 2, 2 ), Nothing )
]A representation of the layout of the board for a game in row-major order.
toString (start X) == "........."
let
game0 =
start X
game1 =
play ( 0, 0 ) game0 |> Result.withDefault game0
game2 =
play ( 1, 1 ) game1 |> Result.withDefault game1
in
toString game2 == "x...o...."The report tells you the best outcome that can be achieved, assuming both players play perfectly.
possibilities is a list of pairs of position and number of moves. Each pair represents the
position to play, to achieve the best outcome, and the number of moves it takes to achieve it.
The best outcome that can be achieved.
W means you can winD means you can draw at bestL means no matter what position is played you will loseNot all games can be analyzed. For e.g. if all positions are occupied or the game is over then there's nothing to analyze.
Find the good unoccupied positions on the board of a game for the current player.
Suppose O has the next turn in a game, g1, with a board layout of x.o.x...., then
--
-- 0 1 2
-- 0 x | | o
-- ---+---+---
-- 1 | x |
-- ---+---+---
-- 2 | |
--
findGoodPositions g1
== { optimum = D
, possibilities = [ ( ( 2, 2 ), 6 ) ]
}It means that O can draw at best, in 6 moves, if O is played at (2, 2).
Suppose O has the next turn in a game, g2, with a board layout of xo..x...., then
--
-- 0 1 2
-- 0 x | o |
-- ---+---+---
-- 1 | x |
-- ---+---+---
-- 2 | |
--
findGoodPositions g2
== { optimum = L
, possibilities =
[ ( ( 0, 2 ), 2 )
, ( ( 1, 0 ), 2 )
, ( ( 1, 2 ), 2 )
, ( ( 2, 0 ), 2 )
, ( ( 2, 1 ), 2 )
, ( ( 2, 2 ), 4 )
]
}It means that no matter the position O plays, O will lose. However, if
O is played at (2, 2), in order to block X from the immediate win, then
O can extend the game a little more.
Suppose X has the next turn in a game, g3, with a board layout of x.ox...o., then
--
-- 0 1 2
-- 0 x | | o
-- ---+---+---
-- 1 x | |
-- ---+---+---
-- 2 | o |
--
findGoodPositions g3
== { optimum = W
, possibilities =
[ ( ( 1, 1 ), 3 )
, ( ( 1, 2 ), 3 )
, ( ( 2, 0 ), 1 )
, ( ( 2, 2 ), 3 )
]
}It means that X can win. X can either win immediately if X is played at (2, 0), or
X can have some fun and win in 3 moves if X is played at (1, 1), (1, 2), or (2, 2).
Suppose X has the next turn in a game, g4, with a board layout of x.o...x.o, then
--
-- 0 1 2
-- 0 x | | o
-- ---+---+---
-- 1 | |
-- ---+---+---
-- 2 x | | o
--
findGoodPositions g4
== { optimum = W
, possibilities = [ ( ( 1, 0 ), 1 ) ]
}It means that X can win immediately if X is played at (1, 0). Notice that
winning is favoured over blocking O at (1, 2).
N.B. All the analysis above assumes perfect play by both players.
A player is either an
Xor anO.