Reversi Board Game
In this programming assignment, you are expected to implement a command-line utility for two human players to take turns and play a Reversi board game. The material you have learned in the first two lectures, including the guessing game example and basic programming concepts, will be useful when completing this assignment. This assignment is due at 11:59 p.m. on Monday, September 28, 2026.
Game Rules
Here is a brief description of the Reversi board game. Reversi is played on a 8x8 board (like a chess board or a checkers board) with two players. The game uses pieces that are white on one side, and black on the other side, and as it progresses, these pieces can be flipped over to change their colour. One player plays white, the other player plays black, and the players take turns to place their pieces on the board. The game starts with two white and two black pieces placed in advance at the centre. Observe that rows and columns are labelled with letters, ranging from a to h. If a position is empty, it is represented by a dot (.). The initial board configuration in this game is as follows:
abcdefgh
a ........
b ........
c ........
d ...WB...
e ...BW...
f ........
g ........
h ........A turn in the game consists of a player placing a piece of his/her own colour on a candidate empty board position, subject to the following two rules:
-
There must be a continuous straight line of piece(s) of the opponent’s colour in at least one of the eight directions from the candidate empty position (north, south, east, west, and diagonals).
-
In the position immediately following the continuous straight line mentioned in the rule above, a piece of the player’s own colour must already be placed.
In other words, a player can place a piece on an empty square if the square is adjacent to the opponent’s piece and the opponent’s pieces are sandwiched between the player’s own piece and the piece that the player just placed. After placing a piece at a position that meets the criteria above, all of the lines of the opponent’s pieces that meet the criteria above are then flipped to the player’s colour.
For example, starting from the initial board configuration above, if the black player plays at position cd, the board configuration will become the following after the move:
abcdefgh
a ........
b ........
c ...B....
d ...BB...
e ...BW...
f ........
g ........
h ........The turns alternate between the players, unless one player has no available move, in which case the only player with an available move is allowed to continue to make moves until a move becomes available for the opponent. At this point, the opponent is allowed to take a turn and the alternating turns between the players resumes. The game ends when no more moves can be made by both players, and the player with the most pieces on the board wins the game.
Playing the Game
In this assignment, you will write a command-line utility in Rust that allows two human players to take turns and play the game to completion, assuming that the player with the black colour always plays first. This utility should start with printing the initial board configuration, and prompting the black player to enter a move, such as the (valid) move cd. All moves should be entered with a two-character combination, using lowercase letters to represent rows and columns. Here is a sample run:
abcdefgh
a ........
b ........
c ........
d ...WB...
e ...BW...
f ........
g ........
h ........
Enter move for colour B (RowCol): cd
abcdefgh
a ........
b ........
c ...B....
d ...BB...
e ...BW...
f ........
g ........
h ........If a move is not valid, the utility should print Invalid move. Try again., and then print the current board again for the player to try another move.
Enter move for colour B (RowCol): dd
Invalid move. Try again.
abcdefgh
a ........
b ........
c ........
d ...WB...
e ...BW...
f ........
g ........
h ........
Enter move for colour B (RowCol):Once the first move is out of the way, the turns proceed following the game rules, alternating between Black and White unless one of the players has no move to make, in which case your program should print a message W player has no valid move. (i.e., for the case of the White player) and should prompt the opponent player for another move.
When working in this assignment, print the exact messages in the handout rather than customizing them to your own liking. The automarker will look for exact matches to the expected output, and your work will not be manually graded. In particular, you should not print anything that has not been explicitly mentioned in this handout, as any additional printing will affect the automarker when grading, and we will not be able to give you credits if the automarker fails.
For example, after printing the message W player has no valid move. here, you should not print the board again before prompting the opponent player for another move.
After each turn, your utility must print the current board, and must detect whether the game is over. If your utility detects the game is over (i.e. a win or a draw), a message is printed and the program terminates. The specific messages to print are: White wins by {x} points!, Black wins by {x} points!, or Draw!, where {x} represents the number of additional pieces that the winner has on the board than the opponent.
Implementation Notes
Similar to the guessing game example covered in our lectures, use the std::io module to read input from the user. You may also find it necessary to flush the standard output after printing the prompt, but before reading input from the user. To do this, use:
io::stdout().flush().expect("Failed to flush stdout.");Just like gen_range() needs to bring the rand::Rng trait into scope in the guessing game example, flush() needs to bring the Write trait into scope. We will cover traits in more detail in future lectures. You can do this by adding the following line to your Rust code:
use std::io::Write;Another useful trick is to use the as keyword to convert a variable to a different type. For example, to convert an isize-typed variable row to an unsigned type usize, you can use:
row as usizeYou will write this assignment in Rustrace, the course’s editor, which is required for all assignments. Download the assignment package, lab1.rta, save it in a normal local folder, and open it with:
rustrace work lab1.rtaRustrace unpacks a starter project into lab1.work, with a Cargo.toml file and a src/main.rs file, and opens the editor. The starter is a complete game shell: the input handling, the board printing, and the game loop are written for you, and five functions are left for you to implement. Each of them is marked with a todo!() placeholder and a comment that explains the rule to implement, the steps to take, and the pitfalls to avoid. Read the whole file first, then fill in the placeholders. You may also create additional files in the src directory if you need to. Compile and run your code with Check and Run in the F7 menu (Fn + F7 on Macs), or with cargo run in the F9 console (Fn + F9 on Macs), as described in the Rustrace guide.
Testing
Five public test cases come with the assignment package. Each one is a sequence of moves and the exact output that your program is expected to print. Press F4 (Fn + F4 on Macs) in Rustrace, or choose Test cases from the F7 menu (Fn + F7 on Macs), to see them; press Enter on a case to run your program with that input, and Rustrace compares the output with the expected output and reports PASS, FAIL with the number of the first line that differs, or ERROR if your program did not run to completion. Run all runs every case in turn.
The test cases are also placed as plain files in a test-cases directory next to lab1.work, so that you can read the inputs and expected outputs. If you prefer the console, cargo run < 33.in runs the case named 33 in the same way. Use the public cases to fix minor output differences, such as spacing or wording, and to check the game logic: every one of them exercises captures in all eight directions, and some of them include invalid moves or turns that must be passed.
Notes on AI Tools
This assignment is designed for manual work without AI assistance, and you should not use AI tools at all for this assignment. While we recognize that the habit of using AI may be so reflective and strong that — like social media — you cannot think without AI assistance, one of the objectives in this course is for you to learn writing code in the Rust programming language, and this learning experience needs to start from somewhere. This assignment offers an excellent starting point for you to learn from the beginning, and using AI defeats the purpose and completely changes the learning experience.
For this reason, you are required to write your programs in a dedicated Rust playground, called Rustrace, designed specifically for the programming assignments in this course. Rustrace records how your program came together, and it accepts only text that you type or copied within the editor itself. See the Rustrace guide for how to install and use it.
Submission
When you are done, quit Rustrace and create your submission from the terminal, using your UTORid as the identifier:
rustrace submit lab1.work --student-id YOUR_UTORIDThis finalizes your work and writes a .zip file, named after your UTORid and the assignment, next to the lab1.work directory. Upload that .zip file to Quercus, under Assignment 1. Rustrace does not upload anything by itself, and the .zip file already contains everything that is needed for marking, so do not add or remove anything.
The deadline for this assignment is Monday, September 28, 2026, at 11:59pm Eastern time, and late submissions will not be accepted. Once you have run rustrace submit, your lab1.work directory is finalized and cannot be reopened; if you need to change your work before the deadline, follow the revision steps in the Rustrace guide and upload the new ZIP file. Keep the lab1.work directory until your grade is released.
Marking
Your project will be built and tested using the cargo run command against a set of 10 test cases, including 5 public test cases that are released to you, and 5 more hidden test cases that we use internally for testing your solutions. The marking will be based on the correctness of your implementation in these test cases, by comparing the output of your code to the correct output. An extra newline character at the end of your output will not affect the automarker.
You should make sure that your code is free of warnings when compiled with the cargo build or the cargo check command within the interactive Rustrace terminal.