Design the Data Structures(classes and objects)for a generic deck of cards

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

Solution:



First, we need to recognize that a “generic” deck of cards can mean many things. Generic could mean a standard deck of cards that can play a poker-like game, or it could even stretch to Uno or Baseball cards.

To implement particular card games

Let’s assume that the deck is a standard 52-card set like you might see used in a blackjack or poker game. If so, the design might look like this:

The structure is clear here: a deck contains four suits and a suit contains 13 card. Each card has a numerical value from 1 to 13. 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. The class diagram I draw is here:


Below is C++ implementation of the idea.

filter_none

edit
close

play_arrow

link
brightness_4
code

/*1. Investigation on an individual card instead of 
   a collection of cards, focus on a card's state 
   and interface.
2. A card game has its own specific constrain and 
   requirement on cards, such that a generic card 
   cannot satisfy a blackjack card
3. Player manage multiple cards */
  
#include <bits/stdc++.h>
using namespace std;
  
namespace SUIT {
enum Enum {
    SPADE,
    HEART,
    CLUB,
    DIAMOND
};
};
  
class Card {
private:
    SUIT::Enum s;
    int v;
  
public:
    virtual SUIT::Enum suit() const
    {
        return s;
    };
  
    virtual int val() const
    {
        return v;
    };
  
    Card(int val, SUIT::Enum suit)
        : s(suit), v(val){};
};
  
class BlackJackCard : public Card {
public:
    virtual int val()
    {
        int v = Card::val();
        if (v < 10)
            return v;
        return 10;
    }
  
    BlackJackCard(int val, SUIT::Enum suit)
        : Card(val, suit){};
};
  
class player {
private:
    int id;
    int bet;
    set<int> points;
    vector<BlackJackCard*> bjcs;
    bool addPoint(set<int>& amp; points, BlackJackCard * card)
    {
        if (points.empty()) {
            points.insert(card->val());
            if (card->val() == 1)
                points.insert(11);
        } else {
  
            /* Set elements are ALWAYS CONST, they can't
               be modified once inserted. */
            set<int> tmp;
            for (auto it = points.begin(); it != points.end(); ++it) {
                tmp.insert(*it + card->val());
                if (card->val() == 1)
                    tmp.insert(*it + 11);
            }
            points = tmp;
        }
    }
  
    void getPoints()
    {
        cout << "You All Possible Points : " << endl;
        for (auto it = points.begin(); it != points.end(); ++it) {
            cout << *it << endl;
        }
    };
  
    int getMinPoints()
    {
        /* set is implemented by commonly BST, so else 
          are in order!!!
          learn to use lower_bound() and upper_bound()
          "they allow the direct iteration on subsets 
           based on their order."
          which gives us another option to find min. preferable */
  
        // return *(points.lower_bound(0));
        return *(points.begin());
    };
  
    void printCards()
    {
        cout << "You Cards : " << endl;
        for (auto it = bjcs.begin(); it != bjcs.end(); ++it) {
            cout << (*it)->val() << endl;
        }
    }
  
public:
    player(int i, int j)
        : id(i), bet(j)
    {
        bjcs.push_back(new BlackJackCard(rand() % 13 + 1, SUIT::SPADE));
        bjcs.push_back(new BlackJackCard(rand() % 13 + 1, SUIT::SPADE));
        addPoint(points, bjcs[0]);
        addPoint(points, bjcs[1]);
    };
  
    void getAnotherCard()
    {
        for (set<int>::iterator it = points.begin(); it != points.end(); ++it) {
           
            /* predefined strategy for the player    */
            if (*it <= 21 && 21 - *it <= 4) {
                printCards();
                getPoints();
                cout << "Stand" << endl;
                exit(1);
            }
        }
        bjcs.push_back(new BlackJackCard(rand() % 13 + 1, SUIT::SPADE));
        addPoint(points, bjcs.back());
        if (getMinPoints() > 21) {
            printCards();
            getPoints();
            cout << "Busted" << endl;
            exit(2);
        }
    };
  
    virtual ~player()
    {
        for (auto it = bjcs.begin(); it != bjcs.end(); ++it) {
            delete *it;
        }
    };
};
// Driver code
int main()
{
    srand(time(NULL));
    player p(1, 1000);
    p.getAnotherCard();
    p.getAnotherCard();
    p.getAnotherCard();
  
    return 0;
}

chevron_right


Output:

You Cards : 
10
10
You All Possible Points : 
20
Stand

To implement Blackjack.

Note: Now, let’s say we’re building a blackjack game, so we need to know the value of the cards. Face cards are 10 and an ace is 11 (most of the time, but that’s the job of the Hand class, not the following class).

At the start of a blackjack game, the players and the dealer receive two cards each. The players’ cards are normally dealt face up, while the dealer has one face down (called the hole card) and one face up.

The best possible blackjack hand is an opening deal of an ace with any ten-point card. This is called a “blackjack”, or a natural 21, and the player holding this automatically wins unless the dealer also has a blackjack. If a player and the dealer each have a blackjack, the result is a push for that player. If the dealer has a blackjack, all players not holding a blackjack lose.


Blackjack

Main logic of Blackjack in Java

filter_none

edit
close

play_arrow

link
brightness_4
code

public class BlackJackHand extends Hand<BlackJackCard> {
  
    /* There are multiple possible scores for a blackjack 
   hand, since aces have 3 * multiple values. Return 
   the highest possible score that's under 21, or the
   4 * lowest score that's over. */
  
    public int score()
    {
        Arraylist<Integer> scores = possibleScores();
        int maxUnder = Integer.MIN_VALUE;
        int minOver = Integer.MAX_VALUE;
        for (int score : scores) {
            if (score > 21 & amp; &score < minOver) {
                minOver = score;
            } else if (score <= 21 & amp; &score > maxUnder) {
                maxUnder = score;
            }
        }
        return maxUnder Integer.MIN_VALUE ? minOver maxUnder;
    }
  
    /* return a list of all possible scores this hand could have 
     (evaluating each * ace as both 1 and 11 */
    private Arraylist<Integer> possibleScores() { ... }
  
    public boolean busted() { return score() > 21; }
    public boolean is21() { return score() == 21; }
    public boolean isBlackJack() { ... }
}
  
public class BlackJackCard extends Card {
    public BlackJackCard(int c, Suit s) { super(c, s); }
    public int value()
    {
        if (isAce())
            return 1;
        else if (faceValue >= 11 & amp; &faceValue <= 13)
            return 10;
        else
            return faceValue;
    }
  
    public int minValue()
    {
        if (isAce())
            return 1;
        else
            return value();
    }
  
    public int maxValue()
    {
        if (isAce())
            return 11;
        else
            return value();
    }
  
    public boolean isAce()
    {
        return faceValue == 1;
    }
  
    public boolean isFaceCard()
    {
        return faceValue >= 11 & amp;
        &faceValue <= 13;
    }
}
  
/* This is just one way of handling aces. We could, alternatively, create a class
of type Ace that extends BlackJackCard. */

chevron_right


References :
https://www.careercup.com/question?id=2983
http://stackoverflow.com/questions/37363008/a-singleton-class-to-design-a-generic-deck-of-card

This article is contributed by Mr. Somesh Awasthi. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.



My Personal Notes arrow_drop_up

Improved By : AnamikaPandey2