Skip to content

Instantly share code, notes, and snippets.

@BSN4
Created January 2, 2025 01:38
Show Gist options
  • Save BSN4/a624be23f49c9d1ee9545808d916af24 to your computer and use it in GitHub Desktop.
Save BSN4/a624be23f49c9d1ee9545808d916af24 to your computer and use it in GitHub Desktop.
rock_paper_rust v1
use rand::Rng;
use std::io::{self, Write};
#[derive(Debug)]
struct Score {
player: u32,
computer: u32,
}
#[derive(Debug, PartialEq, Clone)]
enum Move {
Rock,
Paper,
Scissors,
}
enum GameResult {
PlayerWins(Move, Move),
ComputerWins(Move, Move),
Draw(Move),
}
fn main() {
play();
}
fn play() {
let mut score = Score {
player: 0,
computer: 0,
};
for round in 1..=3 {
println!("\nRound {}", round);
play_round(&mut score);
}
announce_winner(&score);
maybe_play_again();
}
fn play_round(score: &mut Score) {
match get_player_move() {
Ok(player_move) => {
let computer_move = random_move();
println!("Computer chose: {}", move_to_str(&computer_move));
let result = determine_winner(&player_move, &computer_move);
println!("{}", format_result(&result));
update_score(&result, score);
}
Err(msg) => {
println!("{}", msg);
play_round(score);
}
}
}
fn get_player_move() -> Result<Move, &'static str> {
print!("Enter your move (rock/paper/scissors): ");
io::stdout().flush().unwrap();
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.map_err(|_| "Failed to read input")?;
parse_move(&input)
}
fn parse_move(input: &str) -> Result<Move, &'static str> {
match input.trim().to_lowercase().as_str() {
"rock" => Ok(Move::Rock),
"paper" => Ok(Move::Paper),
"scissors" => Ok(Move::Scissors),
_ => Err("Invalid move. Please enter rock, paper, or scissors."),
}
}
fn move_to_str(move_: &Move) -> &'static str {
match move_ {
Move::Rock => "rock",
Move::Paper => "paper",
Move::Scissors => "scissors",
}
}
fn random_move() -> Move {
match rand::thread_rng().gen_range(0..3) {
0 => Move::Rock,
1 => Move::Paper,
_ => Move::Scissors,
}
}
fn determine_winner(player: &Move, computer: &Move) -> GameResult {
match (player, computer) {
(Move::Rock, Move::Scissors) => GameResult::PlayerWins(Move::Rock, Move::Scissors),
(Move::Paper, Move::Rock) => GameResult::PlayerWins(Move::Paper, Move::Rock),
(Move::Scissors, Move::Paper) => GameResult::PlayerWins(Move::Scissors, Move::Paper),
(p, c) if p == c => GameResult::Draw(p.clone()),
(p, c) => GameResult::ComputerWins(c.clone(), p.clone()),
}
}
fn format_result(result: &GameResult) -> String {
match result {
GameResult::PlayerWins(threw, beat) => {
format!(
"You won by throwing {} against {}",
move_to_str(threw),
move_to_str(beat)
)
}
GameResult::ComputerWins(threw, beat) => {
format!(
"Computer won by throwing {} against {}",
move_to_str(threw),
move_to_str(beat)
)
}
GameResult::Draw(move_) => {
format!("Draw! Both players threw {}", move_to_str(move_))
}
}
}
fn update_score(result: &GameResult, score: &mut Score) {
match result {
GameResult::PlayerWins(_, _) => score.player += 1,
GameResult::ComputerWins(_, _) => score.computer += 1,
GameResult::Draw(_) => (),
}
}
fn announce_winner(score: &Score) {
println!(
"\nFinal Score - You: {}, Computer: {}",
score.player, score.computer
);
let result = if score.player > score.computer {
"You win the series!"
} else if score.player < score.computer {
"Computer wins the series!"
} else {
"The series is a draw!"
};
println!("{}", result);
}
fn maybe_play_again() {
print!("\nPlay again? (y/n): ");
io::stdout().flush().unwrap();
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(_) => {
if input.trim().to_lowercase() == "y" {
play();
} else {
println!("Thanks for playing!");
}
}
Err(_) => println!("Error reading input. Game ended."),
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment