Moving to foundations seems to be alright

I think there's probably a few more tests I should write
This commit is contained in:
2025-03-08 02:36:18 +00:00
parent 408978dd4f
commit 8ce03a4b1c

View File

@@ -146,6 +146,7 @@ impl Card {
}
pub fn can_be_placed_on_foundation(&self, top: &Option<Card>) -> 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<Card>,
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);
}
}