Skip to main content

spades/
cards.rs

1use rand::thread_rng;
2use rand::seq::SliceRandom;
3use std::fmt;
4use std::cmp::Ordering;
5use serde::{Serialize, Deserialize};
6
7#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub enum Suit {
9    Blank = 0,
10    Club = 1,
11    Diamond = 2,
12    Heart = 3,
13    Spade = 4,
14}
15
16impl fmt::Debug for Suit {
17    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18        match self {
19            Suit::Blank => write!(f, " "),
20            Suit::Club => write!(f, "\u{2667}"),
21            Suit::Diamond => write!(f, "\u{2662}"),
22            Suit::Heart => write!(f, "\u{2661}"),
23            Suit::Spade => write!(f, "\u{2664}"),
24        }
25    }
26}
27#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
28pub enum Rank {
29    Blank = 0,
30    Two = 2,
31    Three = 3,
32    Four = 4,
33    Five = 5,
34    Six = 6,
35    Seven = 7,
36    Eight = 8,
37    Nine = 9,
38    Ten = 10,
39    Jack = 11,
40    Queen = 12,
41    King = 13,
42    Ace = 14
43}
44impl fmt::Debug for Rank {
45    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46        match self {
47            Rank::Blank => write!(f, " "),
48            Rank::Two => write!(f, "2"),
49            Rank::Three => write!(f, "3"),
50            Rank::Four => write!(f, "4"),
51            Rank::Five => write!(f, "5"),
52            Rank::Six => write!(f, "6"),
53            Rank::Seven => write!(f, "7"),
54            Rank::Eight => write!(f, "8"),
55            Rank::Nine => write!(f, "9"),
56            Rank::Ten => write!(f, "10"),
57            Rank::Jack => write!(f, "J"),
58            Rank::Queen => write!(f, "Q"),
59            Rank::King => write!(f, "K"),
60            Rank::Ace => write!(f, "A"),
61        }
62    }
63}
64
65/// Intuitive card struct. Comparisons are made according to alphabetical order, ascending.
66#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
67pub struct Card {
68    pub suit: Suit,
69    pub rank: Rank
70}
71
72impl fmt::Debug for Card {
73    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74        write!(f, "{:?} {:?}",self.suit , self.rank)
75    }
76}
77
78impl Ord for Card {
79    fn cmp(&self, other: &Card) -> Ordering {
80        ((self.suit as u64) * 15 + (self.rank as u64)).cmp(&(((other.suit as u64)* 15) + (other.rank as u64)))
81    }
82}
83
84impl PartialOrd for Card {
85    fn partial_cmp(&self, other: &Card) -> Option<Ordering> {
86        Some(((self.suit as u64) * 15 + (self.rank as u64)).cmp(&(((other.suit as u64)* 15) + (other.rank as u64))))
87    }
88}
89
90
91
92
93/// Given four cards and a starting card, returns the winner of a trick.
94/// 
95/// The rules used to determine the winner of a trick are as follows: 
96/// * Spades trump all other suits
97/// * The suit the first player (given by index) plays sets the suit of the trick
98/// * The highest ranking spades card or card of suit of first player's card wins the trick.
99pub fn get_trick_winner(index: usize, others: &[Card ; 4]) -> usize {
100    let mut winning_index = index;
101    let mut max_card = &others[index];
102
103    for i in 0..4 {
104        let other = &others[i];
105        if other.suit == max_card.suit {
106            if other.rank as u8  > max_card.rank as u8 {
107                max_card = &other;
108                winning_index = i;
109            }
110        } else if other.suit == Suit::Spade {
111            max_card = &other;
112            winning_index = i;
113        }
114    }
115    return winning_index;
116}
117
118
119
120/// Returns a shuffled deck of [`deck::Card`](struct.Card.html)'s, with 52 elements.
121pub fn new_deck() -> Vec<Card> {
122    let ranks: Vec<Rank> = vec![
123        Rank::Two,
124        Rank::Three,
125        Rank::Four,
126        Rank::Five,
127        Rank::Six,
128        Rank::Seven,
129        Rank::Eight,
130        Rank::Nine,
131        Rank::Ten,
132        Rank::Jack,
133        Rank::Queen,
134        Rank::King,
135        Rank::Ace
136    ];
137    let suits: Vec<Suit> = vec![
138        Suit::Club,
139        Suit::Diamond,
140        Suit::Heart,
141        Suit::Spade,
142    ];
143
144    let mut cards = Vec::new();
145    for s in &suits {
146        for r in &ranks {
147            cards.push(Card {suit:s.clone(), rank:r.clone()});
148        }
149    }
150    shuffle(&mut cards);
151
152    return cards;
153}
154
155/// Returns an array of `Blank` suited and ranked cards.
156pub fn new_pot() -> [Card; 4] {
157    [
158        Card { suit: Suit::Blank, rank: Rank::Blank}, 
159        Card { suit: Suit::Blank, rank: Rank::Blank},
160        Card { suit: Suit::Blank, rank: Rank::Blank},
161        Card { suit: Suit::Blank, rank: Rank::Blank}
162    ]
163}
164
165/// Shuffles a `Vector` of cards in place, see [`rand::seq::SliceRandom::shuffle`](https://docs.rs/rand/latest/rand/seq/trait.SliceRandom.html#tymethod.shuffle).
166pub fn shuffle(cards: &mut Vec<Card>) {
167    let mut rng = thread_rng();
168    cards.shuffle(&mut rng);
169}
170
171/// Used to reshuffle a deck of cards, panics if the `cards` does not have 52 elements (should only be used on a "full" deck).
172pub fn deal_four_players(cards: &mut Vec<Card>) -> Vec<Vec<Card>> {
173    assert_eq!(cards.len(), 52);
174    shuffle(cards);
175    let mut hands = vec![vec![], vec![], vec![], vec![]];
176
177    let mut i = 0;
178    while cards.len() > 0 {
179        hands[i].push(cards.pop().unwrap());
180        i = (i + 1) % 4;
181    }
182
183    return hands;
184}
185