i don't care anymore
This commit is contained in:
parent
d34a72cf3b
commit
e517bed681
1469
Cargo.lock
generated
1469
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -5,3 +5,5 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
rocket = { version = "0.5.0", features = ["json"] }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use crate::{decks::new_blackjack_shoe, hand::Hand};
|
use crate::cards::{card::Card, decks::new_blackjack_shoe, hand::Hand};
|
||||||
|
|
||||||
|
use super::{gamestate::GameState, play_moves::PlayMoves, player::Player, playing_hand::{HandState, PlayingHand}};
|
||||||
|
|
||||||
pub struct BlackjackGame {
|
pub struct BlackjackGame {
|
||||||
shoe: Hand,
|
shoe: Hand,
|
||||||
@ -7,73 +9,6 @@ pub struct BlackjackGame {
|
|||||||
state: GameState,
|
state: GameState,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Player {
|
|
||||||
hands: Vec<PlayingHand>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Player {
|
|
||||||
fn new() -> Self {
|
|
||||||
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: HandState::Playing,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_hand(&self) -> &Hand {
|
|
||||||
&self.hand
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_state(&self) -> HandState {
|
|
||||||
self.state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
pub enum HandState {
|
|
||||||
Playing,
|
|
||||||
Standing,
|
|
||||||
DoubleDown,
|
|
||||||
Busted,
|
|
||||||
Blackjack,
|
|
||||||
Maxed, // Reached 21
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub enum PlayMoves {
|
|
||||||
Hit,
|
|
||||||
Stand,
|
|
||||||
DoubleDown,
|
|
||||||
Split,
|
|
||||||
Deal(usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum GameState {
|
|
||||||
Starting,
|
|
||||||
Over, // Game is over
|
|
||||||
PlayerTurn(usize, usize), // Its the turn of the player
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BlackjackGame {
|
impl BlackjackGame {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
BlackjackGame {
|
BlackjackGame {
|
||||||
@ -88,10 +23,18 @@ impl BlackjackGame {
|
|||||||
&self.dealer_hand
|
&self.dealer_hand
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_dealer_upcard(&self) -> Option<&Card> {
|
||||||
|
self.dealer_hand.get_card(0)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_state(&self) -> &GameState {
|
pub fn get_state(&self) -> &GameState {
|
||||||
&self.state
|
&self.state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_players(&self) -> &Vec<Player>{
|
||||||
|
&self.players
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_player(&self, index: usize) -> Option<&Player> {
|
pub fn get_player(&self, index: usize) -> Option<&Player> {
|
||||||
self.players.get(index)
|
self.players.get(index)
|
||||||
}
|
}
|
||||||
@ -102,7 +45,13 @@ impl BlackjackGame {
|
|||||||
|
|
||||||
pub fn play(&mut self, action: PlayMoves) -> bool {
|
pub fn play(&mut self, action: PlayMoves) -> bool {
|
||||||
match (&self.state, action) {
|
match (&self.state, action) {
|
||||||
(GameState::PlayerTurn(player_index, hand_index), PlayMoves::Hit) => {
|
(
|
||||||
|
GameState::PlayerTurn {
|
||||||
|
player_index,
|
||||||
|
hand_index,
|
||||||
|
},
|
||||||
|
PlayMoves::Hit,
|
||||||
|
) => {
|
||||||
let Some(player) = self.players.get_mut(*player_index) else {
|
let Some(player) = self.players.get_mut(*player_index) else {
|
||||||
// Player does not exists
|
// Player does not exists
|
||||||
return false;
|
return false;
|
||||||
@ -131,7 +80,13 @@ impl BlackjackGame {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
(GameState::PlayerTurn(player_index, hand_index), PlayMoves::Split) => {
|
(
|
||||||
|
GameState::PlayerTurn {
|
||||||
|
player_index,
|
||||||
|
hand_index,
|
||||||
|
},
|
||||||
|
PlayMoves::Split,
|
||||||
|
) => {
|
||||||
let Some(player) = self.players.get_mut(*player_index) else {
|
let Some(player) = self.players.get_mut(*player_index) else {
|
||||||
// Player does not exists
|
// Player does not exists
|
||||||
return false;
|
return false;
|
||||||
@ -169,7 +124,13 @@ impl BlackjackGame {
|
|||||||
|
|
||||||
player.hands.push(new_hand);
|
player.hands.push(new_hand);
|
||||||
}
|
}
|
||||||
(GameState::PlayerTurn(player_index, hand_index), PlayMoves::DoubleDown) => {
|
(
|
||||||
|
GameState::PlayerTurn {
|
||||||
|
player_index,
|
||||||
|
hand_index,
|
||||||
|
},
|
||||||
|
PlayMoves::DoubleDown,
|
||||||
|
) => {
|
||||||
let Some(player) = self.players.get_mut(*player_index) else {
|
let Some(player) = self.players.get_mut(*player_index) else {
|
||||||
// Player does not exists
|
// Player does not exists
|
||||||
return false;
|
return false;
|
||||||
@ -203,7 +164,13 @@ impl BlackjackGame {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
(GameState::PlayerTurn(player_index, hand_index), PlayMoves::Stand) => {
|
(
|
||||||
|
GameState::PlayerTurn {
|
||||||
|
player_index,
|
||||||
|
hand_index,
|
||||||
|
},
|
||||||
|
PlayMoves::Stand,
|
||||||
|
) => {
|
||||||
let Some(player) = self.players.get_mut(*player_index) else {
|
let Some(player) = self.players.get_mut(*player_index) else {
|
||||||
// Player does not exists
|
// Player does not exists
|
||||||
return false;
|
return false;
|
||||||
@ -221,10 +188,10 @@ impl BlackjackGame {
|
|||||||
|
|
||||||
hand.state = HandState::Standing;
|
hand.state = HandState::Standing;
|
||||||
}
|
}
|
||||||
(GameState::Over, PlayMoves::Deal(player_count))
|
(GameState::Over, PlayMoves::Deal { players })
|
||||||
| (GameState::Starting, PlayMoves::Deal(player_count)) => {
|
| (GameState::Starting, PlayMoves::Deal { players }) => {
|
||||||
// Create players
|
// Create players
|
||||||
for _ in 0..player_count {
|
for _ in 0..players {
|
||||||
self.players.push(Player::new());
|
self.players.push(Player::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,16 +224,22 @@ impl BlackjackGame {
|
|||||||
// Add 2nd card to the dealer
|
// Add 2nd card to the dealer
|
||||||
self.dealer_hand.add_card(self.shoe.pop_card().unwrap());
|
self.dealer_hand.add_card(self.shoe.pop_card().unwrap());
|
||||||
|
|
||||||
self.state = GameState::PlayerTurn(0, 0);
|
self.state = GameState::PlayerTurn {
|
||||||
|
player_index: 0,
|
||||||
|
hand_index: 0,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
(_, PlayMoves::Deal(_)) | (GameState::Over, _) | (GameState::Starting, _) => {
|
(_, PlayMoves::Deal { .. }) | (GameState::Over, _) | (GameState::Starting, _) => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find next player or dealer turn
|
// Find next player or dealer turn
|
||||||
if let Some(next_turn) = self.next_player_and_hand() {
|
if let Some(next_turn) = self.next_player_and_hand() {
|
||||||
self.state = GameState::PlayerTurn(next_turn.0, next_turn.1);
|
self.state = GameState::PlayerTurn {
|
||||||
|
player_index: next_turn.0,
|
||||||
|
hand_index: next_turn.1,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
self.dealer_turn();
|
self.dealer_turn();
|
||||||
}
|
}
|
||||||
@ -294,7 +267,11 @@ impl BlackjackGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_player_and_hand(&self) -> Option<(usize, usize)> {
|
fn next_player_and_hand(&self) -> Option<(usize, usize)> {
|
||||||
if let GameState::PlayerTurn(player_index, hand_index) = self.state {
|
if let GameState::PlayerTurn {
|
||||||
|
player_index,
|
||||||
|
hand_index,
|
||||||
|
} = self.state
|
||||||
|
{
|
||||||
let Some(player) = self.players.get(player_index) else {
|
let Some(player) = self.players.get(player_index) else {
|
||||||
// Player does not exists
|
// Player does not exists
|
||||||
return None;
|
return None;
|
12
src/blackjack/gamestate.rs
Normal file
12
src/blackjack/gamestate.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum GameState {
|
||||||
|
Starting,
|
||||||
|
Over,
|
||||||
|
PlayerTurn {
|
||||||
|
player_index: usize,
|
||||||
|
hand_index: usize,
|
||||||
|
},
|
||||||
|
}
|
5
src/blackjack/mod.rs
Normal file
5
src/blackjack/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pub mod blackjack_game;
|
||||||
|
pub mod gamestate;
|
||||||
|
pub mod play_moves;
|
||||||
|
pub mod player;
|
||||||
|
pub mod playing_hand;
|
11
src/blackjack/play_moves.rs
Normal file
11
src/blackjack/play_moves.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum PlayMoves {
|
||||||
|
Hit,
|
||||||
|
Stand,
|
||||||
|
DoubleDown,
|
||||||
|
Split,
|
||||||
|
Deal { players: usize },
|
||||||
|
}
|
24
src/blackjack/player.rs
Normal file
24
src/blackjack/player.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use super::playing_hand::{HandState, PlayingHand};
|
||||||
|
|
||||||
|
#[derive(Serialize, Clone)]
|
||||||
|
pub struct Player {
|
||||||
|
pub(super) hands: Vec<PlayingHand>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Player {
|
||||||
|
pub(super) fn new() -> Self {
|
||||||
|
Player { hands: Vec::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_hands(&self) -> &Vec<PlayingHand> {
|
||||||
|
&self.hands
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn next_playing_hand(&self) -> Option<usize> {
|
||||||
|
self.hands
|
||||||
|
.iter()
|
||||||
|
.position(|e| *e.get_state() == HandState::Playing)
|
||||||
|
}
|
||||||
|
}
|
36
src/blackjack/playing_hand.rs
Normal file
36
src/blackjack/playing_hand.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::cards::hand::Hand;
|
||||||
|
|
||||||
|
#[derive(Serialize, Clone)]
|
||||||
|
pub struct PlayingHand {
|
||||||
|
pub(super) hand: Hand,
|
||||||
|
pub(super) state: HandState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlayingHand {
|
||||||
|
pub(super) fn new() -> Self {
|
||||||
|
PlayingHand {
|
||||||
|
hand: Hand::new(),
|
||||||
|
state: HandState::Playing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_hand(&self) -> &Hand {
|
||||||
|
&self.hand
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_state(&self) -> &HandState {
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
|
||||||
|
pub enum HandState {
|
||||||
|
Playing,
|
||||||
|
Standing,
|
||||||
|
DoubleDown,
|
||||||
|
Busted,
|
||||||
|
Blackjack,
|
||||||
|
Maxed, // Reached 21
|
||||||
|
}
|
@ -1,7 +1,10 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::{card_index::CardIndex, card_suit::CardSuit};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::{card_index::CardIndex, card_suit::CardSuit};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||||
pub struct Card {
|
pub struct Card {
|
||||||
pub suit: CardSuit,
|
pub suit: CardSuit,
|
||||||
pub index: CardIndex,
|
pub index: CardIndex,
|
@ -1,6 +1,8 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
#[derive(PartialEq, PartialOrd, Eq, Ord, Clone, Copy)]
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Serialize, Deserialize)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum CardIndex {
|
pub enum CardIndex {
|
||||||
A = 14,
|
A = 14,
|
@ -1,6 +1,8 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||||
pub enum CardSuit {
|
pub enum CardSuit {
|
||||||
Spades,
|
Spades,
|
||||||
Clubs,
|
Clubs,
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{card::Card, hand::Hand, CardIndex as CI, CardSuit as CS};
|
use super::{card::Card, hand::Hand, card_index::CardIndex as CI, card_suit::CardSuit as CS};
|
||||||
|
|
||||||
pub fn new_full_deck() -> Hand {
|
pub fn new_full_deck() -> Hand {
|
||||||
let mut hand = Hand::new();
|
let mut hand = Hand::new();
|
@ -1,8 +1,10 @@
|
|||||||
use rand::{seq::SliceRandom, thread_rng};
|
use rand::{seq::SliceRandom, thread_rng};
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::{card::Card, card_index::CardIndex};
|
use super::{card::Card, card_index::CardIndex};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Hand {
|
pub struct Hand {
|
||||||
cards: Vec<Card>,
|
cards: Vec<Card>,
|
||||||
}
|
}
|
||||||
@ -106,19 +108,40 @@ impl Display for Hand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for Hand {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
self.cards.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Hand {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
// Deserialize into a Vec directly and wrap it in MyVecWrapper
|
||||||
|
let cards = Vec::<Card>::deserialize(deserializer)?;
|
||||||
|
Ok(Hand { cards })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::super::card_suit::CardSuit;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn is_blackjack_ace_first() {
|
fn is_blackjack_ace_first() {
|
||||||
let mut hand = Hand::new();
|
let mut hand = Hand::new();
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Hearts,
|
suit: CardSuit::Hearts,
|
||||||
index: CardIndex::A,
|
index: CardIndex::A,
|
||||||
});
|
});
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Diamonds,
|
suit: CardSuit::Diamonds,
|
||||||
index: CardIndex::N10,
|
index: CardIndex::N10,
|
||||||
});
|
});
|
||||||
assert!(hand.is_backjack());
|
assert!(hand.is_backjack());
|
||||||
@ -128,11 +151,11 @@ mod tests {
|
|||||||
fn is_blackjack_ace_last() {
|
fn is_blackjack_ace_last() {
|
||||||
let mut hand = Hand::new();
|
let mut hand = Hand::new();
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Diamonds,
|
suit: CardSuit::Diamonds,
|
||||||
index: CardIndex::J,
|
index: CardIndex::J,
|
||||||
});
|
});
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Hearts,
|
suit: CardSuit::Hearts,
|
||||||
index: CardIndex::A,
|
index: CardIndex::A,
|
||||||
});
|
});
|
||||||
assert!(hand.is_backjack());
|
assert!(hand.is_backjack());
|
||||||
@ -142,15 +165,15 @@ mod tests {
|
|||||||
fn is_not_blackjack_too_many() {
|
fn is_not_blackjack_too_many() {
|
||||||
let mut hand = Hand::new();
|
let mut hand = Hand::new();
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Diamonds,
|
suit: CardSuit::Diamonds,
|
||||||
index: CardIndex::J,
|
index: CardIndex::J,
|
||||||
});
|
});
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Hearts,
|
suit: CardSuit::Hearts,
|
||||||
index: CardIndex::A,
|
index: CardIndex::A,
|
||||||
});
|
});
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Spades,
|
suit: CardSuit::Spades,
|
||||||
index: CardIndex::A,
|
index: CardIndex::A,
|
||||||
});
|
});
|
||||||
assert!(!hand.is_backjack());
|
assert!(!hand.is_backjack());
|
||||||
@ -160,7 +183,7 @@ mod tests {
|
|||||||
fn is_not_blackjack_too_few() {
|
fn is_not_blackjack_too_few() {
|
||||||
let mut hand = Hand::new();
|
let mut hand = Hand::new();
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Hearts,
|
suit: CardSuit::Hearts,
|
||||||
index: CardIndex::A,
|
index: CardIndex::A,
|
||||||
});
|
});
|
||||||
assert!(!hand.is_backjack());
|
assert!(!hand.is_backjack());
|
||||||
@ -170,15 +193,15 @@ mod tests {
|
|||||||
fn is_not_blackjack_value_21() {
|
fn is_not_blackjack_value_21() {
|
||||||
let mut hand = Hand::new();
|
let mut hand = Hand::new();
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Hearts,
|
suit: CardSuit::Hearts,
|
||||||
index: CardIndex::K,
|
index: CardIndex::K,
|
||||||
});
|
});
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Clubs,
|
suit: CardSuit::Clubs,
|
||||||
index: CardIndex::N7,
|
index: CardIndex::N7,
|
||||||
});
|
});
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Hearts,
|
suit: CardSuit::Hearts,
|
||||||
index: CardIndex::N4,
|
index: CardIndex::N4,
|
||||||
});
|
});
|
||||||
assert!(!hand.is_backjack());
|
assert!(!hand.is_backjack());
|
||||||
@ -188,7 +211,7 @@ mod tests {
|
|||||||
fn blackjack_value() {
|
fn blackjack_value() {
|
||||||
let mut hand = Hand::new();
|
let mut hand = Hand::new();
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Hearts,
|
suit: CardSuit::Hearts,
|
||||||
index: CardIndex::K,
|
index: CardIndex::K,
|
||||||
});
|
});
|
||||||
assert_eq!(hand.get_blackjack_value(), 10);
|
assert_eq!(hand.get_blackjack_value(), 10);
|
||||||
@ -198,17 +221,17 @@ mod tests {
|
|||||||
fn merge_hands() {
|
fn merge_hands() {
|
||||||
let mut hand = Hand::new();
|
let mut hand = Hand::new();
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Diamonds,
|
suit: CardSuit::Diamonds,
|
||||||
index: CardIndex::N5,
|
index: CardIndex::N5,
|
||||||
});
|
});
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Spades,
|
suit: CardSuit::Spades,
|
||||||
index: CardIndex::Q,
|
index: CardIndex::Q,
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut other = Hand::new();
|
let mut other = Hand::new();
|
||||||
hand.add_card(Card {
|
hand.add_card(Card {
|
||||||
suit: crate::card_suit::CardSuit::Spades,
|
suit: CardSuit::Spades,
|
||||||
index: CardIndex::K,
|
index: CardIndex::K,
|
||||||
});
|
});
|
||||||
|
|
5
src/cards/mod.rs
Normal file
5
src/cards/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pub mod card;
|
||||||
|
pub mod card_index;
|
||||||
|
pub mod card_suit;
|
||||||
|
pub mod decks;
|
||||||
|
pub mod hand;
|
@ -1,13 +1,13 @@
|
|||||||
use std::io::{self, stdin};
|
use std::io::{self, stdin};
|
||||||
|
|
||||||
use crate::blackjack::{BlackjackGame, GameState, PlayMoves};
|
use crate::blackjack::{blackjack_game::BlackjackGame, gamestate::GameState, play_moves::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();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match game.get_state() {
|
match game.get_state() {
|
||||||
GameState::PlayerTurn(player_index, _) => {
|
GameState::PlayerTurn{player_index, ..} => {
|
||||||
print_full_state(&game);
|
print_full_state(&game);
|
||||||
let play_move = get_move(*player_index)?;
|
let play_move = get_move(*player_index)?;
|
||||||
if !game.play(play_move) {
|
if !game.play(play_move) {
|
||||||
@ -20,7 +20,7 @@ pub fn play() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
GameState::Starting => {
|
GameState::Starting => {
|
||||||
game.play(PlayMoves::Deal(2));
|
game.play(PlayMoves::Deal{players: 2});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
src/main.rs
20
src/main.rs
@ -1,19 +1,13 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
#[macro_use] extern crate rocket;
|
||||||
use std::error::Error;
|
use webserver::build;
|
||||||
|
|
||||||
use console_blackjack::play;
|
|
||||||
|
|
||||||
use crate::{card_index::CardIndex, card_suit::CardSuit};
|
|
||||||
|
|
||||||
mod blackjack;
|
mod blackjack;
|
||||||
mod card;
|
mod cards;
|
||||||
mod card_index;
|
|
||||||
mod card_suit;
|
|
||||||
mod console_blackjack;
|
mod console_blackjack;
|
||||||
mod decks;
|
mod webserver;
|
||||||
mod hand;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
#[launch]
|
||||||
play()
|
fn launch() -> _ {
|
||||||
|
build()
|
||||||
}
|
}
|
||||||
|
64
src/webserver.rs
Normal file
64
src/webserver.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use rocket::{
|
||||||
|
http::Status,
|
||||||
|
serde::{json::Json, Serialize},
|
||||||
|
Build, Rocket, State,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{blackjack::{blackjack_game::BlackjackGame, gamestate::GameState, play_moves::PlayMoves, player::Player}, cards::card::Card};
|
||||||
|
|
||||||
|
#[get("/state")]
|
||||||
|
fn get_state(state: &State<MyState>) -> Json<GamestateJson> {
|
||||||
|
Json(gamestate_as_json(&state.game.lock().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/state", data = "<request>", format = "application/json")]
|
||||||
|
fn post_move(
|
||||||
|
state: &State<MyState>,
|
||||||
|
request: Json<PlayMoves>,
|
||||||
|
) -> Result<Json<GamestateJson>, Status> {
|
||||||
|
let action = request.0;
|
||||||
|
|
||||||
|
if state.game.lock().unwrap().play(action) {
|
||||||
|
Ok(Json(gamestate_as_json(&state.game.lock().unwrap())))
|
||||||
|
} else {
|
||||||
|
Err(Status::BadRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyState {
|
||||||
|
game: Mutex<BlackjackGame>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct GamestateJson {
|
||||||
|
state: GameState,
|
||||||
|
dealer_upcard: Option<Card>,
|
||||||
|
players: Vec<Player>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gamestate_as_json(game: &BlackjackGame) -> GamestateJson {
|
||||||
|
match game.get_state() {
|
||||||
|
GameState::Starting => GamestateJson {
|
||||||
|
state: *game.get_state(),
|
||||||
|
dealer_upcard: None,
|
||||||
|
players: Vec::new(),
|
||||||
|
},
|
||||||
|
GameState::Over | GameState::PlayerTurn { .. } => GamestateJson {
|
||||||
|
state: *game.get_state(),
|
||||||
|
dealer_upcard: game.get_dealer_upcard().copied(),
|
||||||
|
players: game.get_players().clone(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build() -> Rocket<Build> {
|
||||||
|
let state = MyState {
|
||||||
|
game: Mutex::new(BlackjackGame::new()),
|
||||||
|
};
|
||||||
|
|
||||||
|
rocket::build()
|
||||||
|
.manage(state)
|
||||||
|
.mount("/", routes![get_state, post_move])
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user