1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
use rand::*;

use super::*;

#[test]
fn test_shuffle() {
    // This code is going create a bunch of decks and shuffle them. It will test that the cards at ends of the deck appear to be shuffled.
    let loop_count = 50;
    let mut top_matches = 0;
    let mut bottom_matches = 0;

    for _ in 0..loop_count {
        let mut d = Deck::new();
        // Get cards before shuffling
        let t1 = d.top_card().unwrap();
        let b1 = d.bottom_card().unwrap();
        // Shuffle
        d.shuffle();
        // Get end cards after shuffling
        let t2 = d.top_card().unwrap();
        let b2 = d.bottom_card().unwrap();
        // Increment if top and bottom appear to be unshuffled
        if t1 == t2 {
            top_matches += 1;
        }
        if b1 == b2 {
            bottom_matches += 1;
        }
    }

    println!(
        "top card matched {} times, bottom card matched {} times",
        top_matches, bottom_matches
    );

    // We expect shuffling of both top and bottom at least some of the iterations of the loop
    assert!(top_matches < loop_count);
    assert!(bottom_matches < loop_count);
}

/// Sorts the slice by suit then rank (low to high)
fn sort_suit_ascending_rank(cards: &mut [Card]) {
    cards.sort_by(|a, b| a.cmp_suit_then_rank(b));
}

/// Sorts the slice by rank(high to low) and then suit
fn sort_suit_descending_rank(cards: &mut [Card]) {
    // Reverse sort (since default is low to high)
    cards.sort_by(|a, b| a.cmp_suit_then_desc_rank(b));
}

/// Sorts the slice by rank(high to low) and then suit
fn sort_descending_rank_suit(cards: &mut [Card]) {
    // Reverse sort (since default is low to high)
    cards.sort_by(|a, b| a.cmp_desc_rank_then_suit(b));
}

/// Returns cards of the specified rank
pub fn cards_of_rank(cards: &[Card], rank: Rank) -> Vec<Card> {
    cards.iter().filter(|c| c.rank == rank).cloned().collect()
}

/// Returns cards of the specified suit
pub fn cards_of_suit(cards: &[Card], suit: Suit) -> Vec<Card> {
    cards.iter().filter(|c| c.suit == suit).cloned().collect()
}

/// Shuffles the slice of cards
pub fn shuffle(cards: &mut [Card]) {
    let mut rng = thread_rng();
    // Knuth shuffle
    let l = cards.len();
    for n in 0..l {
        let i = rng.gen_range(0, l - n);
        cards.swap(i, l - n - 1);
    }
}

/// Certain actions are common to a deck and a hand of cards
pub trait Cards {
    /// Return the cards as a slice
    fn cards(&self) -> &[Card];

    /// Return the cards as a mutable slice
    fn mut_cards(&mut self) -> &mut [Card];

    /// Shuffle the cards into a random order
    fn shuffle(&mut self) {
        shuffle(self.mut_cards());
    }

    /// Sort the cards by suit and then by rank (low to high)
    fn sort_suit_ascending_rank(&mut self) {
        sort_suit_ascending_rank(self.mut_cards());
    }

    /// Sorts the cards by suit and then by rank (high to low)
    fn sort_suit_descending_rank(&mut self) {
        sort_suit_descending_rank(self.mut_cards());
    }

    /// Sort the cards by rank (high to low) and then by suit
    fn sort_descending_rank_suit(&mut self) {
        sort_descending_rank_suit(self.mut_cards());
    }
}