Compare commits

6 Commits

Author SHA1 Message Date
b2e2d547ef Created Hand Type
Created a Hand type that can also calculate the sum of the cards in the
hand. Also wrote a display for it so that we can just print hands out.

Reviewed-on: #13
2026-01-11 16:25:37 -05:00
b5cc0a7293 Deck Shuffling
Implemented a deck shuffling algorithm. It will iterate over the deck of
cards 1000 times and swap the card it is on with another random card to
mix up the deck.

Reviewed-on: #12
2026-01-10 20:09:53 -05:00
cedef1792f Deck Implementation
Implemented a Deck type that has a new function that returns an
unshuffled deck. Also wrote an integration test for the new function to
make sure that it works.

Reviewed-on: #11
2026-01-10 18:03:43 -05:00
624e39b78e Card Struct
Added first version of Card struct. Also added an ability for it to be printed out through rust standard functions.

Reviewed-on: #10
2026-01-10 15:37:00 -05:00
f71a9f2a29 Initial Skeleton Code
Initial skeleton code to start basing development work off of.

Reviewed-on: #4
2026-01-10 12:13:39 -05:00
96f9cc1d98 Default Dev Environment
Setup a default environment by running a cargo init.

Reviewed-on: #2
2026-01-08 20:24:13 -05:00
10 changed files with 418 additions and 0 deletions

148
Cargo.lock generated Normal file
View 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
View 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
View 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
View 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
View File

82
src/hand.rs Normal file
View 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
View 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
View 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
View 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
View 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());
}