Wednesday, March 26, 2014

Design a data structure for generic deck of cards

Problem
Design the data structures for a generic deck of cards. Explain how you would sub-class it to implement particular card games.

Solution
The structure is clear here: a

Deck contains n number of cards. So for Pocker, the Deck contains 52 cards.

A card is compose of suit and a rank. Suit can be like spade, hearts, diamond and club (in order) :
This can be treated as enum :
public enum Suit
{
    CLUBS(1),
    SPADES(2),
    HEARTS (3),
    DIAMONDS(4) ;
    
    private int suitValue;
    private Suit(int suitValue_){
     suitValue = suitValue_;
    }
}

Each card has a numerical value from 1 to 13 in the order:

So, in the above example we have shown the deck containing the card from 2 to 14 for spades.
This should also be treated as enum :
public enum Rank {
 TWO(2),
 THREE(3),
        ...
 KING(13),
 ACE(14)
}


If you think about a card game, different games differ from ways of dealing cards and putting cards back in. So we can have a set of abstract methods inside the class ‘Deck’ to allow sub-class implements its own way of dealing.

I think you can achieve what you want with a single deck class like below which is essentially a wrapper around Stack, I don't see why any particular deck/pile/hand would not want most if not all of the same methods.

The only real problem i see is with the deal() method and for that we will a Player class and a Dealer class that extends Player and implements the logic of dealing a deck


The class diagram I draw is here:
So, card will look like this:
public class Card implements Comparable<Card>{

    private Suit suit;
    private Rank rank;

 public Card(Suit suit, Rank rank) {
     this.suit = suit;
     this.rank = rank;
 }
 

 @Override
 public int compareTo(Card card2) {
  if(card2==null)
   return 1;
  
  int suit2 = card2.getSuit().getSuitValue();
  int rank2 = card2.getRank().getCardValue();
  
  if(suit.getSuitValue()!=suit2)
    return suit.getSuitValue() - suit2;
  if(rank.getCardValue() != rank2)
   return rank.getCardValue()  - rank2;
  
  return 0;
 }
}

and deck will contain cards:
class Deck {
    private Stack<Card> cards = new Stack<Card>();

    public Deck() { }

    public Deck(int numberOfCards) {
        for (int i=0; i<numberOfCards; i++) {
            cards.push(CardFactory.createCard(i));
        }
    }

    private void shuffle() {
        Collections.shuffle(this.cards);
    }

    public void sort() {
        Collections.sort(this.cards);
    }

    public void removeAllCards() {
        this.cards.removeAllElements();
    }

    public void removeCard(Card c) {
        int i = this.cards.search(c);
        this.cards.remove(i);            
    }

    public Card getCard(Card c) {
        int i = this.cards.search(c);
        return this.cards.get(i);
    }

    public Card getTopCard() {
        return this.cards.pop();
    }

    public Card getNthCard(int i) {
        return this.cards.get(i);
    }

    public Card addCard(Card c) {
        this.cards.push(c);
        return c;
    }

}

You can find the detailed classes at my github (kinshuk4). Thanks.

0 comments:

Post a Comment