that's all folks

This commit is contained in:
Niklas Kapelle 2024-05-21 14:04:44 +02:00
parent bf73860433
commit 338b5d442a
Signed by: niklas
GPG Key ID: 4EB651B36D841D16
2 changed files with 169 additions and 67 deletions

View File

@ -8,15 +8,35 @@ pub struct BlackjackGame {
}
pub struct Player {
hand: Hand,
state: PlayerState,
hands: Vec<PlayingHand>,
}
impl Player {
fn new() -> Self {
Player {
Player { hands: Vec::new() }
}
pub fn get_hands(&self) -> &Vec<PlayingHand> {
&self.hands
}
fn next_playing_hand(&self) -> Option<usize> {
self.hands
.iter()
.position(|e| e.state == HandState::Playing)
}
}
pub struct PlayingHand {
hand: Hand,
state: HandState,
}
impl PlayingHand {
fn new() -> Self {
PlayingHand {
hand: Hand::new(),
state: PlayerState::Playing,
state: HandState::Playing,
}
}
@ -24,13 +44,13 @@ impl Player {
&self.hand
}
pub fn get_state(&self) -> &PlayerState {
&self.state
pub fn get_state(&self) -> HandState {
self.state
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PlayerState {
pub enum HandState {
Playing,
Standing,
DoubleDown,
@ -50,7 +70,7 @@ pub enum PlayMoves {
pub enum GameState {
Starting,
Over, // Game is over
PlayerTurn(usize), // Its the turn of the player
PlayerTurn(usize, usize), // Its the turn of the player
}
impl BlackjackGame {
@ -81,97 +101,148 @@ impl BlackjackGame {
pub fn play(&mut self, action: PlayMoves) -> bool {
match (&self.state, action) {
(GameState::PlayerTurn(i), PlayMoves::Hit) => {
let Some(player) = self.players.get_mut(*i) else {
(GameState::PlayerTurn(player_index, hand_index), PlayMoves::Hit) => {
let Some(player) = self.players.get_mut(*player_index) else {
// Player does not exists
return false;
};
if player.state != PlayerState::Playing {
let Some(hand) = player.hands.get_mut(*hand_index) else {
// Hand does not exist
return false;
};
if hand.state != HandState::Playing {
return false;
}
player.hand.add_card(self.shoe.pop_card().unwrap());
match player.hand.get_blackjack_value().cmp(&21) {
hand.hand.add_card(self.shoe.pop_card().unwrap());
match hand.hand.get_blackjack_value().cmp(&21) {
std::cmp::Ordering::Equal => {
player.state = PlayerState::Maxed;
hand.state = HandState::Maxed;
}
std::cmp::Ordering::Greater => {
player.state = PlayerState::Busted;
hand.state = HandState::Busted;
}
std::cmp::Ordering::Less => {
// Player is still playing
}
};
}
(GameState::PlayerTurn(i), PlayMoves::DoubleDown) => {
let Some(player) = self.players.get_mut(*i) else {
(GameState::PlayerTurn(player_index, hand_index), PlayMoves::DoubleDown) => {
let Some(player) = self.players.get_mut(*player_index) else {
// Player does not exists
return false;
};
if player.state != PlayerState::Playing {
let Some(hand) = player.hands.get_mut(*hand_index) else {
// Hand does not exist
return false;
};
if hand.state != HandState::Playing {
return false;
}
player.hand.add_card(self.shoe.pop_card().unwrap());
match player.hand.get_blackjack_value().cmp(&21) {
std::cmp::Ordering::Equal | std::cmp::Ordering::Less => {
player.state = PlayerState::Maxed;
if hand.hand.count() != 2 {
// Can oly double down as your first move
return false;
}
hand.hand.add_card(self.shoe.pop_card().unwrap());
match hand.hand.get_blackjack_value().cmp(&21) {
std::cmp::Ordering::Equal => {
hand.state = HandState::Maxed;
}
std::cmp::Ordering::Less => {
hand.state = HandState::Standing;
}
std::cmp::Ordering::Greater => {
player.state = PlayerState::Busted;
hand.state = HandState::Busted;
}
};
}
(GameState::PlayerTurn(i), PlayMoves::Stand) => {
let Some(player) = self.players.get_mut(*i) else {
(GameState::PlayerTurn(player_index, hand_index), PlayMoves::Stand) => {
let Some(player) = self.players.get_mut(*player_index) else {
// Player does not exists
return false;
};
if player.state != PlayerState::Playing {
let Some(hand) = player.hands.get_mut(*hand_index) else {
// Hand does not exist
return false;
};
if hand.state != HandState::Playing {
// Can only stand on playing hands
return false;
}
player.state = PlayerState::Standing;
hand.state = HandState::Standing;
}
(GameState::Over, PlayMoves::Deal(player_count))
| (GameState::Starting, PlayMoves::Deal(player_count)) => {
for i in 0..player_count {
// Create players
for _ in 0..player_count{
self.players.push(Player::new());
self.players[i].hand.add_card(self.shoe.pop_card().unwrap());
}
// Create one hand for the players
for player in self.players.iter_mut(){
player.hands.push(PlayingHand::new());
}
// Add one card to each hand the players have
for player in self.players.iter_mut(){
for hand in player.hands.iter_mut(){
hand.hand.add_card(self.shoe.pop_card().unwrap());
}
}
// Add one card to the dealer
self.dealer_hand.add_card(self.shoe.pop_card().unwrap());
for i in 0..player_count {
self.players[i].hand.add_card(self.shoe.pop_card().unwrap());
// Add the 2nd card to the players hand
for player in self.players.iter_mut(){
for hand in player.hands.iter_mut(){
hand.hand.add_card(self.shoe.pop_card().unwrap());
if self.players[i].hand.is_backjack() {
self.players[i].state = PlayerState::Blackjack;
if hand.hand.is_backjack() {
hand.state = HandState::Blackjack;
}
}
}
// Add 2nd card to the dealer
self.dealer_hand.add_card(self.shoe.pop_card().unwrap());
self.state = GameState::PlayerTurn(0);
self.state = GameState::PlayerTurn(0, 0);
}
(_, PlayMoves::Deal(_)) | (GameState::Over, _) | (GameState::Starting, _) => {
return false;
}
}
let player_count = self.players.len();
// Find next player or dealer turn
if let Some(next_turn) = self.next_player_and_hand() {
self.state = GameState::PlayerTurn(next_turn.0, next_turn.1);
} else {
self.dealer_turn();
}
match self.state {
GameState::PlayerTurn(i) => {
if self.players[i].state == PlayerState::Playing {
self.state = GameState::PlayerTurn(i);
} else if i + 1 >= player_count {
return true;
}
fn dealer_turn(&mut self) {
loop {
let dealer_value = self.dealer_hand.get_blackjack_value();
if dealer_value >= 17 {
// Check winners
// Dealer stands
self.state = GameState::Over;
return true;
return;
}
self.dealer_hand.add_card(self.shoe.pop_card().unwrap());
@ -179,17 +250,45 @@ impl BlackjackGame {
if self.dealer_hand.get_blackjack_value() > 21 {
// Dealer busts
self.state = GameState::Over;
return true;
return;
}
}
} else {
self.state = GameState::PlayerTurn(i + 1);
}
return true;
fn next_player_and_hand(&self) -> Option<(usize, usize)> {
if let GameState::PlayerTurn(player_index, hand_index) = self.state {
let Some(player) = self.players.get(player_index) else {
// Player does not exists
return None;
};
let Some(hand) = player.hands.get(hand_index) else {
// Hand does not exist
return None;
};
if hand.state == HandState::Playing {
// Hand is still playing
return Some((player_index, hand_index));
}
_ => {
return false;
// Get next valid hand for player
if let Some(next_hand) = player.next_playing_hand() {
return Some((player_index, next_hand));
}
// Get next valid player
if let Some(next_hand) = self.players.iter().enumerate().find_map(|p| {
if let Some(h) = p.1.next_playing_hand(){
Some((p.0,h))
}else{
None
}
}) {
return Some((next_hand.0, next_hand.1));
}
}
None
}
}

View File

@ -7,7 +7,7 @@ pub fn play() -> Result<(), Box<dyn std::error::Error>> {
loop {
match game.get_state() {
GameState::PlayerTurn(player_index) => {
GameState::PlayerTurn(player_index,_) => {
print_full_state(&game);
let play_move = get_move(*player_index)?;
if !game.play(play_move){
@ -28,7 +28,7 @@ pub fn play() -> Result<(), Box<dyn std::error::Error>> {
fn get_move(player_index: usize) -> Result<PlayMoves, io::Error> {
loop {
println!("P{}, (H)it (S)tand (D)double",player_index);
println!("Turn {}: (H)it (S)tand (D)double",player_index);
let mut buffer = String::new();
stdin().read_line(&mut buffer)?;
@ -47,6 +47,9 @@ fn print_full_state(game: &BlackjackGame) {
for player_index in 0..game.get_player_count(){
let player = game.get_player(player_index).unwrap();
println!("P{}: {} ({})",player_index,player.get_hand(),player.get_hand().get_blackjack_value());
println!("Player {}:",player_index);
for hand in player.get_hands().iter().enumerate(){
println!("{}: {} ({}) - {:?}",hand.0,hand.1.get_hand(),hand.1.get_hand().get_blackjack_value(),hand.1.get_state());
}
}
}