improved game & console
This commit is contained in:
		
							parent
							
								
									1982d27c4f
								
							
						
					
					
						commit
						782b52ca6c
					
				
							
								
								
									
										128
									
								
								src/blackjack.rs
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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<dyn std::error::Error>> {
 | 
			
		||||
    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<PlayMoves, io::Error> {
 | 
			
		||||
    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()
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user