Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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.

CPP




/*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;
}


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

Java




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. */


References :

https://www.careercup.com/question?id=2983http://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

write.geeksforgeeks.org

or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.



Last Updated : 31 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads