Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/binarymuse/ultimate-ttt
Elixir implementation of the game Ultimate Tic-Tac-Toe
https://github.com/binarymuse/ultimate-ttt
board-game elixir
Last synced: 10 days ago
JSON representation
Elixir implementation of the game Ultimate Tic-Tac-Toe
- Host: GitHub
- URL: https://github.com/binarymuse/ultimate-ttt
- Owner: BinaryMuse
- Created: 2020-04-26T17:54:52.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2020-04-26T19:15:23.000Z (almost 5 years ago)
- Last Synced: 2025-01-28T15:12:33.584Z (12 days ago)
- Topics: board-game, elixir
- Language: Elixir
- Homepage: https://hexdocs.pm/ultimate_ttt/
- Size: 159 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Elixir Ultimate Tic-Tac-Toe
`UltimateTtt` is an Elixir module implementing the game Ultimate Tic-Tac-Toe. It implements the core, sequential game logic as well as an OTP app for creating and managing games. If you're unfamiliar with the game, [check out _Ultimate Tic-Tac-Toe_ by Ben Orlin](https://mathwithbaddrawings.com/ultimate-tic-tac-toe-original-post/).
## Links
- Package: [https://hex.pm/packages/ultimate_ttt](https://hex.pm/packages/ultimate_ttt)
- Documentation: [https://hexdocs.pm/ultimate_ttt/](https://hexdocs.pm/ultimate_ttt/)
- Source: [https://github.com/BinaryMuse/ultimate-ttt](https://github.com/BinaryMuse/ultimate-ttt)## Installation
This package is [available on Hex](https://hex.pm/packages/ultimate_ttt) and can be installed by adding `ultimate_ttt` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:ultimate_ttt, "~> 0.1.0"}
]
end
```## Game Rules
Ultimate Tic-Tac-Toe is played on a 3x3 grid, where each cell of the grid contains another 3x3 grid. The goal of the game is to win three games of tic-tac-toe in the inner grids such that they form a line in the outer grid.
The key rule of the game is that a play must be made in the board associated with the space the previous player played.
For example, `x` starts the game by plying anywhere they want. Here, they choose to play in the middle-left board (index 3) in the center space (index 4):
```elixir
alias UltimateTtt.Game
game = Game.new()
{:ok, game} = Game.place_tile(game, :x, {3, 4})
``````text
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
───────────┼───────────┼───────────
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ x │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
───────────┼───────────┼───────────
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
```Now, `o` is required to play somewhere in the board at the center of the outer grid, because `x` played in the center space in the grid they chose. Similarly, the square they choose to play on in this center board will affect which grid `x` will be forced to play in next.
```elixir
Game.valid_moves(game, :o)
``````text
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
───────────┼───────────┼───────────
│ │ │ + │ + │ + │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ x │ │ + │ + │ + │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ + │ + │ + │ │ │
───────────┼───────────┼───────────
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
───┼───┼───│───┼───┼───│───┼───┼───
│ │ │ │ │ │ │ │
```If a play forces the next player to play in a board that is either already claimed (by someone winning that board) or is full (resulting in a tie in the board), that player may choose to play anywhere they want.
The game is over when a player has won three inner boards in a row, resulting in a win for that player, or when every board is either won or a tie but no player has won three boards in a line, resulting in a tie.
## Example
### Core Rules
The core rules of Ultimate Tic-Tac-Toe are implemented by the `UltimateTtt.Game` module.
```elixir
iex> alias UltimateTtt.Game
iex> game = Game.new()
iex> Game.turn(game)
:x
iex> Game.valid_move?(game, :x, {3, 4})
true
iex> {:ok, game} = Game.place_tile(game, :x, {3, 4})
iex> Game.turn(game)
:o
iex> Game.valid_move?(game, :o, {3, 0}) # Player o has to play in the board at index 4
false
iex> Game.valid_move?(game, :x, {4, 0}) # Not player x's turn
false
iex> Game.valid_move?(game, :o, {4, 0})
true
iex> Game.valid_moves(game, :o)
[{4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}, {4, 5}, {4, 6}, {4, 7}, {4, 8}]
iex> Game.status(game)
:in_progress
iex> Game.last_played_space(game)
{3, 4}
iex> Game.tile_at(game, {3, 4})
:x
iex> Game.tile_at(game, {4, 0})
:empty
```### OTP App
(Not yet implemented)
```elixir
game = GameSession.start_link()
```