Added code to push to foundation

Need to write some tests. I have no idea if it works
This commit is contained in:
2025-03-08 02:05:04 +00:00
parent 804ff3f8b1
commit 408978dd4f

View File

@@ -131,7 +131,7 @@ pub enum StackingError {
} }
impl Card { impl Card {
pub fn can_be_placed_on_top_pile(&self, top: &Card) -> Result<(), StackingError> { pub fn can_be_placed_on_pile(&self, top: &Card) -> Result<(), StackingError> {
// Can't be the same Colour // Can't be the same Colour
if self.suit.colour() == top.suit.colour() { if self.suit.colour() == top.suit.colour() {
return Err(StackingError::SameColour); return Err(StackingError::SameColour);
@@ -145,7 +145,7 @@ impl Card {
Ok(()) Ok(())
} }
pub fn can_be_placed_on_top_foundation(&self, top: &Option<Card>) -> Result<(), StackingError> { pub fn can_be_placed_on_foundation(&self, top: &Option<Card>) -> Result<(), StackingError> {
match top { match top {
None => { None => {
if self.value == Value::Ace { if self.value == Value::Ace {
@@ -212,11 +212,12 @@ pub struct CardAndPosition {
pos: CardPosition, pos: CardPosition,
} }
#[derive(PartialEq)]
pub enum CardPosition { pub enum CardPosition {
Deck, // I don't think this will need to be used 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 TopWaste, // I don't think we'd ever interact with anything other than the top of the Waste
Pile(u8, u8), // (PileNumber, Index) Pile(usize, usize), // (PileNumber, Index)
Foundation(u8) Foundation(usize)
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@@ -266,24 +267,71 @@ impl Klondike {
} }
} }
pub fn move_card(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) { pub fn move_card(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool {
// TODO raise errors properly // TODO raise errors properly
assert!(source_card.card.is_some());
assert_eq!(source_card.card.unwrap().visible, true); assert_eq!(source_card.card.unwrap().visible, true);
source_card.pos.is_valid_source(); source_card.pos.is_valid_source();
dest_card.pos.is_valid_dest(); dest_card.pos.is_valid_dest();
// Maybe TODO - check the .cards is the actual card in that position
match dest_card.pos { match dest_card.pos {
CardPosition::Pile(_, _) => self.move_card_to_pile(&source_card, &dest_card), CardPosition::Pile(_, _) => self.move_card_to_pile(&source_card, &dest_card),
CardPosition::Foundation(_) => self.move_card_to_foundation(source_card, dest_card), CardPosition::Foundation(_f) => self.move_card_to_foundation(source_card, dest_card),
CardPosition::Deck | CardPosition::TopWaste => unreachable!() CardPosition::Deck | CardPosition::TopWaste => unreachable!()
} }
} }
pub fn move_card_to_foundation(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) { 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) {
return false;
}
if source_card.card.unwrap().can_be_placed_on_foundation(&dest_card.card).is_err() {
return false;
}
// TODO actually move the cards - it should be possible from here
// There really must be a better way to extract an enum "value" than this...
if let CardPosition::Foundation(foundation_index) = dest_card.pos {
match source_card.pos {
CardPosition::TopWaste => {
let card = self.waste.pop().unwrap();
self.foundation[foundation_index].push(card);
},
CardPosition::Pile(pile_index, _) => {
let card = self.piles[pile_index].pop().unwrap();
self.foundation[foundation_index].push(card);
},
CardPosition::Deck | CardPosition::Foundation(_) => unreachable!(),
}
}
unreachable!();
} }
pub fn move_card_to_pile(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) {
pub fn move_card_to_pile(self, source_card: &CardAndPosition, dest_card: &CardAndPosition) -> bool {
true
}
fn is_card_top_of_pile(self, pos: &CardPosition) -> bool {
// TODO consider, at which point the Pos::Pile() ranges etc are correct
match pos {
CardPosition::Pile(pile_index, card_index) => {
match self.piles.get(*pile_index) {
Some(pile_index) => {
// TODO - this is the correct palce to put a - 1
if *card_index == (pile_index.len() - 1) {
true
} else {
false
}
}
None => false
}
},
CardPosition::Deck | CardPosition::TopWaste | CardPosition::Foundation(_) => false
}
} }
} }
@@ -291,15 +339,15 @@ impl CardPosition {
// Unsure this is "correct" to just panic - but it really shouldn't happen // Unsure this is "correct" to just panic - but it really shouldn't happen
fn is_valid_dest(&self) { fn is_valid_dest(&self) {
match self { match self {
CardPosition::Deck => unreachable!("You can't move cards to deck"), CardPosition::Deck => panic!("You can't move cards to deck"),
CardPosition::TopWaste => unreachable!("You can't move cards to waste"), CardPosition::TopWaste => panic!("You can't move cards to waste"),
CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (), CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (),
} }
} }
fn is_valid_source(&self) { fn is_valid_source(&self) {
match self { match self {
CardPosition::Deck => unreachable!("You can't move cards from deck"), CardPosition::Deck => panic!("You can't move cards from deck"),
CardPosition::TopWaste | CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (), CardPosition::TopWaste | CardPosition::Pile(_, _) | CardPosition::Foundation(_) => (),
} }
} }
@@ -350,25 +398,25 @@ mod tests {
value: Value::Six, value: Value::Six,
..Default::default() ..Default::default()
}; };
assert_eq!(testing_card.can_be_placed_on_top_pile(&bad_same_suit), Err(StackingError::SameColour)); assert_eq!(testing_card.can_be_placed_on_pile(&bad_same_suit), Err(StackingError::SameColour));
let bad_same_colour = Card { let bad_same_colour = Card {
suit: Suit::Diamond, suit: Suit::Diamond,
value: Value::Six, value: Value::Six,
..Default::default() ..Default::default()
}; };
assert_eq!(testing_card.can_be_placed_on_top_pile(&bad_same_colour), Err(StackingError::SameColour)); assert_eq!(testing_card.can_be_placed_on_pile(&bad_same_colour), Err(StackingError::SameColour));
let should_stack_card = Card { let should_stack_card = Card {
suit: Suit::Club, suit: Suit::Club,
value: Value::Six, value: Value::Six,
..Default::default() ..Default::default()
}; };
assert_eq!(testing_card.can_be_placed_on_top_pile(&should_stack_card), Ok(())); assert_eq!(testing_card.can_be_placed_on_pile(&should_stack_card), Ok(()));
let value_too_high = Card { let value_too_high = Card {
suit: Suit::Club, suit: Suit::Club,
value: Value::Seven, value: Value::Seven,
..Default::default() ..Default::default()
}; };
let not_adj_error = testing_card.can_be_placed_on_top_pile(&value_too_high); let not_adj_error = testing_card.can_be_placed_on_pile(&value_too_high);
if let Err(e) = not_adj_error { if let Err(e) = not_adj_error {
match e { match e {
StackingError::NotAdjacent(_, _) => assert!(true), StackingError::NotAdjacent(_, _) => assert!(true),