Skip to content

Commit

Permalink
Merge pull request #201 from dstrain115/fix_quantum_tic_tac_toe
Browse files Browse the repository at this point in the history
Add documentation for TicTacToe
  • Loading branch information
dstrain115 authored Jul 10, 2024
2 parents af86a31 + 1dc6d95 commit ae5bb49
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 121 deletions.
52 changes: 52 additions & 0 deletions examples/tic_tac_toe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,55 @@ After cloning the Unitary library you can use command line flags to run the game
```
python -m examples.tic_tac_toe.tic_tac_toe
```

## Rules of the game

There are nine positions on the 3x3 board, labeled a through h.
The object is to get three in a row. Players alternate turns,
placing either an X or an O on each square.

In the quantum version, there is an additional move for placing
an X or an O on two squares in superposition, called the split move.

Once the board is full (i.e. each of the squares has either X,
O, or a superposition of them), the board is measured and the
result is determined.

## Quantum representation

Each square is represented as a Qutrit. This square can either be:

* |0> meaning that the square is empty
* |1> meaning that the square has an X
* |2> meaning that the square has an O

Placing an X or O will do the qutrit version of an "X" gate
on that square. Since these are qutrits (not qubits), the
definition of this gate is that it is swapping the amplitude
of the zero state with either the one or two state
(depending on whether this is an X or O move).
For example, if someone places an O on a square, then placing
an X on that same square has no effect, since the zero state
has zero amplitude.

Note that there are two variants of the rules with regards to
the split move. In one rule, the qutrit X gate is applied
followed by a square root of iSWAP gate (restricted to either the
|1> or |2> subspace depending on the move).

In the other variant, the corresponding states |01> and |10>
(or |02> and |20>) are swapped.

## Code organization

The qutrit operations (such as the split move) are defined in
`tic_tac_split.py`. These classes can be used as examples of
how to create your own gates and effects using unitary.

The game itself is defined in `tic_tac_toe.py`. The `GameInterface`
class defines the main game loop and input/output.

The `TicTacToe` class keeps track of the game state and also
allows you to sample (measure) the board.

Enums used by the example are stored in `enums.py`.
113 changes: 0 additions & 113 deletions examples/tic_tac_toe/ascii_board.py

This file was deleted.

16 changes: 16 additions & 0 deletions examples/tic_tac_toe/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,20 @@


class GameMoves(enum.Enum):
"""Possible inputs for the ASCII version of tic tac toe."""

EXIT = "exit"
MAP = "map"
HELP = "help"


class TicTacSquare(enum.Enum):
"""Possible states of one tic tac toe square.
For the quantum version of tic tac toe, these
are represented as qutrits (qubits with three states).
"""

EMPTY = 0
X = 1
O = 2
Expand All @@ -35,6 +43,14 @@ def from_result(cls, value: Union[enum.Enum, int]):


class TicTacResult(enum.Enum):
"""End results of a tic tac toe game.
Either one side has won or it is a draw.
If the game has continued past the end state,
it is possible both sides have completed a three-in-a-row.
If the game is not complete, the result is UNFINISHED.
"""

UNFINISHED = 0
X_WINS = 1
O_WINS = 2
Expand Down
17 changes: 9 additions & 8 deletions examples/tic_tac_toe/tic_tac_toe.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ def _result_to_str(result: List[TicTacSquare]) -> str:


def eval_board(result: List[TicTacSquare]) -> TicTacResult:
"""Determines who has won the tic tac toe board.
This function checks all the possible three-in-a-row positions
(all cols, all rows, and the two diagonals. Depending on which
player(s) have a three in a row (X's, O's, both, or neither)
returns the result of the tic tac toe board.
"""
x_wins = False
o_wins = False
still_empty = False
Expand All @@ -90,18 +97,12 @@ def eval_board(result: List[TicTacSquare]) -> TicTacResult:
if any(result[check[idx]] == TicTacSquare.EMPTY for idx in range(3)):
still_empty = True
if x_wins:
if o_wins:
return TicTacResult.BOTH_WIN
else:
return TicTacResult.X_WINS
return TicTacResult.BOTH_WIN if o_wins else TicTacResult.X_WINS
else:
if o_wins:
return TicTacResult.O_WINS
else:
if still_empty:
return TicTacResult.UNFINISHED
else:
return TicTacResult.DRAW
return TicTacResult.UNFINISHED if still_empty else TicTacResult.DRAW


class TicTacToe:
Expand Down

0 comments on commit ae5bb49

Please sign in to comment.