improved game & console

This commit is contained in:
Niklas Kapelle 2024-05-13 17:22:07 +02:00
parent 1982d27c4f
commit 782b52ca6c
Signed by: niklas
GPG Key ID: 4EB651B36D841D16
2 changed files with 161 additions and 136 deletions

View File

@ -4,25 +4,33 @@ pub struct BlackjackGame {
shoe: Hand, shoe: Hand,
player_hand: Hand, player_hand: Hand,
dealer_hand: Hand, dealer_hand: Hand,
state: GameState,
} }
pub enum DealResult { pub enum PlayResult {
DealerBlackJack, // Dealer has a blackjack. Player does not. 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 Push, // Dealer has a Blackjack and so does the Player
PlayerBlackJack, // Player has a blackjack. Dealer does not. Bust, // Player bust
Continue, // Game continues DealerBust, // Dealer bust
}
pub enum HitResult {
Bust,
Continue,
}
pub enum DealerPlayResult {
Bust,
Push, // Player and dealer have the same value
StandPlayerLose, // Dealer stands and wins StandPlayerLose, // Dealer stands and wins
StandPlayerWin, // Dealer stands and loses 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 { impl BlackjackGame {
@ -31,6 +39,7 @@ impl BlackjackGame {
shoe: new_blackjack_shoe(6), shoe: new_blackjack_shoe(6),
player_hand: Hand::new(), player_hand: Hand::new(),
dealer_hand: Hand::new(), dealer_hand: Hand::new(),
state: GameState::Empty,
} }
} }
@ -42,43 +51,66 @@ impl BlackjackGame {
&self.player_hand &self.player_hand
} }
pub fn deal(&mut self) -> DealResult { pub fn get_state(&self) -> &GameState {
self.player_hand.add_card(self.shoe.pop_card().unwrap()); &self.state
self.dealer_hand.add_card(self.shoe.pop_card().unwrap()); }
self.player_hand.add_card(self.shoe.pop_card().unwrap()); pub fn play(&mut self, action: PlayMoves) -> PlayResult {
self.dealer_hand.add_card(self.shoe.pop_card().unwrap()); 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() { self.player_hand.add_card(self.shoe.pop_card().unwrap());
if self.player_hand.is_backjack() { self.dealer_hand.add_card(self.shoe.pop_card().unwrap());
return DealResult::Push;
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 { fn dealer_play(&mut self) -> PlayResult {
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 {
// Stand on 17 or above // Stand on 17 or above
// Hit on 16 and below // Hit on 16 and below
@ -88,16 +120,16 @@ impl BlackjackGame {
let player_value = self.player_hand.get_blackjack_value(); let player_value = self.player_hand.get_blackjack_value();
return match dealer_value.cmp(&player_value) { return match dealer_value.cmp(&player_value) {
std::cmp::Ordering::Equal => DealerPlayResult::Push, std::cmp::Ordering::Equal => PlayResult::Push,
std::cmp::Ordering::Greater => DealerPlayResult::StandPlayerLose, std::cmp::Ordering::Greater => PlayResult::StandPlayerLose,
std::cmp::Ordering::Less => DealerPlayResult::StandPlayerWin, std::cmp::Ordering::Less => PlayResult::StandPlayerWin,
}; };
} }
self.dealer_hand.add_card(self.shoe.pop_card().unwrap()); self.dealer_hand.add_card(self.shoe.pop_card().unwrap());
if self.dealer_hand.get_blackjack_value() > 21 { if self.dealer_hand.get_blackjack_value() > 21 {
return DealerPlayResult::Bust; return PlayResult::DealerBust;
} }
} }
} }

View File

@ -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>> { pub fn play() -> Result<(), Box<dyn std::error::Error>> {
let mut game = BlackjackGame::new(); let mut game = BlackjackGame::new();
let mut play_move = PlayMoves::Bet;
let deal = game.deal(); while !matches!(game.get_state(), GameState::Over) {
match game.play(play_move) {
println!( crate::blackjack::PlayResult::DealerBlackJack => {
"Dealer hand: {} ?", print_full_state(&game);
game.get_dealer_hand().get_card(0).unwrap() println!("Dealer wins with blackjack!");
);
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 => {}
} }
} else { crate::blackjack::PlayResult::PlayerBlackJack => println!("Player has a blackjack!"),
game.stand(); crate::blackjack::PlayResult::PushBlackjack => {
print_full_state(&game);
let dealer_play = game.dealer_play(); println!("Player and Dealer have a blackjack!");
}
println!( crate::blackjack::PlayResult::DealerBust => {
"Dealer hand: {} ({})", println!("Dealer busts. Player wins!");
game.get_dealer_hand(), }
game.get_dealer_hand().get_blackjack_value() crate::blackjack::PlayResult::StandPlayerLose => {
); print_full_state(&game);
println!( println!(
"Player hand: {} ({})", "Dealer wins with {}",
game.get_player_hand(), game.get_dealer_hand().get_blackjack_value()
game.get_player_hand().get_blackjack_value() );
); }
crate::blackjack::PlayResult::StandPlayerWin => {
match dealer_play { print_full_state(&game);
crate::blackjack::DealerPlayResult::Bust => { println!(
println!("Dealer bust. Player wins."); "Player wins with {}",
} game.get_player_hand().get_blackjack_value()
crate::blackjack::DealerPlayResult::Push => { );
println!("Player and dealer have same value. Push."); }
} crate::blackjack::PlayResult::Push => {
crate::blackjack::DealerPlayResult::StandPlayerLose => { print_full_state(&game);
println!("Dealer wins"); println!("Player and dealer have the same value");
} }
crate::blackjack::DealerPlayResult::StandPlayerWin => { crate::blackjack::PlayResult::Bust => {
println!("Player wins"); 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(()) 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()
);
}