Ultimate Tic-Tac-Toe v0.1.0 UltimateTtt.Game View Source

This module implements the core, sequential rules of Ultimate Tic-Tac-Toe.

To begin a game, use new/0. Make plays on the board with place_tile/3.

alias UltimateTtt.Game
game = Game.new()
# Place an "x" in the center board, in the top-left square
{:ok, game} = Game.place_tile(game, :x, {4, 0})

You can check whether or not a move would be valid for a player using valid_move?/3. Note that this function returns false if it's not the given player's turn. (To check if a given move is valid for any player, use board/1 and pass it to UltimateTtt.Game.OuterBoard.valid_move?/2.) You can get a list of all valid moves for a player with valid_moves/2 (or valid moves for any player using UltimateTtt.Game.OuterBoard.valid_moves/1), which can be useful for highlighting valid moves in a UI.

Note that no moves are considered valid once the game is over.

In this example, since :x just played in the top-left square of a board, :o must now play inside the top-left board, if possible.

Game.valid_move?(game, :o, {2, 3}) # false, not in top-left board!
Game.valid_move?(game, :x, {0, 3}) # false, not x's turn!
Game.valid_move?(game, :o, {0, 3}) # true
Game.valid_moves(game, :o) # [{0, 0}, {0, 1}, {0, 2}, {0, 3}, ...]

Finally, you can get an overall status of the game using status/1. The possible return values are :in_progress, :tie, and {:win, player} where player is :x or :o.

Game.status(game) # :in_progress

Link to this section Summary

Types

An atom representing the player playing "X" or "O".

A tuple of two numbers; the first number represents the index of the board, starting in the top-left cell and moving to the right and then to the left-most cell on the next row, and the second number represents the index of the cell inside that board.

t()

Represents the data for a single tile in a tic-tac-toe board; can be one of either players or :empty.

Functions

Return the UltimateTtt.Game.OuterBoard contained within the game.

Returns the space that the most recent move was made in.

Creates a new game. The :x player starts.

Get the status of the game.

Returns the tile at the given space.

Return the player who should play the next turn.

Determines if the given play is valid. Returns false if it's not the given player's turn, even if the move would otherwise be valid. Always returns false once the game is over.

Get a list of all valid moves for the given player. Will return an empty list if it's not the given player's turn, even if some moves would otherwise be valid. No moves are valid once the game is won.

Link to this section Types

Link to this type

game_status()

View Source
game_status() :: :in_progress | :tie | {:win, player()}
Link to this type

player()

View Source
player() :: :x | :o

An atom representing the player playing "X" or "O".

A tuple of two numbers; the first number represents the index of the board, starting in the top-left cell and moving to the right and then to the left-most cell on the next row, and the second number represents the index of the cell inside that board.

Link to this type

tile()

View Source
tile() :: player() | :empty

Represents the data for a single tile in a tic-tac-toe board; can be one of either players or :empty.

Link to this section Functions

Return the UltimateTtt.Game.OuterBoard contained within the game.

Link to this function

last_played_space(game)

View Source
last_played_space(t()) :: space() | nil

Returns the space that the most recent move was made in.

Examples

iex> alias UltimateTtt.Game
iex> game = Game.new()
iex> Game.last_played_space(game)
nil
iex> {:ok, game} = Game.place_tile(game, :x, {0, 4})
iex> Game.last_played_space(game)
{0, 4}

Creates a new game. The :x player starts.

Link to this function

place_tile(game, player, space)

View Source
place_tile(t(), player(), space()) :: {:ok, t()} | {:error, :invalid_move}

Place a new tile.

Examples

iex> alias UltimateTtt.Game
iex> game = Game.new()
iex> {:ok, game} = Game.place_tile(game, :x, {0, 0})
iex> Game.valid_move?(game, :o, {0, 0})
false

Get the status of the game.

Examples

iex> alias UltimateTtt.Game
iex> game = Game.new()
iex> Game.status(game)
:in_progress
Link to this function

tile_at(game, space)

View Source
tile_at(t(), space()) :: tile()

Returns the tile at the given space.

Examples

iex> alias UltimateTtt.Game
iex> game = Game.new()
iex> Game.tile_at(game, {0, 0})
:empty
iex> {:ok, game} = Game.place_tile(game, :x, {0, 0})
iex> Game.tile_at(game, {0, 0})
:x

Return the player who should play the next turn.

Examples

iex> alias UltimateTtt.Game
iex> game = Game.new()
iex> Game.turn(game)
:x
iex> {:ok, game} = Game.place_tile(game, :x, {0, 0})
iex> Game.turn(game)
:o
Link to this function

valid_move?(game, player, space)

View Source
valid_move?(t(), player(), space()) :: boolean()

Determines if the given play is valid. Returns false if it's not the given player's turn, even if the move would otherwise be valid. Always returns false once the game is over.

Examples

iex> alias UltimateTtt.Game
iex> game = Game.new()
iex> Game.valid_move?(game, :x, {0, 0})
true
iex> Game.valid_move?(game, :o, {0, 0})
false
Link to this function

valid_moves(game, player)

View Source
valid_moves(t(), player()) :: [space()]

Get a list of all valid moves for the given player. Will return an empty list if it's not the given player's turn, even if some moves would otherwise be valid. No moves are valid once the game is won.

Examples

iex> alias UltimateTtt.Game
iex> game = Game.new()
iex> moves = Game.valid_moves(game, :x)
iex> Enum.count(moves)
81
iex> Game.valid_moves(game, :o)
[]