Much work fleshing out cards and hands.

This commit is contained in:
2024-03-22 22:59:42 -04:00
parent b01c5209f5
commit 7d6643d30b
3 changed files with 289 additions and 128 deletions

100
src/card.rs Normal file
View File

@@ -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<std::cmp::Ordering> {
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>) -> PlayingCard {
let num = rand::thread_rng().gen_range(0..deck.len());
let card = deck.remove(num);
card
}
pub fn create_deck() -> Vec<PlayingCard> {
let mut deck: Vec<PlayingCard> = 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
}

174
src/hand.rs Normal file
View File

@@ -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<PlayingCard>,
}
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<PlayingCard>) -> Self {
assert!(cards.len() == 5);
cards.sort_unstable();
PokerHand { cards }
}
fn hash_map(&self) -> HashMap<CardValue, u8> {
let mut count: HashMap<CardValue, u8> = 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
}

View File

@@ -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<PlayingCard>) -> 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<PlayingCard>) -> bool {
let mut count: HashMap<u8, u8> = 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>) -> PlayingCard {
let num = rand::thread_rng().gen_range(0..deck.len());
let card = deck.remove(num);
card
}
fn create_deck() -> Vec<PlayingCard> {
let mut deck: Vec<PlayingCard> = 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);
}