Update README for tictactoe

This commit is contained in:
Pranav Gaddamadugu 2022-09-20 11:52:21 -07:00
parent 93307b1446
commit 48cb481d73
3 changed files with 64 additions and 5 deletions

View File

@ -1,8 +1,33 @@
# tictactoe.aleo
# Tic Tac Toe
## Build Guide
A simple Tic Tac Toe game written in Leo.
To compile this Aleo program, run:
## Representing State
Leo allows users to define composite data types with the `circuit` keyword.
The game board is represented by a circuit called `Board`, which contains three `Row`s.
An alternative representation would be to use an array, however, these are not yet supported in Leo.
## Language Features
- `circuit` declarations
- conditional statements
- early termination. Leo allows users to return from a function early using the `return` keyword.
## Running the Program
Leo provides users with a command line interface for compiling and running Leo programs.
Users may either specify input values via the command line or provide an input file in `inputs/`.
### Providing inputs via the command line.
1. Run
```bash
aleo build
leo run <function_name> <input_1> <input_2> ...
```
See `./run.sh` for an example.
### Using an input file.
1. Modify `inputs/tictactoe.in` with the desired inputs.
2. Run
```bash
leo run <function_name>
```

View File

@ -1,5 +1,11 @@
// The `new` function does not take any inputs.
[new]
// Inputs for the `make_move` function.
// - `player` : A u8 representing the player making the move. 1 for player 1, 2 for player 2.
// - `row` : A u8 representing the row to make the move in.
// - `column` : A u8 representing the column to make the move in.
// - `board` : A representation of the board state.
[make_move]
player: u8 = 1u8;
row: u8 = 1u8;

View File

@ -1,15 +1,26 @@
// A row in a tic tac toe board.
// - `c1` : The first entry in the row.
// - `c2` : The second entry in the row.
// - `c3` : The third entry in the row.
// A valid entry is either 0, 1, or 2, where 0 is empty, 1 corresponds to player 1, and 2 corresponds to player 2.
// Any other values are invalid.
circuit Row {
c1: u8,
c2: u8,
c3: u8
}
// A tic tac toe board.
// - `r1` : The first row in the board.
// - `r2` : The second row in the board.
// - `r3` : The third row in the board.
circuit Board {
r1: Row,
r2: Row,
r3: Row,
}
// Returns an empty board.
@program
function new() -> Board {
return Board {
@ -19,6 +30,9 @@ function new() -> Board {
};
}
// Returns `true` if there exists a row, column, or diagonal with all entries occupied by the same player.
// - `b` : A tic tac toe board.
// - `p` : A number corresponding to a player.
function check_for_win(b: Board, p: u8) -> bool {
return
(b.r1.c1 == p && b.r1.c2 == p && b.r1.c3 == p) || // row 1
@ -31,12 +45,23 @@ function check_for_win(b: Board, p: u8) -> bool {
(b.r1.c3 == p && b.r2.c2 == p && b.r3.c1 == p); // other diagonal
}
// Returns an updated tic tac toe board with a move made by a player.
// Returns a `u8` corresponding to the player who won the game, or 0 if no one has won yet.
// - `player` : A number corresponding to a player.
// - `row` : The row of the move.
// - `col` : The column of the move.
// - `board` : A tic tac toe board.
// Assumes that `player` is either 1 or 2.
// Assumes that `row` and `col` are valid indices into the board.
// If an entry is already occupied, the move is invalid and the board is returned unchanged.
@program
function make_move(player: u8, row: u8, col: u8, board: Board) -> (Board, u8) {
console.assert(player == 1u8 || player == 2u8); // 1 for X, 2 for O
// Check that inputs are valid.
console.assert(player == 1u8 || player == 2u8);
console.assert(1u8 <= row && row <= 3u8);
console.assert(1u8 <= col && col <= 3u8);
// Unpack the entries in the board into variables.
let r1c1: u8 = board.r1.c1;
let r1c2: u8 = board.r1.c2;
let r1c3: u8 = board.r1.c3;
@ -47,6 +72,7 @@ function make_move(player: u8, row: u8, col: u8, board: Board) -> (Board, u8) {
let r3c2: u8 = board.r3.c2;
let r3c3: u8 = board.r3.c3;
// Update the appropriate entry with the given move.
if row == 1u8 && col == 1u8 && r1c1 == 0u8 {
r1c1 = player;
} else if row == 1u8 && col == 2u8 && r1c2 == 0u8 {
@ -67,12 +93,14 @@ function make_move(player: u8, row: u8, col: u8, board: Board) -> (Board, u8) {
r3c3 = player;
}
// Construct the updated game board.
let updated: Board = Board {
r1: Row { c1: r1c1, c2: r1c2, c3: r1c3 },
r2: Row { c1: r2c1, c2: r2c2, c3: r2c3 },
r3: Row { c1: r3c1, c2: r2c2, c3: r2c3 },
};
// Check if the game is over.
if check_for_win(updated, 1u8) {
return (updated, 1u8);
} else if check_for_win(updated, 2u8) {