Compare commits
6 Commits
main
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| b2e2d547ef | |||
| b5cc0a7293 | |||
| cedef1792f | |||
| 624e39b78e | |||
| f71a9f2a29 | |||
| 96f9cc1d98 |
148
Cargo.lock
generated
Normal file
148
Cargo.lock
generated
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blackjack"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasip2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.180"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.105"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||||
|
dependencies = [
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.114"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasip2"
|
||||||
|
version = "1.0.1+wasi-0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "blackjack"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rand = "0.9.2"
|
||||||
37
src/card.rs
Normal file
37
src/card.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Card {
|
||||||
|
pub suit: u8,
|
||||||
|
pub value: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Card {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let value = match self.value {
|
||||||
|
0 => "A",
|
||||||
|
1 => "2",
|
||||||
|
2 => "3",
|
||||||
|
3 => "4",
|
||||||
|
4 => "5",
|
||||||
|
5 => "6",
|
||||||
|
6 => "7",
|
||||||
|
7 => "8",
|
||||||
|
8 => "9",
|
||||||
|
9 => "10",
|
||||||
|
10 => "J",
|
||||||
|
11 => "Q",
|
||||||
|
12 => "K",
|
||||||
|
_ => "",
|
||||||
|
};
|
||||||
|
let suit = match self.suit {
|
||||||
|
0 => "H",
|
||||||
|
1 => "C",
|
||||||
|
2 => "D",
|
||||||
|
3 => "S",
|
||||||
|
_ => "",
|
||||||
|
};
|
||||||
|
|
||||||
|
write!(f, "{}{}", value, suit)
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/deck.rs
Normal file
57
src/deck.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
use super::card::Card;
|
||||||
|
use rand::random_range;
|
||||||
|
|
||||||
|
pub struct Deck {
|
||||||
|
deck_size: u64,
|
||||||
|
current_card: u64,
|
||||||
|
cards: Vec<Card>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deck {
|
||||||
|
pub fn new(num_decks: u64) -> Self {
|
||||||
|
let deck_size: u64 = num_decks * 52;
|
||||||
|
let mut cards: Vec<Card> = Vec::with_capacity(deck_size as usize);
|
||||||
|
|
||||||
|
for card in 0..deck_size {
|
||||||
|
let value = (card % 13) as u8;
|
||||||
|
let suit = ((card / 13) % 4) as u8;
|
||||||
|
|
||||||
|
cards.push(Card {
|
||||||
|
value: value,
|
||||||
|
suit: suit,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Deck {
|
||||||
|
deck_size: deck_size,
|
||||||
|
current_card: 0,
|
||||||
|
cards: cards,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_next_card(&mut self) -> Card {
|
||||||
|
let next_card = self.cards[self.current_card as usize];
|
||||||
|
self.current_card += 1;
|
||||||
|
|
||||||
|
next_card
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deck_size(&self) -> usize {
|
||||||
|
self.deck_size as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cur_card(&self) -> u64 {
|
||||||
|
self.current_card
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shuffle(&mut self) {
|
||||||
|
for _ in 0..1000 {
|
||||||
|
for card in 0..self.deck_size {
|
||||||
|
let swap_card = random_range(0..self.deck_size);
|
||||||
|
let save_card = self.cards[card as usize];
|
||||||
|
self.cards[card as usize] = self.cards[swap_card as usize];
|
||||||
|
self.cards[swap_card as usize] = save_card;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
src/gamestate.rs
Normal file
0
src/gamestate.rs
Normal file
82
src/hand.rs
Normal file
82
src/hand.rs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use super::card::Card;
|
||||||
|
|
||||||
|
pub struct Hand {
|
||||||
|
cards: Vec<Card>,
|
||||||
|
is_dealer: bool,
|
||||||
|
show_all: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hand {
|
||||||
|
pub fn new(is_dealer: bool) -> Self {
|
||||||
|
let cards: Vec<Card> = Vec::new();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
cards: cards,
|
||||||
|
is_dealer: is_dealer,
|
||||||
|
show_all: !is_dealer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sum(&self) -> u8 {
|
||||||
|
let mut num_aces = 0;
|
||||||
|
let mut sum: u8 = 0;
|
||||||
|
if self.is_dealer && !self.show_all {
|
||||||
|
if self.cards[1].value + 1 > 10 {
|
||||||
|
return 10;
|
||||||
|
} else if self.cards[1].value + 1 == 1 {
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
return self.cards[1].value + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for card in 0..self.cards.len() {
|
||||||
|
match self.cards[card].value + 1 {
|
||||||
|
1 => {
|
||||||
|
sum += 11;
|
||||||
|
num_aces += 1;
|
||||||
|
}
|
||||||
|
2..=9 => sum += self.cards[card].value + 1,
|
||||||
|
10..=13 => sum += 10,
|
||||||
|
_ => sum += 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while num_aces > 0 && sum > 21 {
|
||||||
|
num_aces -= 1;
|
||||||
|
sum -= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_new_card(&mut self, new_card: Card) {
|
||||||
|
self.cards.push(new_card);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_show_all(&mut self, show_all: bool) {
|
||||||
|
if self.is_dealer {
|
||||||
|
self.show_all = show_all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Hand {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let mut display_string = String::new();
|
||||||
|
|
||||||
|
if self.show_all {
|
||||||
|
for card in 0..self.cards.len() {
|
||||||
|
display_string.push_str(&self.cards[card].to_string());
|
||||||
|
display_string.push_str(" ");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
display_string.push_str("** ");
|
||||||
|
display_string.push_str(&self.cards[1].to_string());
|
||||||
|
display_string.push_str(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "{}", display_string)
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/lib.rs
Normal file
20
src/lib.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
mod card;
|
||||||
|
|
||||||
|
pub use card::Card;
|
||||||
|
|
||||||
|
mod deck;
|
||||||
|
|
||||||
|
pub use deck::Deck;
|
||||||
|
|
||||||
|
mod gamestate;
|
||||||
|
mod hand;
|
||||||
|
|
||||||
|
pub use hand::Hand;
|
||||||
|
|
||||||
|
pub fn run() -> Result<(), Box<dyn Error>> {
|
||||||
|
println!("Hello, world!");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
8
src/main.rs
Normal file
8
src/main.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use blackjack::run;
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
run()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
19
tests/deck_tests.rs
Normal file
19
tests/deck_tests.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
use blackjack::Deck;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_num_decks() {
|
||||||
|
let mut num_card: [u64; 52] = [0; 52];
|
||||||
|
let num_decks = 8;
|
||||||
|
let mut deck = Deck::new(num_decks as u64);
|
||||||
|
deck.shuffle();
|
||||||
|
|
||||||
|
for _ in 0..deck.deck_size() {
|
||||||
|
let next_card = deck.get_next_card();
|
||||||
|
let card_pos = next_card.suit * 13 + next_card.value;
|
||||||
|
num_card[card_pos as usize] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for card in 0..num_card.len() {
|
||||||
|
assert_eq!(num_card[card], num_decks);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
tests/hand_tests.rs
Normal file
40
tests/hand_tests.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
use blackjack::Card;
|
||||||
|
use blackjack::Hand;
|
||||||
|
|
||||||
|
const ACE_HEARTS: Card = Card { suit: 0, value: 0 };
|
||||||
|
const ACE_SPADES: Card = Card { suit: 3, value: 0 };
|
||||||
|
const KING_HEARTS: Card = Card { suit: 0, value: 12 };
|
||||||
|
const KING_SPADES: Card = Card { suit: 3, value: 12 };
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_double_ace() {
|
||||||
|
let mut hand = Hand::new(false);
|
||||||
|
hand.get_new_card(ACE_HEARTS);
|
||||||
|
hand.get_new_card(ACE_SPADES);
|
||||||
|
|
||||||
|
assert_eq!(12, hand.sum());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_ace_double_face() {
|
||||||
|
let mut hand = Hand::new(false);
|
||||||
|
hand.get_new_card(ACE_HEARTS);
|
||||||
|
hand.get_new_card(ACE_SPADES);
|
||||||
|
hand.get_new_card(KING_HEARTS);
|
||||||
|
hand.get_new_card(KING_SPADES);
|
||||||
|
|
||||||
|
assert_eq!(22, hand.sum());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn show_all_is_dealer() {
|
||||||
|
let mut hand = Hand::new(true);
|
||||||
|
hand.get_new_card(ACE_HEARTS);
|
||||||
|
hand.get_new_card(KING_SPADES);
|
||||||
|
|
||||||
|
assert_eq!(10, hand.sum());
|
||||||
|
|
||||||
|
hand.set_show_all(true);
|
||||||
|
|
||||||
|
assert_eq!(21, hand.sum());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user