From 48cb481d733145275401f263881086dfc18df905 Mon Sep 17 00:00:00 2001 From: Pranav Gaddamadugu Date: Tue, 20 Sep 2022 11:52:21 -0700 Subject: [PATCH] Update README for tictactoe --- examples/tictactoe/README.md | 33 ++++++++++++++++++++++---- examples/tictactoe/inputs/tictactoe.in | 6 +++++ examples/tictactoe/src/main.leo | 30 ++++++++++++++++++++++- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/examples/tictactoe/README.md b/examples/tictactoe/README.md index e2f4d08222..48243ac1d8 100644 --- a/examples/tictactoe/README.md +++ b/examples/tictactoe/README.md @@ -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 ... +``` +See `./run.sh` for an example. + + +### Using an input file. +1. Modify `inputs/tictactoe.in` with the desired inputs. +2. Run +```bash +leo run ``` diff --git a/examples/tictactoe/inputs/tictactoe.in b/examples/tictactoe/inputs/tictactoe.in index 41b1e8afed..76c9aa77d0 100644 --- a/examples/tictactoe/inputs/tictactoe.in +++ b/examples/tictactoe/inputs/tictactoe.in @@ -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; diff --git a/examples/tictactoe/src/main.leo b/examples/tictactoe/src/main.leo index 601c2dd69f..dd2adc45b1 100644 --- a/examples/tictactoe/src/main.leo +++ b/examples/tictactoe/src/main.leo @@ -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) {