diff --git a/src/card.rs b/src/card.rs new file mode 100644 index 0000000..a730b78 --- /dev/null +++ b/src/card.rs @@ -0,0 +1,100 @@ +use rand::Rng; +use std::fmt; + +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum CardSuit { + Diamonds, + Clubs, + Hearts, + Spades, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub enum CardValue { + Two = 2, + Three, + Four, + Five, + Six, + Seven, + Eight, + Nine, + Ten, + Jack, + Queen, + King, + Ace, +} + +#[derive(PartialEq, Eq)] +pub struct PlayingCard { + pub value: CardValue, + pub suit: CardSuit, +} + +impl Ord for PlayingCard { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.value.cmp(&other.value) + } +} + +impl PartialOrd for PlayingCard { + fn partial_cmp(&self, other: &Self) -> Option { + self.value.partial_cmp(&other.value) + } +} + +impl fmt::Display for PlayingCard { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let suit = match self.suit { + CardSuit::Clubs => "♣", + CardSuit::Diamonds => "♦", + CardSuit::Hearts => "♥", + CardSuit::Spades => "♠", + }; + + write!(f, "{:?}{}", self.value, suit) + } +} + +pub fn draw_card(deck: &mut Vec) -> PlayingCard { + let num = rand::thread_rng().gen_range(0..deck.len()); + let card = deck.remove(num); + + card +} + +pub fn create_deck() -> Vec { + let mut deck: Vec = vec![]; + let suits = [ + CardSuit::Diamonds, + CardSuit::Clubs, + CardSuit::Hearts, + CardSuit::Spades, + ]; + + let values = [ + CardValue::Two, + CardValue::Three, + CardValue::Four, + CardValue::Five, + CardValue::Six, + CardValue::Seven, + CardValue::Eight, + CardValue::Nine, + CardValue::Ten, + CardValue::Jack, + CardValue::Queen, + CardValue::King, + CardValue::Ace, + ]; + + for s in suits { + for i in values { + let card = PlayingCard { suit: s, value: i }; + deck.insert(0, card); + } + } + + deck +} diff --git a/src/hand.rs b/src/hand.rs new file mode 100644 index 0000000..ca462d0 --- /dev/null +++ b/src/hand.rs @@ -0,0 +1,174 @@ +use crate::card::{CardValue, PlayingCard}; +use core::fmt; +use std::collections::HashMap; + +#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] +pub enum HandType { + HighCard, + OnePair, + TwoPair, + ThreeOfAKind, + Straight, + Flush, + FullHouse, + FourOfAKind, + StraightFlush, +} + +struct PokerHand { + cards: Vec, +} + +impl fmt::Display for PokerHand { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self.hand_type() { + HandType::HighCard => write!(f, "{}", self.cards[4]), + HandType::OnePair => { + for val in self.hash_map() { + if val.1 == 2 { + return write!(f, "Pair of {:?}'s", val); + } + } + return write!(f, "???"); + } + HandType::TwoPair => todo!(), + HandType::ThreeOfAKind => todo!(), + HandType::Straight => todo!(), + HandType::Flush => todo!(), + HandType::FullHouse => todo!(), + HandType::FourOfAKind => todo!(), + HandType::StraightFlush => todo!(), + }; + + s + } +} + +impl PokerHand { + fn new(mut cards: Vec) -> Self { + assert!(cards.len() == 5); + cards.sort_unstable(); + PokerHand { cards } + } + + fn hash_map(&self) -> HashMap { + let mut count: HashMap = HashMap::new(); + + for card in &self.cards { + *count.entry(card.value).or_insert(0) += 1; + } + + count + } + + fn hand_type(&self) -> HandType { + if is_straight_flush(self) { + return HandType::StraightFlush; + } + + if is_four_of_a_kind(self) { + return HandType::FourOfAKind; + } + + if is_full_house(self) { + return HandType::FullHouse; + } + + if is_flush(self) { + return HandType::Flush; + } + + if is_straight(self) { + return HandType::Straight; + } + + if is_three_of_a_kind(self) { + return HandType::ThreeOfAKind; + } + + if is_two_pair(self) { + return HandType::TwoPair; + } + + if is_one_pair(self) { + return HandType::OnePair; + } + + return HandType::HighCard; + } +} + +fn is_straight_flush(hand: &PokerHand) -> bool { + let hand = &hand.cards; + assert!(hand.len() == 5); + + let suit = hand[0].suit; + let mut min_val = CardValue::Two; + let mut max_val = CardValue::Ace; + + // Must all be the same suit + for i in 0..5 { + let card = &hand[i]; + + for k in (i + 1)..5 { + if hand[k].value == card.value { + return false; + } + } + + if card.value < min_val { + min_val = card.value; + }; + + if card.value > max_val { + max_val = card.value; + } + + if card.suit != suit { + return false; + } + } + + let max_val = max_val as u8; + let min_val = min_val as u8; + + if max_val - min_val > 4 { + return false; + } + + true +} + +fn is_four_of_a_kind(hand: &PokerHand) -> bool { + for e in hand.hash_map() { + if e.1 == 4 { + return true; + } + } + + false +} + +fn is_full_house(hand: &PokerHand) -> bool { + false +} + +fn is_flush(hand: &PokerHand) -> bool { + false +} + +fn is_straight(hand: &PokerHand) -> bool { + false +} + +fn is_three_of_a_kind(hand: &PokerHand) -> bool { + false +} + +fn is_two_pair(hand: &PokerHand) -> bool { + false +} + +fn is_one_pair(hand: &PokerHand) -> bool { + false +} diff --git a/src/main.rs b/src/main.rs index 1b89ead..9ea0ca0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,154 +1,41 @@ -use rand::Rng; -use std::collections::HashMap; -use std::fmt; +#![allow(dead_code)] + use std::vec; -#[derive(Clone, Copy, Eq, PartialEq)] -enum CardSuit { - Diamonds, - Clubs, - Hearts, - Spades, -} +mod card; +mod hand; -struct PlayingCard { - value: u8, - suit: CardSuit, -} - -fn is_straight_flush(hand: &Vec) -> bool { - assert!(hand.len() == 5); - - let suit = hand[0].suit; - let mut min_val = 15; - let mut max_val = 1; - - // Must all be the same suit - for i in 0..5 { - let card = &hand[i]; - - for k in (i + 1)..5 { - if hand[k].value == card.value { - return false; - } - } - - if card.value < min_val { - min_val = card.value; - }; - - if card.value > max_val { - max_val = card.value; - } - - if card.suit != suit { - return false; - } - } - - if max_val - min_val > 4 { - return false; - } - - true -} - -fn is_four_of_a_kind(hand: &Vec) -> bool { - let mut count: HashMap = HashMap::new(); - - for card in hand { - *count.entry(card.value).or_insert(0) += 1; - } - - for e in count { - if e.1 == 4 { - return true; - } - } - - false -} - -impl fmt::Display for PlayingCard { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let val = match self.value { - 2 => "Two", - 3 => "Three", - 4 => "Four", - 5 => "Five", - 6 => "Six", - 7 => "Seven", - 8 => "Eight", - 9 => "Nine", - 10 => "Ten", - 11 => "Jack", - 12 => "King", - 13 => "Queen", - 14 => "Ace", - _ => "???", - }; - - let suit = match self.suit { - CardSuit::Clubs => "Clubs", - CardSuit::Diamonds => "Diamonds", - CardSuit::Hearts => "Hearts", - CardSuit::Spades => "Spades", - }; - - write!(f, "{} of {}", val, suit) - } -} - -fn draw_card(deck: &mut Vec) -> PlayingCard { - let num = rand::thread_rng().gen_range(0..deck.len()); - let card = deck.remove(num); - - card -} - -fn create_deck() -> Vec { - let mut deck: Vec = vec![]; - - for s in [ - CardSuit::Diamonds, - CardSuit::Clubs, - CardSuit::Hearts, - CardSuit::Spades, - ] { - for i in 2..14 { - let card = PlayingCard { suit: s, value: i }; - deck.insert(0, card); - } - } - - deck -} +use crate::card::{create_deck, CardSuit, CardValue, PlayingCard}; +use crate::hand::HandType; fn main() { let mut deck = create_deck(); let card1: PlayingCard = PlayingCard { suit: CardSuit::Clubs, - value: 2, + value: CardValue::Five, }; let card2: PlayingCard = PlayingCard { suit: CardSuit::Clubs, - value: 2, + value: CardValue::Five, }; let card3: PlayingCard = PlayingCard { suit: CardSuit::Clubs, - value: 2, + value: CardValue::Five, }; let card4: PlayingCard = PlayingCard { suit: CardSuit::Clubs, - value: 2, + value: CardValue::Five, }; let card5: PlayingCard = PlayingCard { suit: CardSuit::Clubs, - value: 3, + value: CardValue::Five, }; let hand = vec![card1, card2, card3, card4, card5]; - println!("{}", is_four_of_a_kind(&hand)); + let hand1 = HandType::Flush; + let hand2 = HandType::StraightFlush; + + println!("{}", hand1 >= hand2); }