This commit is contained in:
2026-05-15 16:01:26 -07:00
parent b8624ef9d0
commit 3edc19d02e
2 changed files with 44 additions and 48 deletions
+5 -12
View File
@@ -144,30 +144,23 @@ impl<const CAP: usize> IntoIterator for Stack<CAP> {
} }
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Pile<const CAP: usize> { pub struct Pile<const DN: usize, const UP: usize> {
face_down: Stack<CAP>, face_down: Stack<DN>,
face_up: Stack<CAP>, face_up: Stack<UP>,
} }
impl<const CAP: usize> Pile<CAP> { impl<const DN: usize, const UP: usize> Pile<DN, UP> {
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<CAP>) -> Self { pub fn new_face_down(stack: Stack<DN>) -> Self {
Self { Self {
face_down: stack, face_down: stack,
face_up: Stack::new(), face_up: Stack::new(),
} }
} }
pub fn flip_it_and_reverse_it(&mut self) {
self.swap_up_down();
self.face_down.reverse();
}
pub fn swap_up_down(&mut self) {
core::mem::swap(&mut self.face_up, &mut self.face_down);
}
pub fn flip_up(&mut self) { pub fn flip_up(&mut self) {
if let Some(card) = self.face_down.pop() { if let Some(card) = self.face_down.pop() {
self.face_up.push(card); self.face_up.push(card);
+38 -35
View File
@@ -1,5 +1,5 @@
use crate::Rng; use crate::Rng;
use crate::card_game::{CardValue, Game, Pile, Stack}; use crate::card_game::{Card, CardValue, Game, Pile, Stack};
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct KlondikeConfig {} pub struct KlondikeConfig {}
@@ -81,15 +81,17 @@ const MAX_STACK: usize = 52 - sum(TABLEAUS);
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
struct KlondikeState { struct KlondikeState {
piles: [Pile<MAX_STACK>; TABLEAUS + FOUNDATIONS + STOCKS], stock: Pile<MAX_STACK, MAX_STACK>,
foundations: [Stack<13>; 4],
tableau1: Pile<0, 13>,
tableau2: Pile<1, 13>,
tableau3: Pile<2, 13>,
tableau4: Pile<3, 13>,
tableau5: Pile<4, 13>,
tableau6: Pile<5, 13>,
tableau7: Pile<6, 13>,
} }
impl KlondikeState { impl KlondikeState {
fn pile(&self, index: KlondikePileId) -> &Pile<MAX_STACK> {
&self.piles[index as usize]
}
fn pile_mut(&mut self, index: KlondikePileId) -> &mut Pile<MAX_STACK> {
&mut self.piles[index as usize]
}
fn is_instruction_valid(&self, instruction: KlondikeInstruction) -> bool { fn is_instruction_valid(&self, instruction: KlondikeInstruction) -> bool {
match instruction { match instruction {
// Stock -> Stock draws a card or resets the stock // Stock -> Stock draws a card or resets the stock
@@ -98,7 +100,7 @@ impl KlondikeState {
dst: KlondikePileId::Stock, dst: KlondikePileId::Stock,
} => { } => {
// cannot move stock when stock is empty // cannot move stock when stock is empty
!self.pile(KlondikePileId::Stock).is_empty() !self.stock.is_empty()
} }
// cannot move cards to stock // cannot move cards to stock
@@ -196,42 +198,36 @@ impl Klondike {
let mut deck = deck.into_iter(); let mut deck = deck.into_iter();
// generate tableaus // generate tableaus
let [t0, t1, t2, t3, t4, t5, t6] = core::array::from_fn(|i| { fn pile<const DN: usize>(deck: &mut arrayvec::IntoIter<Card, 52>) -> Pile<DN, 13> {
let stack = arrayvec::ArrayVec::from_iter((&mut deck).take(i)).into(); let stack = arrayvec::ArrayVec::from_iter(deck.take(DN)).into();
let mut pile = Pile::new_face_down(stack); let mut pile = Pile::new_face_down(stack);
pile.push(deck.next().unwrap()); pile.push(deck.next().unwrap());
pile pile
}); }
let tableau1 = pile(&mut deck);
let tableau2 = pile(&mut deck);
let tableau3 = pile(&mut deck);
let tableau4 = pile(&mut deck);
let tableau5 = pile(&mut deck);
let tableau6 = pile(&mut deck);
let tableau7 = pile(&mut deck);
// stock is remaining cards // stock is remaining cards
let stock = Pile::new_face_down(arrayvec::ArrayVec::from_iter(deck).into()); let stock = Pile::new_face_down(arrayvec::ArrayVec::from_iter(deck).into());
let state = KlondikeState { let state = KlondikeState {
piles: [
t0,
t1,
t2,
t3,
t4,
t5,
t6,
Pile::new(),
Pile::new(),
Pile::new(),
Pile::new(),
stock, stock,
], foundations: core::array::from_fn(|_| Stack::new()),
tableau1,
tableau2,
tableau3,
tableau4,
tableau5,
tableau6,
tableau7,
}; };
Self { config, state } Self { config, state }
} }
#[inline]
pub fn pile(&self, index: KlondikePileId) -> &Pile<MAX_STACK> {
self.state.pile(index)
}
#[inline]
fn pile_mut(&mut self, index: KlondikePileId) -> &mut Pile<MAX_STACK> {
self.state.pile_mut(index)
}
} }
impl Game for Klondike { impl Game for Klondike {
@@ -268,7 +264,14 @@ impl Game for Klondike {
} }
} }
fn is_win(&self) -> bool { fn is_win(&self) -> bool {
// assuming only valid moves, tableau empty and stock empty means win // all face down cards empty means win
self.state.piles[0..9].iter().all(|pile| pile.is_empty()) self.state.stock.face_down().is_empty()
&& self.state.tableau1.face_down().is_empty()
&& self.state.tableau2.face_down().is_empty()
&& self.state.tableau3.face_down().is_empty()
&& self.state.tableau4.face_down().is_empty()
&& self.state.tableau5.face_down().is_empty()
&& self.state.tableau6.face_down().is_empty()
&& self.state.tableau7.face_down().is_empty()
} }
} }