Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OOP Design for Card Game Classes

What would be the best approach when designing the following classes applying design patterns?

  • Deck - addCard, deal, shuffle, getTopCard, removeTopCard, removeAllCards
  • Hand - addCard, removeCard, getCard,removeAllCards
  • DiscardPile - addCard, getTopCard, removeTopCard, removeAllCards
  • MeldPile - addCard, removeAllCards

(The MeldPile holds all the melds in the table.)

For me, I think the getTopCard and removeTopCard are just a wrapper of getCard and removeCard, as it just get the top position of a card then pass it to getCard or removeCard.

Should I use composition? strategy pattern? or just create a another class called CardPile and use it as the base class of the above class? Really appreciate if you could provide a sample code on this.

like image 601
Zack Avatar asked Feb 06 '12 12:02

Zack


People also ask

What is class design in OOP?

In object-oriented programming, a class is a blueprint for creating objects (a particular data structure), providing initial values for state (member variables or attributes), and implementations of behavior (member functions or methods).

Is OOP good for game development?

As stated earlier, OOP is helpful because it helps create maintainable code — code that is understandable, adaptable, and extendable. It also helps create reusable code by following the DRY (Don't Repeat Yourself) method: write the code once and then reuse it, rather than copying and pasting.

Which method is used to shuffle the deck and deck Pop () to deal cards into a player's hand?

We can use random. shuffle() to shuffle the deck and deck. pop() to deal cards into a player's Hand .


1 Answers

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.

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);
    }

}

The only real problem i see is with the deal() method and whether this should be the responsibility of a Deck? Personally I would not think so, this leads me to think that perhaps you would have a Player class and a Dealer class that extends Player and implements the logic of dealing a deck

class Player() {
    protected String name;
    protected Deck hand = new Deck();

    public void addCard(Card c) {
        this.hand.addCard(c);
    }

    // .....
}

class Dealer() extends Player {
    private Deck deck;

    public Dealer(int deckSize) {
        this.deck = new Deck(deckSize);
    }

    public void deal(Player[] players, int numberOfCards) {
        for (player in players) {
            for (int i=0; i<numberOfCards; i++) {
                player.addCard(this.deck.getTopCard());
            } 
        }
    }

    // .....
}
like image 131
T I Avatar answered Sep 27 '22 16:09

T I