diff --git a/src/blackjack.rs b/src/blackjack.rs index f96a00f..3156629 100644 --- a/src/blackjack.rs +++ b/src/blackjack.rs @@ -4,25 +4,33 @@ pub struct BlackjackGame { shoe: Hand, player_hand: Hand, dealer_hand: Hand, + state: GameState, } -pub enum DealResult { - DealerBlackJack, // Dealer has a blackjack. Player does not. +pub enum PlayResult { + DealerBlackJack, // Dealer has a blackjack. Player does not + PlayerBlackJack, // Player has a blackjack. Dealer does not + PushBlackjack, // Player and dealer have a blockjack Push, // Dealer has a Blackjack and so does the Player - PlayerBlackJack, // Player has a blackjack. Dealer does not. - Continue, // Game continues -} - -pub enum HitResult { - Bust, - Continue, -} - -pub enum DealerPlayResult { - Bust, - Push, // Player and dealer have the same value + Bust, // Player bust + DealerBust, // Dealer bust StandPlayerLose, // Dealer stands and wins StandPlayerWin, // Dealer stands and loses + Continue, // Game goes on as normal + InvalidMove, +} + +#[derive(Clone, Copy,Debug)] +pub enum PlayMoves { + Hit, + Stand, + Bet, // At the Start of the game +} + +pub enum GameState { + Empty, // No cards have been dealt + Over, // Game is over + PlayerTurn, // Its the turn of the player } impl BlackjackGame { @@ -31,6 +39,7 @@ impl BlackjackGame { shoe: new_blackjack_shoe(6), player_hand: Hand::new(), dealer_hand: Hand::new(), + state: GameState::Empty, } } @@ -42,43 +51,66 @@ impl BlackjackGame { &self.player_hand } - pub fn deal(&mut self) -> DealResult { - self.player_hand.add_card(self.shoe.pop_card().unwrap()); - self.dealer_hand.add_card(self.shoe.pop_card().unwrap()); + pub fn get_state(&self) -> &GameState { + &self.state + } - self.player_hand.add_card(self.shoe.pop_card().unwrap()); - self.dealer_hand.add_card(self.shoe.pop_card().unwrap()); + pub fn play(&mut self, action: PlayMoves) -> PlayResult { + match (&self.state, action) { + (GameState::Empty, PlayMoves::Bet) => { + self.player_hand.add_card(self.shoe.pop_card().unwrap()); + self.dealer_hand.add_card(self.shoe.pop_card().unwrap()); - if self.dealer_hand.is_backjack() { - if self.player_hand.is_backjack() { - return DealResult::Push; + self.player_hand.add_card(self.shoe.pop_card().unwrap()); + self.dealer_hand.add_card(self.shoe.pop_card().unwrap()); + + match (self.dealer_hand.is_backjack(),self.player_hand.is_backjack()) { + (true,true) => { + self.state = GameState::Over; + PlayResult::PushBlackjack + }, + (true,false) => { + self.state = GameState::Over; + PlayResult::DealerBlackJack + }, + (false,true) => { + self.state = GameState::Over; + PlayResult::PlayerBlackJack + }, + (false,false) => { + self.state = GameState::PlayerTurn; + PlayResult::Continue + }, + } } + (GameState::PlayerTurn, PlayMoves::Hit) => { + self.player_hand.add_card(self.shoe.pop_card().unwrap()); - return DealResult::DealerBlackJack; + return match self.player_hand.get_blackjack_value().cmp(&21) { + std::cmp::Ordering::Equal => { + self.state = GameState::Over; + self.dealer_play() + } + std::cmp::Ordering::Greater => { + self.state = GameState::Over; + PlayResult::Bust + } + std::cmp::Ordering::Less => PlayResult::Continue, + }; + } + (GameState::PlayerTurn, PlayMoves::Stand) => { + self.state = GameState::Over; + return self.dealer_play(); + } + (GameState::Over, _) + | (GameState::Empty, _) + | (GameState::PlayerTurn, PlayMoves::Bet) => { + return PlayResult::InvalidMove; + } } - - if self.player_hand.is_backjack() { - return DealResult::PlayerBlackJack; - } - - DealResult::Continue } - pub fn hit(&mut self) -> HitResult { - self.player_hand.add_card(self.shoe.pop_card().unwrap()); - - if self.player_hand.get_blackjack_value() > 21 { - return HitResult::Bust; - } - - HitResult::Continue - } - - pub fn stand(&mut self) { - // ??? - } - - pub fn dealer_play(&mut self) -> DealerPlayResult { + fn dealer_play(&mut self) -> PlayResult { // Stand on 17 or above // Hit on 16 and below @@ -88,16 +120,16 @@ impl BlackjackGame { let player_value = self.player_hand.get_blackjack_value(); return match dealer_value.cmp(&player_value) { - std::cmp::Ordering::Equal => DealerPlayResult::Push, - std::cmp::Ordering::Greater => DealerPlayResult::StandPlayerLose, - std::cmp::Ordering::Less => DealerPlayResult::StandPlayerWin, + std::cmp::Ordering::Equal => PlayResult::Push, + std::cmp::Ordering::Greater => PlayResult::StandPlayerLose, + std::cmp::Ordering::Less => PlayResult::StandPlayerWin, }; } self.dealer_hand.add_card(self.shoe.pop_card().unwrap()); if self.dealer_hand.get_blackjack_value() > 21 { - return DealerPlayResult::Bust; + return PlayResult::DealerBust; } } } diff --git a/src/console_blackjack.rs b/src/console_blackjack.rs index fd15443..bb8c3aa 100644 --- a/src/console_blackjack.rs +++ b/src/console_blackjack.rs @@ -1,100 +1,93 @@ -use std::io::stdin; +use std::io::{self, stdin}; -use crate::blackjack::BlackjackGame; +use crate::blackjack::{BlackjackGame, GameState, PlayMoves}; pub fn play() -> Result<(), Box> { let mut game = BlackjackGame::new(); + let mut play_move = PlayMoves::Bet; - let deal = game.deal(); - - println!( - "Dealer hand: {} ?", - game.get_dealer_hand().get_card(0).unwrap() - ); - println!( - "Player hand: {} ({})", - game.get_player_hand(), - game.get_player_hand().get_blackjack_value() - ); - - match deal { - crate::blackjack::DealResult::DealerBlackJack => { - println!("Dealer has a blackjack!"); - return Ok(()); - } - crate::blackjack::DealResult::PlayerBlackJack => { - println!("Player has a blackjack!"); - return Ok(()); - } - crate::blackjack::DealResult::Push => { - println!("Both Player and dealer have a blackjack!"); - return Ok(()); - } - crate::blackjack::DealResult::Continue => {} - } - - loop { - println!("(H)it (S)tand"); - - let mut buffer = String::new(); - stdin().read_line(&mut buffer)?; - - let hit = buffer.trim() == "h"; - - if hit { - let hit_result = game.hit(); - - println!( - "Dealer hand: {} ?", - game.get_dealer_hand().get_card(0).unwrap() - ); - println!( - "Player hand: {} ({})", - game.get_player_hand(), - game.get_player_hand().get_blackjack_value() - ); - - match hit_result { - crate::blackjack::HitResult::Bust => { - println!("Player busts"); - return Ok(()); - } - crate::blackjack::HitResult::Continue => {} + while !matches!(game.get_state(), GameState::Over) { + match game.play(play_move) { + crate::blackjack::PlayResult::DealerBlackJack => { + print_full_state(&game); + println!("Dealer wins with blackjack!"); } - } else { - game.stand(); - - let dealer_play = game.dealer_play(); - - println!( - "Dealer hand: {} ({})", - game.get_dealer_hand(), - game.get_dealer_hand().get_blackjack_value() - ); - println!( - "Player hand: {} ({})", - game.get_player_hand(), - game.get_player_hand().get_blackjack_value() - ); - - match dealer_play { - crate::blackjack::DealerPlayResult::Bust => { - println!("Dealer bust. Player wins."); - } - crate::blackjack::DealerPlayResult::Push => { - println!("Player and dealer have same value. Push."); - } - crate::blackjack::DealerPlayResult::StandPlayerLose => { - println!("Dealer wins"); - } - crate::blackjack::DealerPlayResult::StandPlayerWin => { - println!("Player wins"); - } + crate::blackjack::PlayResult::PlayerBlackJack => println!("Player has a blackjack!"), + crate::blackjack::PlayResult::PushBlackjack => { + print_full_state(&game); + println!("Player and Dealer have a blackjack!"); + } + crate::blackjack::PlayResult::DealerBust => { + println!("Dealer busts. Player wins!"); + } + crate::blackjack::PlayResult::StandPlayerLose => { + print_full_state(&game); + println!( + "Dealer wins with {}", + game.get_dealer_hand().get_blackjack_value() + ); + } + crate::blackjack::PlayResult::StandPlayerWin => { + print_full_state(&game); + println!( + "Player wins with {}", + game.get_player_hand().get_blackjack_value() + ); + } + crate::blackjack::PlayResult::Push => { + print_full_state(&game); + println!("Player and dealer have the same value"); + } + crate::blackjack::PlayResult::Bust => { + print_full_state(&game); + println!( + "Player busts with {}", + game.get_player_hand().get_blackjack_value() + ); + } + crate::blackjack::PlayResult::InvalidMove => { + println!("You cannot do that!"); + play_move = get_move()?; + } + crate::blackjack::PlayResult::Continue => { + println!("Dealer: {} ?", game.get_dealer_hand().get_card(0).unwrap()); + println!( + "Player: {} ({})", + game.get_player_hand(), + game.get_player_hand().get_blackjack_value() + ); + play_move = get_move()? } - - break; } } Ok(()) } + +fn get_move() -> Result { + loop { + println!("(H)it (S)tand"); + let mut buffer = String::new(); + + stdin().read_line(&mut buffer)?; + + match buffer.trim() { + "h" | "H" => return Ok(PlayMoves::Hit), + "s" | "S" => return Ok(PlayMoves::Stand), + _ => {} + } + } +} + +fn print_full_state(game: &BlackjackGame) { + println!( + "Dealer: {} ({})", + game.get_dealer_hand(), + game.get_dealer_hand().get_blackjack_value() + ); + println!( + "Player: {} ({})", + game.get_player_hand(), + game.get_player_hand().get_blackjack_value() + ); +}