implement Stack using ArrayVec

This commit is contained in:
2026-05-15 13:48:36 -07:00
parent 334084e4df
commit bbe4ec6625
4 changed files with 41 additions and 24 deletions
Generated
+7
View File
@@ -8,6 +8,12 @@ version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.11.1" version = "2.11.1"
@@ -18,6 +24,7 @@ checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
name = "card_game" name = "card_game"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"arrayvec",
"rand", "rand",
] ]
+1
View File
@@ -4,4 +4,5 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
arrayvec = "0.7.6"
rand = { version = "0.10.1", default-features = false, features = ["thread_rng"] } rand = { version = "0.10.1", default-features = false, features = ["thread_rng"] }
+24 -15
View File
@@ -101,14 +101,16 @@ impl Card {
} }
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Stack(Vec<Card>); pub struct Stack<const CAP: usize>(arrayvec::ArrayVec<Card, CAP>);
impl Stack { impl<const CAP: usize> Stack<CAP> {
pub fn new() -> Self { pub fn new() -> Self {
Self(Vec::new()) Self(arrayvec::ArrayVec::new())
} }
}
impl Stack<52> {
/// Generate a full deck of cards with the specified deck id. /// Generate a full deck of cards with the specified deck id.
pub fn full_deck(deck: u8) -> Stack { pub fn full_deck(deck: u8) -> Self {
let mut stack = Vec::with_capacity(52); let mut stack = arrayvec::ArrayVec::new();
for suit in Suit::SUITS { for suit in Suit::SUITS {
for value in 1..=13 { for value in 1..=13 {
stack.push(Card::new(deck, suit, CardValue(value))); stack.push(Card::new(deck, suit, CardValue(value)));
@@ -117,36 +119,43 @@ impl Stack {
Stack(stack) Stack(stack)
} }
} }
impl From<Vec<Card>> for Stack { impl<const CAP: usize> From<arrayvec::ArrayVec<Card, CAP>> for Stack<CAP> {
fn from(value: Vec<Card>) -> Self { fn from(value: arrayvec::ArrayVec<Card, CAP>) -> Self {
Self(value) Self(value)
} }
} }
impl std::ops::Deref for Stack { impl<const CAP: usize> std::ops::Deref for Stack<CAP> {
type Target = Vec<Card>; type Target = arrayvec::ArrayVec<Card, CAP>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.0 &self.0
} }
} }
impl std::ops::DerefMut for Stack { impl<const CAP: usize> std::ops::DerefMut for Stack<CAP> {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }
impl<const CAP: usize> IntoIterator for Stack<CAP> {
type Item = Card;
type IntoIter = arrayvec::IntoIter<Card, CAP>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Pile { pub struct Pile<const CAP: usize> {
face_down: Stack, face_down: Stack<CAP>,
face_up: Stack, face_up: Stack<CAP>,
} }
impl Pile { impl<const CAP: usize> Pile<CAP> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
face_down: Stack::new(), face_down: Stack::new(),
face_up: Stack::new(), face_up: Stack::new(),
} }
} }
pub fn new_face_down(stack: Stack) -> Self { pub fn new_face_down(stack: Stack<CAP>) -> Self {
Self { Self {
face_down: stack, face_down: stack,
face_up: Stack::new(), face_up: Stack::new(),
+9 -9
View File
@@ -75,13 +75,13 @@ impl KlondikeInstruction {
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
struct KlondikeState { struct KlondikeState {
piles: [Pile; 13], piles: [Pile<13>; 13],
} }
impl KlondikeState { impl KlondikeState {
fn pile(&self, index: KlondikePileId) -> &Pile { fn pile(&self, index: KlondikePileId) -> &Pile<13> {
&self.piles[index as usize] &self.piles[index as usize]
} }
fn pile_mut(&mut self, index: KlondikePileId) -> &mut Pile { fn pile_mut(&mut self, index: KlondikePileId) -> &mut Pile<13> {
&mut self.piles[index as usize] &mut self.piles[index as usize]
} }
fn is_instruction_valid(&self, instruction: KlondikeInstruction) -> bool { fn is_instruction_valid(&self, instruction: KlondikeInstruction) -> bool {
@@ -187,18 +187,18 @@ impl Klondike {
let mut deck = Stack::full_deck(0); let mut deck = Stack::full_deck(0);
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
deck.shuffle(&mut seed); deck.shuffle(&mut seed);
let mut deck = deck.into_iter();
// generate tableaus // generate tableaus
let [t0, t1, t2, t3, t4, t5, t6, t7] = core::array::from_fn(|i| { let [t0, t1, t2, t3, t4, t5, t6, t7] = core::array::from_fn(|i| {
let remaining = deck.split_off(i).into(); let stack = arrayvec::ArrayVec::from_iter((&mut deck).take(i)).into();
let stack = core::mem::replace(&mut deck, remaining);
let mut pile = Pile::new_face_down(stack); let mut pile = Pile::new_face_down(stack);
pile.push(deck.pop().unwrap()); pile.push(deck.next().unwrap());
pile pile
}); });
// stock is remaining cards // stock is remaining cards
let stock = Pile::new_face_down(deck); let stock = Pile::new_face_down(arrayvec::ArrayVec::from_iter(deck).into());
let state = KlondikeState { let state = KlondikeState {
piles: [ piles: [
@@ -220,11 +220,11 @@ impl Klondike {
Self { config, state } Self { config, state }
} }
#[inline] #[inline]
pub fn pile(&self, index: KlondikePileId) -> &Pile { pub fn pile(&self, index: KlondikePileId) -> &Pile<13> {
self.state.pile(index) self.state.pile(index)
} }
#[inline] #[inline]
fn pile_mut(&mut self, index: KlondikePileId) -> &mut Pile { fn pile_mut(&mut self, index: KlondikePileId) -> &mut Pile<13> {
self.state.pile_mut(index) self.state.pile_mut(index)
} }
} }