From 8ce03a4b1c4dfcd85ed6b97072c6b461d648719f Mon Sep 17 00:00:00 2001 From: Arthur Roberts Date: Sat, 8 Mar 2025 02:36:18 +0000 Subject: [PATCH] Moving to foundations seems to be alright I think there's probably a few more tests I should write --- card_stuffs/src/lib.rs | 128 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 121 insertions(+), 7 deletions(-) diff --git a/card_stuffs/src/lib.rs b/card_stuffs/src/lib.rs index 3c0a568..023cf69 100644 --- a/card_stuffs/src/lib.rs +++ b/card_stuffs/src/lib.rs @@ -146,6 +146,7 @@ impl Card { } pub fn can_be_placed_on_foundation(&self, top: &Option) -> Result<(), StackingError> { + // TODO check suit is correct match top { None => { if self.value == Value::Ace { @@ -207,12 +208,13 @@ impl Deck { } } +#[derive(Debug)] pub struct CardAndPosition { card: Option, pos: CardPosition, } -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] pub enum CardPosition { Deck, // I don't think this will need to be used TopWaste, // I don't think we'd ever interact with anything other than the top of the Waste @@ -286,10 +288,13 @@ impl Klondike { pub fn move_card_to_foundation(mut self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool { // TODO Check whether the card is the top of a pile / waste - it needs to be // TODO actually learn Rust properly so I can figure out why I need to clone the whole struct to check a value - if source_card.pos != CardPosition::TopWaste || !self.clone().is_card_top_of_pile(&source_card.pos) { + if source_card.pos != CardPosition::TopWaste && !self.clone().is_card_top_of_pile(&source_card.pos) { + // TODO as above - make this a proper error + println!("Can't move from this position"); return false; } if source_card.card.unwrap().can_be_placed_on_foundation(&dest_card.card).is_err() { + println!("Can't be placed on foundation for some reason - wrong colour? wrong value?"); return false; } // TODO actually move the cards - it should be possible from here @@ -299,12 +304,16 @@ impl Klondike { CardPosition::TopWaste => { let card = self.waste.pop().unwrap(); self.foundation[foundation_index].push(card); + return true; }, CardPosition::Pile(pile_index, _) => { let card = self.piles[pile_index].pop().unwrap(); self.foundation[foundation_index].push(card); + return true; + }, + CardPosition::Deck | CardPosition::Foundation(_) => { + unreachable!() }, - CardPosition::Deck | CardPosition::Foundation(_) => unreachable!(), } } unreachable!(); @@ -434,25 +443,130 @@ mod tests { value: Value::Ace, ..Default::default() }; - assert_eq!(testing_card.can_be_placed_on_top_foundation(&None), Ok(())); + assert_eq!(testing_card.can_be_placed_on_foundation(&None), Ok(())); let testing_card = Card { suit: Suit::Spade, value: Value::Two, ..Default::default() }; - assert!(testing_card.can_be_placed_on_top_foundation(&None).is_err()); + assert!(testing_card.can_be_placed_on_foundation(&None).is_err()); + } + + #[test] + fn moving_to_foundation() { + // GOOD: Ace from Pile to Empty Foundation + let mut klon = Klondike::default(); + let ace = Card { + suit: Suit::Spade, + value: Value::Ace, + .. Default::default() + }; + klon.piles[0].push(ace.clone()); + let source_card = CardAndPosition { + card: Some(ace.clone()), + pos: CardPosition::Pile(0, 1) + }; + let dest_card = CardAndPosition { + card: None, + pos: CardPosition::Foundation(0), + }; + assert!(klon.move_card_to_foundation(&source_card, &dest_card)); + + // BAD: Non-Ace from Pile to Empty Foundaction + let mut klon = Klondike::default(); + let two = Card { + suit: Suit::Spade, + value: Value::Two, + .. Default::default() + }; + klon.piles[0].push(two.clone()); + let source_card = CardAndPosition { + card: Some(two.clone()), + pos: CardPosition::Pile(0, 1) + }; + let dest_card = CardAndPosition { + card: None, + pos: CardPosition::Foundation(0), + }; + assert!(!klon.move_card_to_foundation(&source_card, &dest_card)); + + // GOOD: Ace from TopWaste to Empty Foundaction + let mut klon = Klondike::default(); + let ace = Card { + suit: Suit::Spade, + value: Value::Ace, + .. Default::default() + }; + klon.waste.push(ace.clone()); + let source_card = CardAndPosition { + card: Some(ace.clone()), + pos: CardPosition::TopWaste, + }; + let dest_card = CardAndPosition { + card: None, + pos: CardPosition::Foundation(0), + }; + assert!(klon.move_card_to_foundation(&source_card, &dest_card)); + + // BAD: Non-Ace from TopWaste to Empty Foundaction + let mut klon = Klondike::default(); + let two = Card { + suit: Suit::Spade, + value: Value::Two, + .. Default::default() + }; + klon.waste.push(two.clone()); + let source_card = CardAndPosition { + card: Some(two.clone()), + pos: CardPosition::TopWaste, + }; + let dest_card = CardAndPosition { + card: None, + pos: CardPosition::Foundation(0), + }; + assert!(!klon.move_card_to_foundation(&source_card, &dest_card)); + + // GOOD: Two from TopWaste to Foundaction with Ace there + let mut klon = Klondike::default(); + let ace = Card { + suit: Suit::Spade, + value: Value::Ace, + .. Default::default() + }; + let two = Card { + suit: Suit::Spade, + value: Value::Two, + .. Default::default() + }; + klon.waste.push(two.clone()); + klon.piles[0].push(ace.clone()); + let source_card = CardAndPosition { + card: Some(ace.clone()), + pos: CardPosition::TopWaste, + }; + let dest_card = CardAndPosition { + card: None, + pos: CardPosition::Foundation(0), + }; + assert!(klon.move_card_to_foundation(&source_card, &dest_card)); + + // TODO the following cases: + // - moving a card from pile to foundation when something is already there + // - moving Ace from waste to top of pile + // - moving a card frmo waste to foundation when something is already there + // => for cases where it'll both work and not work - when cards are / aren't present } #[test] fn get_a_whole_deck() { let d = Deck::default(); assert_eq!(d.cards.len(), 52); // Probably should test whether all cards are in... eh - println!("{:#?}", d); // A "manual" review looks alright + //println!("{:#?}", d); // A "manual" review looks alright } #[test] fn klondike() { let k = Klondike::default(); - println!("{:#?}", k); + //println!("{:#?}", k); } }