Merge pull request #757 from alingse-forks/implement-36

Implement 35 Even Wins with Rust
This commit is contained in:
Jeff Atwood
2022-06-05 12:50:29 -07:00
committed by GitHub
2 changed files with 237 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,229 @@
use std::io;
fn print_intro() {
println!(
"Welcome to Even Wins!
Based on evenwins.bas from Creative Computing
Even Wins is a two-person game. You start with
27 marbles in the middle of the table.
Players alternate taking marbles from the middle.
A player can take 1 to 4 marbles on their turn, and
turns cannot be skipped. The game ends when there are
no marbles left, and the winner is the one with an even
number of marbles.
"
);
}
#[derive(Debug)]
enum PlayerType {
Human,
Computer,
}
#[derive(Debug)]
struct Game {
turn: PlayerType,
middle: u32,
human: u32,
computer: u32,
min_take: u32,
max_take: u32,
}
impl Game {
fn get_max_take(&mut self) -> u32 {
if self.max_take > self.middle {
return self.middle;
}
return self.max_take;
}
fn take(&mut self, num: u32) -> bool {
let max_take = self.get_max_take();
if num > max_take {
println!("You can take at most {} marbles", max_take);
return false;
}
if num < self.min_take {
println!("You must take at least {} marble!", self.min_take);
return false;
}
self.middle -= num;
match self.turn {
PlayerType::Computer => self.computer += num,
PlayerType::Human => self.human += num,
}
return true;
}
fn next(&mut self) {
self.turn = match self.turn {
PlayerType::Computer => PlayerType::Human,
PlayerType::Human => PlayerType::Computer,
}
}
fn info(&mut self) {
println!("");
println!(
"marbles in the middle: {} **************************",
self.middle
);
println!("# marbles you have: {}", self.human);
println!("# marbles computer has: {}", self.computer);
println!("");
}
fn wininfo(&mut self) {
if self.middle != 0 {
return;
}
println!("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!! All the marbles are taken: Game Over!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
self.info();
if self.human % 2 == 0 {
println!("You are the winner! Congratulations!");
} else {
println!("The computer wins: all hail mighty silicon!");
}
println!("");
}
}
fn human_play(game: &mut Game) {
println!("It's your turn!");
loop {
let max_take = game.get_max_take();
println!("Marbles to take? ({} - {}) --> ", game.min_take, max_take);
let mut num = String::new();
io::stdin()
.read_line(&mut num)
.expect("Failed to read line");
let _: u32 = match num.trim().to_uppercase().parse() {
Ok(num) => {
if game.take(num) {
println!("Okay, taking {} marble ...", num);
break;
};
println!("");
continue;
}
_ => {
println!("Please enter a whole number from 1 to 4");
println!("");
continue;
}
};
}
}
fn compute_play(game: &mut Game) {
println!("It's the computer's turn ...");
let marbles_to_take: u32;
// the magic 6 and 1.5, 5.3 3.4 4.7 3.5 was copy from python implement
let r: f32 = (game.middle % 6) as f32;
if game.human % 2 == 0 {
if r < 1.5 || r > 5.3 {
marbles_to_take = 1;
} else {
marbles_to_take = (r - 1.0) as u32;
}
} else if game.middle <= 4 {
marbles_to_take = game.middle
} else if r > 3.4 {
if r < 4.7 || r > 3.5 {
marbles_to_take = 4;
} else {
marbles_to_take = 1;
}
} else {
marbles_to_take = (r + 1.0) as u32;
}
game.take(marbles_to_take);
println!("Computer takes {} marble ...", marbles_to_take);
}
fn run_game(turn: PlayerType) {
let mut game = Game {
turn: turn,
middle: 27,
computer: 0,
human: 0,
min_take: 1,
max_take: 4,
};
while game.middle > 0 {
match game.turn {
PlayerType::Computer => {
compute_play(&mut game);
}
PlayerType::Human => {
human_play(&mut game);
}
}
game.info();
game.next();
}
game.wininfo();
}
fn choose_first_player() -> PlayerType {
loop {
println!("Do you want to play first? (y/n) -->");
let mut flag = String::new();
io::stdin()
.read_line(&mut flag)
.expect("Failed to read line");
match flag.trim().to_uppercase().as_str() {
"Y" => return PlayerType::Human,
"N" => return PlayerType::Computer,
_ => {
println!("Please enter \"y\" if you want to play first,\nor \"n\" if you want to play second.\n");
}
};
}
}
fn choose_play_again() -> bool {
println!("Would you like to play again? (y/n) --> ");
let mut flag = String::new();
io::stdin()
.read_line(&mut flag)
.expect("Failed to read line");
match flag.trim().to_uppercase().as_str() {
"Y" => {
println!("\nOk, let's play again ...\n");
return true;
}
_ => {
println!("\nOk, thanks for playing ... goodbye!\n");
return false;
}
}
}
fn main() {
print_intro();
loop {
let first = choose_first_player();
run_game(first);
if !choose_play_again() {
return;
}
}
}