4
\$\begingroup\$

I'm new at Rust and I'm trying to implement a cards' deck on Rust, I'm trying to use most idiomatic code I can, but since I'm new at this language, I'd like to hear advice from more experienced programmers. There's my code. (P.D: Thanks in advance! :>)

use std::fmt;

use rand::seq::SliceRandom;
use rand::thread_rng;

#[derive(PartialEq)]
pub struct Card<'a> {
    name: &'a str,
    value: i8,
    suit: char,
}

impl<'a> fmt::Debug for Card<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} of {}", self.name, self.suit)
    }
}

pub struct Deck<'a> {
    pub cards: Vec<Card<'a>>,
}

impl<'a> Deck<'a> {
    const SUITS: [char; 4] = ['♥', '♦', '♣', '♠'];
    const CARDS: [(&'a str, i8); 13] = [
        ("ACE", 11),
        ("TWO", 2),
        ("THREE", 3),
        ("FOUR", 4),
        ("FIVE", 5),
        ("SIX", 6),
        ("SEVEN", 7),
        ("EIGHT", 8),
        ("NINE", 9),
        ("TEN", 10),
        ("JACK", 10),
        ("QUEEN", 10),
        ("KING", 10),
    ];

    pub fn new() -> Deck<'a> {
        let mut deck: Vec<Card> = Vec::new();

        for suit in Deck::SUITS.iter() {
            for (card_name, card_value) in Deck::CARDS.iter() {
                deck.push(Card {
                    name: card_name,
                    value: *card_value,
                    suit: *suit,
                });
            }
        }
        let mut rng = thread_rng();
        deck.shuffle(&mut rng);

        Deck { cards: deck }
    }

    pub fn deal_card(&mut self) -> Card<'a> {
        if self.cards.is_empty() {
            self.initialize_deck()
        }
        self.cards.pop().unwrap()
    }

    pub fn get_initial_cards(&mut self) -> Vec<Card> {
        vec![self.deal_card(), self.deal_card()]
    }
    /// When the cards vector is empty, shuffle a new deck
    fn initialize_deck(&mut self) {
        *self = Deck::new();
    }
}

EDIT: This module is meaned to be used with a BlackJack game, that is the reason because the cards have those particular values

\$\endgroup\$
2
  • \$\begingroup\$ If you're only going to use a constant once, why not just inline it? That makes it clearer that it's only for a single purpose. Declaring it separately implies you're going to reuse it. And rather than storing the name on the card, it would be more memory efficient to implement a function to look up the name based on the value. \$\endgroup\$
    – Turksarama
    Aug 21, 2019 at 23:20
  • \$\begingroup\$ The constants are there because I want the user to be able to see the cards and suits that I'm using on the deck. I want them to be what in other languages you'd call static variables. About storing both name and value, you're totally right, but I think that for readibility, I'm going to delete the value, and create the function that gives the value according to the name. Thx a lot! \$\endgroup\$
    – Davichete
    Aug 22, 2019 at 7:44

1 Answer 1

2
\$\begingroup\$

You’ve made a fairly classic mistake when it comes to modeling cards in software. Cards have different values depending on the game. In some games, an Ace == 1, others 11, sometimes it could be either in the same game (Blackjack for example). Non-face cards aren’t always their value either. In some games, they’re all “5 points”, regardless of the number on the card.

In short, the value of a particular card depends on the game, not the card. How might you redesign to account for that?

\$\endgroup\$
2
  • \$\begingroup\$ Another example: in the "Belote" (a French game), both the strength and the points of a card depend on if the suit is trump or not. Before the players chose the trumps suit, the cards do not have those characteristics fixed. \$\endgroup\$
    – Boiethios
    Aug 22, 2019 at 7:09
  • \$\begingroup\$ I forgot to mention that I'm going to use this module with a BlackJack game I'm developing, that is the reason because the cards have those particular values \$\endgroup\$
    – Davichete
    Aug 22, 2019 at 7:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.