diff --git a/Cargo.lock b/Cargo.lock index e20da57..64361ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "bitflags" version = "2.11.1" @@ -18,6 +24,7 @@ checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" name = "card_game" version = "0.1.0" dependencies = [ + "arrayvec", "rand", ] diff --git a/Cargo.toml b/Cargo.toml index 3c34404..21ea8fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] +arrayvec = "0.7.6" rand = { version = "0.10.1", default-features = false, features = ["thread_rng"] } diff --git a/src/card_game.rs b/src/card_game.rs index 69d7fac..f24a9ac 100644 --- a/src/card_game.rs +++ b/src/card_game.rs @@ -101,14 +101,16 @@ impl Card { } #[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct Stack(Vec); -impl Stack { +pub struct Stack(arrayvec::ArrayVec); +impl Stack { 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. - pub fn full_deck(deck: u8) -> Stack { - let mut stack = Vec::with_capacity(52); + pub fn full_deck(deck: u8) -> Self { + let mut stack = arrayvec::ArrayVec::new(); for suit in Suit::SUITS { for value in 1..=13 { stack.push(Card::new(deck, suit, CardValue(value))); @@ -117,36 +119,43 @@ impl Stack { Stack(stack) } } -impl From> for Stack { - fn from(value: Vec) -> Self { +impl From> for Stack { + fn from(value: arrayvec::ArrayVec) -> Self { Self(value) } } -impl std::ops::Deref for Stack { - type Target = Vec; +impl std::ops::Deref for Stack { + type Target = arrayvec::ArrayVec; fn deref(&self) -> &Self::Target { &self.0 } } -impl std::ops::DerefMut for Stack { +impl std::ops::DerefMut for Stack { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } +impl IntoIterator for Stack { + type Item = Card; + type IntoIter = arrayvec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} #[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct Pile { - face_down: Stack, - face_up: Stack, +pub struct Pile { + face_down: Stack, + face_up: Stack, } -impl Pile { +impl Pile { pub fn new() -> Self { Self { face_down: Stack::new(), face_up: Stack::new(), } } - pub fn new_face_down(stack: Stack) -> Self { + pub fn new_face_down(stack: Stack) -> Self { Self { face_down: stack, face_up: Stack::new(), diff --git a/src/klondike.rs b/src/klondike.rs index 87ee6ac..6d6014c 100644 --- a/src/klondike.rs +++ b/src/klondike.rs @@ -75,13 +75,13 @@ impl KlondikeInstruction { #[derive(Clone, Debug, Eq, Hash, PartialEq)] struct KlondikeState { - piles: [Pile; 13], + piles: [Pile<13>; 13], } impl KlondikeState { - fn pile(&self, index: KlondikePileId) -> &Pile { + fn pile(&self, index: KlondikePileId) -> &Pile<13> { &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] } fn is_instruction_valid(&self, instruction: KlondikeInstruction) -> bool { @@ -187,18 +187,18 @@ impl Klondike { let mut deck = Stack::full_deck(0); use rand::seq::SliceRandom; deck.shuffle(&mut seed); + let mut deck = deck.into_iter(); // generate tableaus let [t0, t1, t2, t3, t4, t5, t6, t7] = core::array::from_fn(|i| { - let remaining = deck.split_off(i).into(); - let stack = core::mem::replace(&mut deck, remaining); + let stack = arrayvec::ArrayVec::from_iter((&mut deck).take(i)).into(); let mut pile = Pile::new_face_down(stack); - pile.push(deck.pop().unwrap()); + pile.push(deck.next().unwrap()); pile }); // 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 { piles: [ @@ -220,11 +220,11 @@ impl Klondike { Self { config, state } } #[inline] - pub fn pile(&self, index: KlondikePileId) -> &Pile { + pub fn pile(&self, index: KlondikePileId) -> &Pile<13> { self.state.pile(index) } #[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) } }