Skip to content

Instantly share code, notes, and snippets.

@DrMetallius
Created August 31, 2019 20:32
Show Gist options
  • Save DrMetallius/2b2f45a8129bfa482e2dc7345edb8fb7 to your computer and use it in GitHub Desktop.
Save DrMetallius/2b2f45a8129bfa482e2dc7345edb8fb7 to your computer and use it in GitHub Desktop.
Rock Paper Scissors
extern crate rand;
use std::io;
use rand::os::OsRng;
use rand::Rng;
fn main() {
let mut choice_maker = ChoiceMaker::new();
let stdin = io::stdin();
let mut buffer = &mut String::new();
let mut wins = 0;
let mut losses = 0;
loop {
buffer.clear();
stdin.read_line(buffer).unwrap();
let text = buffer.trim().to_lowercase();
let choice = match text.as_ref() {
"rock" => Choice::Rock,
"paper" => Choice::Paper,
"scissors" => Choice::Scissors,
"exit" => return,
_ => {
println!("{} is not a valid choice. Enter \"rock\", \"paper\", or \"scissors\" to make a choice or \"exit\" to quit.", text);
continue;
}
};
let ai_choice = choice_maker.make_choice();
println!("Computer chose {}", ai_choice.to_string());
let outcome = get_outcome(choice, ai_choice);
choice_maker.learn(ai_choice, outcome);
let message = match outcome {
PlayerOutcome::Loss => {
losses += 1;
"You have chosen poorly. You've lost!"
},
PlayerOutcome::Win => {
wins += 1;
"You have chosen wisely. You've won!"
},
PlayerOutcome::Tie => "This is a tie..."
};
println!("{} So far the score is {} - {}", message, wins, losses);
}
}
#[derive(PartialEq, Copy, Clone)]
enum Choice {
Rock,
Paper,
Scissors
}
impl ToString for Choice {
fn to_string(&self) -> String {
let string = match *self {
Choice::Rock => "rock",
Choice::Paper => "paper",
Choice::Scissors => "scissors"
};
String::from(string)
}
}
#[derive(PartialEq, Copy, Clone)]
enum PlayerOutcome {
Loss,
Win,
Tie
}
fn get_outcome(choice: Choice, other_choice: Choice) -> PlayerOutcome {
if choice == other_choice {
PlayerOutcome::Tie
} else {
let win = match choice {
Choice::Rock => other_choice == Choice::Scissors,
Choice::Paper => other_choice == Choice::Rock,
Choice::Scissors => other_choice == Choice::Paper
};
if win { PlayerOutcome::Win } else { PlayerOutcome::Loss }
}
}
struct ChoiceMaker {
rock: u32,
paper: u32,
scissors: u32,
rand: OsRng
}
impl ChoiceMaker {
fn new() -> ChoiceMaker {
ChoiceMaker {
rock: 1,
paper: 1,
scissors: 1,
rand: OsRng::new().unwrap()
}
}
fn make_choice(&mut self) -> Choice {
let sum = self.rock + self.scissors + self.paper;
let result = self.rand.gen_range(0, sum);
if result < self.rock {
Choice::Rock
} else if result < self.rock + self.scissors {
Choice::Scissors
} else {
Choice::Paper
}
}
fn learn(&mut self, choice: Choice, outcome: PlayerOutcome) {
if outcome == PlayerOutcome::Tie {
return;
}
let record_ref = self.get_choice_record_ref(choice);
if outcome == PlayerOutcome::Loss {
*record_ref += 1;
} else if outcome == PlayerOutcome::Win && *record_ref > 1 {
*record_ref -= 1;
}
}
fn get_choice_record_ref(&mut self, choice: Choice) -> &mut u32 {
match choice {
Choice::Rock => &mut self.rock,
Choice::Paper => &mut self.paper,
Choice::Scissors => &mut self.scissors
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment