mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-28 21:54:17 -08:00
Merge pull request #757 from alingse-forks/implement-36
Implement 35 Even Wins with Rust
This commit is contained in:
8
35_Even_Wins/rust/Cargo.toml
Normal file
8
35_Even_Wins/rust/Cargo.toml
Normal 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]
|
||||
229
35_Even_Wins/rust/src/main.rs
Normal file
229
35_Even_Wins/rust/src/main.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user