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