Created
January 2, 2025 01:39
-
-
Save BSN4/e6f0cf184d9de92b2a2eebe670a266e9 to your computer and use it in GitHub Desktop.
rock_paper_scissors rust v2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use rand::Rng; | |
use std::io::{self, Write}; | |
#[derive(Debug, Default)] | |
struct Score { | |
player: u32, | |
computer: u32, | |
} | |
#[derive(Debug, PartialEq, Clone, Copy)] | |
enum Move { | |
Rock, | |
Paper, | |
Scissors, | |
} | |
#[derive(Debug)] | |
enum GameResult { | |
PlayerWins(Move, Move), | |
ComputerWins(Move, Move), | |
Draw(Move), | |
} | |
struct Game { | |
score: Score, | |
rounds: u32, | |
} | |
impl Game { | |
fn new(rounds: u32) -> Self { | |
Self { | |
score: Score::default(), | |
rounds, | |
} | |
} | |
fn play(&mut self) { | |
for round in 1..=self.rounds { | |
println!("\nRound {round}"); | |
self.play_round(); | |
} | |
self.announce_winner(); | |
self.maybe_play_again(); | |
} | |
fn play_round(&mut self) { | |
match self.get_player_move() { | |
Ok(player_move) => { | |
let computer_move = Move::random(); | |
println!("Computer chose: {computer_move}"); | |
let result = GameResult::determine(player_move, computer_move); | |
println!("{result}"); | |
self.update_score(&result); | |
} | |
Err(msg) => { | |
println!("{msg}"); | |
self.play_round(); | |
} | |
} | |
} | |
fn get_player_move(&self) -> 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")?; | |
Move::parse(&input) | |
} | |
fn update_score(&mut self, result: &GameResult) { | |
match result { | |
GameResult::PlayerWins(_, _) => self.score.player += 1, | |
GameResult::ComputerWins(_, _) => self.score.computer += 1, | |
GameResult::Draw(_) => (), | |
} | |
} | |
fn announce_winner(&self) { | |
println!( | |
"\nFinal Score - You: {}, Computer: {}", | |
self.score.player, self.score.computer | |
); | |
let result = match self.score.player.cmp(&self.score.computer) { | |
std::cmp::Ordering::Greater => "You win the series!", | |
std::cmp::Ordering::Less => "Computer wins the series!", | |
std::cmp::Ordering::Equal => "The series is a draw!", | |
}; | |
println!("{result}"); | |
} | |
fn maybe_play_again(&mut self) { | |
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" => { | |
self.score = Score::default(); | |
self.play(); | |
} | |
Ok(_) => println!("Thanks for playing!"), | |
Err(_) => println!("Error reading input. Game ended."), | |
} | |
} | |
} | |
impl Move { | |
fn random() -> Self { | |
match rand::thread_rng().gen_range(0..3) { | |
0 => Self::Rock, | |
1 => Self::Paper, | |
_ => Self::Scissors, | |
} | |
} | |
fn parse(input: &str) -> Result<Self, &'static str> { | |
match input.trim().to_lowercase().as_str() { | |
"rock" => Ok(Self::Rock), | |
"paper" => Ok(Self::Paper), | |
"scissors" => Ok(Self::Scissors), | |
_ => Err("Invalid move. Please enter rock, paper, or scissors."), | |
} | |
} | |
} | |
impl std::fmt::Display for Move { | |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
write!( | |
f, | |
"{}", | |
match self { | |
Self::Rock => "rock", | |
Self::Paper => "paper", | |
Self::Scissors => "scissors", | |
} | |
) | |
} | |
} | |
impl GameResult { | |
fn determine(player: Move, computer: Move) -> Self { | |
match (player, computer) { | |
(Move::Rock, Move::Scissors) | | |
(Move::Paper, Move::Rock) | | |
(Move::Scissors, Move::Paper) => Self::PlayerWins(player, computer), | |
(p, c) if p == c => Self::Draw(p), | |
(p, c) => Self::ComputerWins(c, p), | |
} | |
} | |
} | |
impl std::fmt::Display for GameResult { | |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
match self { | |
Self::PlayerWins(threw, beat) => { | |
write!(f, "You won by throwing {threw} against {beat}") | |
} | |
Self::ComputerWins(threw, beat) => { | |
write!(f, "Computer won by throwing {threw} against {beat}") | |
} | |
Self::Draw(move_) => write!(f, "Draw! Both players threw {move_}"), | |
} | |
} | |
} | |
fn main() { | |
Game::new(3).play(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment