diff --git a/src/models/hand.rs b/src/models/hand.rs index 5868849..11d12c9 100644 --- a/src/models/hand.rs +++ b/src/models/hand.rs @@ -12,6 +12,7 @@ pub enum HandSort { pub struct Hand { pub cards: Vec, pub card_sort: HandSort, + pub hand_value: u8, } impl Hand { @@ -19,6 +20,7 @@ impl Hand { Hand { cards: Vec::new(), card_sort: HandSort::None, + hand_value: 0, } } @@ -47,6 +49,7 @@ impl Hand { self.card_sort = HandSort::Rank; } + /// Checks all cards and returns total amount of pairs in the hand fn pair_count(&self) -> u8 { let mut pairs = 0; @@ -64,6 +67,9 @@ impl Hand { pairs } + /// Checks if the current hand has only one pair. \ + /// One pair is a hand that contains two cards of one rank and three cards of three + /// other ranks, such as `4♥ 4♠ K♠ 10♦ 5♠` pub fn has_single_pair(&mut self) -> bool { if !matches!(self.card_sort, HandSort::Value) { self.sort(HandSort::Value); @@ -76,6 +82,9 @@ impl Hand { false } + /// Checks if the current hand has exactly two pairs. \ + /// Two pair is a hand that contains two cards of one rank, two cards of another rank, + /// and one card of a third rank, such as `J♥ J♣ 4♣ 4♠ 9♥` pub fn has_two_pair(&mut self) -> bool { if !matches!(self.card_sort, HandSort::Value) { self.sort(HandSort::Value); @@ -88,12 +97,16 @@ impl Hand { false } + /// Checks if the current hand has a three of a kind. \ + /// Three of a kind is a hand that contains three cards of one rank and + /// two cards of two other ranks, such as `2♦ 2♠ 2♣ K♠ 6♥` pub fn has_three_of_a_kind(&mut self) -> bool { if !matches!(self.card_sort, HandSort::Value) { self.sort(HandSort::Value); } for i in 2..self.cards.len() { - if self.cards[i].rank == self.cards[i - 1].rank && self.cards[i].rank == self.cards[i - 2].rank { + if self.cards[i].rank == self.cards[i - 1].rank && + self.cards[i].rank == self.cards[i - 2].rank { return true; } } @@ -101,6 +114,9 @@ impl Hand { false } + /// Checks if the current hand has a straight. \ + /// A straight is a hand that contains five cards of sequential rank, + /// not all the same suit, such as `7♣ 6♠ 5♠ 4♥ 3♥` pub fn has_straight(&mut self) -> bool { if !matches!(self.card_sort, HandSort::Value) { self.sort(HandSort::Value); @@ -123,6 +139,9 @@ impl Hand { true } + /// Checks if the current hand has a flush. \ + /// A flush is a hand that contains five cards, all the same suit, + /// and not all of sequential rank, such as `K♣ 10♣ 7♣ 6♣ 4♣` pub fn has_flush(&self) -> bool { for i in 1..self.cards.len() { if self.cards[i].suit != self.cards[i - 1].suit { @@ -133,18 +152,40 @@ impl Hand { true } + /// Checks if the current hand has a full house. \ + /// A full house is a hand that contains three cards of one + /// rank and two cards of another rank, such as `3♣ 3♠ 3♦ 6♣ 6♥` pub fn has_full_house(&mut self) -> bool { - if self.has_three_of_a_kind() && self.has_two_pair() { - return true; + if !matches!(self.card_sort, HandSort::Value) { + self.sort(HandSort::Value); } - false + let mut has_pair = false; + let mut has_three_of_a_kind = false; + + // Check the first two positions for a pair to let the loop check for 2/3 of a kind + if self.cards[0].rank == self.cards[1].rank { has_pair = true; } + for i in 2..self.cards.len() { + if self.cards[i].rank == self.cards[i - 1].rank { + has_pair = true; + } + + if self.cards[i].rank == self.cards[i - 1].rank && + self.cards[i].rank == self.cards[i - 2].rank { + has_three_of_a_kind = true; + } + } + has_pair && has_three_of_a_kind } + /// Checks if the current hand has a four of a kind. \ + /// Four of a kind is a hand that contains four cards of one rank + /// and one card of another rank, such as `9♣ 9♠ 9♦ 9♥ J♥` pub fn has_four_of_a_kind(&mut self) -> bool { if !matches!(self.card_sort, HandSort::Value) { self.sort(HandSort::Value); } + for i in 3..self.cards.len() { if self.cards[i].rank == self.cards[i - 1].rank && self.cards[i].rank == self.cards[i - 2].rank && @@ -157,11 +198,55 @@ impl Hand { false } + /// Checks if the current hand has a straight flush. \ + /// A straight flush is a hand that contains five cards of sequential rank, + /// all the same suit, such as `Q♥ J♥ 10♥ 9♥ 8♥` pub fn has_straight_flush(&mut self) -> bool { - self.has_straight() && self.has_flush() + if !matches!(self.card_sort, HandSort::Value) { + self.sort(HandSort::Value); + } + + let mut has_flush = true; + let mut has_straight = true; + + let suit = &self.cards[0].suit; + + for i in 1..self.cards.len() { + if &self.cards[i].suit != suit { + has_flush = false; + break; + } + if self.cards[i].value != self.cards[i - 1].value + 1 { + has_straight = false; + break; + } + } + + has_flush && has_straight } + /// Checks if the current hand has a royal flush, the best possible hand. \ + /// A royal flush is a hand that contains an ace-high straight flush, such as `A♦ K♦ Q♦ J♦ 10♦` pub fn has_royal_flush(&mut self) -> bool { - self.has_flush() && self.has_straight() && self.cards[0].value == 10 + if !matches!(self.card_sort, HandSort::Value) { + self.sort(HandSort::Value); + } + + let mut has_flush = true; + let mut has_straight = true; + let suit = &self.cards[0].suit; + + for i in 1..self.cards.len() { + if &self.cards[i].suit != suit { + has_flush = false; + break; + } + if self.cards[i].value != self.cards[i - 1].value + 1 { + has_straight = false; + break; + } + } + + has_flush && has_straight && self.cards[0].value == 10 } } diff --git a/src/poker.rs b/src/poker.rs index 864a5f6..2491701 100644 --- a/src/poker.rs +++ b/src/poker.rs @@ -1,13 +1,8 @@ -use crate::models::deck::{Card, Deck}; +use crate::models::deck::Deck; use crate::models::hand::Hand; use crate::models::player::Player; use std::io; -struct Game { - name: String, - deck: Vec, -} - pub fn game() { let mut deck = Deck::new(); deck.shuffle(); diff --git a/src/tests/hand_test.rs b/src/tests/hand_test.rs index 9fbcbd9..506ba9f 100644 --- a/src/tests/hand_test.rs +++ b/src/tests/hand_test.rs @@ -17,7 +17,7 @@ mod tests { } #[test] - fn test_hand_adds_cards_to_exhasting_hand() { + fn test_hand_draw_adds_cards_to_exhasting_hand() { let mut deck = Deck::new(); let mut player = Player { name: String::from("Testy McTestFace"),