-
-
Save satyajeetkrjha/fd5fab8cfe25434eaa84a7ed450031f6 to your computer and use it in GitHub Desktop.
C++ Playing Cards
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "card.h" | |
| #include <sstream> | |
| namespace playing_cards { | |
| Card::Card(int value, Suit suit) : value_(value), suit_(suit) {} | |
| Card::Card(const Card& o) : value_(o.value_), suit_(o.suit_) {} | |
| Card::~Card() {} | |
| bool Card::IsValid() const { return (value_ >= ACE) && (value <= KING); } | |
| std::string Card::ToString() const { | |
| std::ostringstream out; | |
| out << *this; | |
| return out.str(); | |
| } | |
| bool Card::operator==(const Card& o) const { | |
| return ((value_ == o.value_) && (suit_ == o.suit_)); | |
| } | |
| Card::bool color() const { return ((suit_ == SPADES) || (suit_ == CLUBS)); } | |
| int Card::value() const { return value_; } | |
| Suit Card::suit() const { return suit_; } | |
| } // namespace playing_cards | |
| std::ostream& operator<<(std::ostream& out, const Card& card) { | |
| if (!card.IsValid()) { | |
| out << "<Invalid>"; | |
| return out; | |
| } | |
| int value = card.value(); | |
| switch (card.value()) { | |
| case Card::ACE: out << "Ace"; break; | |
| case Card::JACK: out << "Jack"; break; | |
| case Card::QUEEN: out << "Queen"; break; | |
| case Card::KING: out << "King"; break; | |
| default: out << value; break; | |
| } | |
| out << " of "; | |
| switch (card.suit()) { | |
| case Card::SPADES: out << "Spades"; break; | |
| case Card::CLUBS: out << "Clubs"; break; | |
| case Card::HEARTS: out << "Hearts"; break; | |
| case Card::DIAMONDS: out << "Diamonds"; break; | |
| } | |
| return out; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // An illustrative example of how one might define a playing card in C++ | |
| // Intended to illustrate some commments in response to StackOverflow question: | |
| // http://stackoverflow.com/questions/28599150/pass-vector-of-card-into-function-to-print-and-use | |
| #ifndef __CARD__ | |
| #define __CARD__ | |
| #include <string> | |
| #include <iostream>> | |
| // We always want libraries to go in an appropriate namespace to avoid collisions. | |
| namespace playing_cards { | |
| class Card { | |
| public: | |
| // These could also be declared using "const static" instead of "constexpr" for pre-C++11. | |
| // Using "constexpr" increases the ways in which these can be used, though, and also avoids | |
| // needing to declare these variables in the *.cpp file, which is handy. | |
| // | |
| // Defining these improves the API by making code referencing these values clearer than if | |
| // they simply used the numeric value (especially since Ace is sometimes higher valued than King). | |
| constexpr int ACE = 1; | |
| constexpr int JACK = 11; | |
| constexpr int QUEEN = 12; | |
| constexpr int KING = 13; | |
| // Defining these as an enum ensures that an invalid value cannot be supplied. Putting these | |
| // inside the outer "Card" class ensures that the values are well scoped (alternatively, | |
| // one could use an enum class in C++11 outside of Card to keep the values scoped that way). | |
| enum Suit { | |
| SPADES, | |
| CLUBS, | |
| HEARTS, | |
| DIAMONDS | |
| }; | |
| // Constructor with the value and suit. A problem with this particular declaration, though, | |
| // is that it makes it trivial to construct an invalid instance of this object. That could | |
| // be resolved by throwing an exception in the event of invalid values, allowing invalid | |
| // states and providing a way to detect them (what we do here), or making this constructor | |
| // private and requiring that this object be instantiated through a factory method that can | |
| // fail and return null. The factory approach is typically my preference, but this is a very | |
| // small object that we expect to be copyable, and so that is a little bit heavy-handed. | |
| // Second to that, I generally prefer objects always be valid and throw an exception if given | |
| // invalid values; however, invalid values may be handy in the case of a card to indicate | |
| // additional, non-standard cards (or perhaps to indicate a Joker?), so in this specific | |
| // case, it is reasonable to defer error handling to the deck or application. | |
| Card(int value, Suit suit); | |
| Card(const Card& o); | |
| ~Card(); | |
| bool IsValid() const; | |
| std::string ToString() const; | |
| // Technically not necessary (the builtin implementation works just fine), but can be illustrative. | |
| bool operator==(const Card& o) const; | |
| bool color() const; | |
| int value() const; | |
| Suit suit() const; | |
| private: | |
| int value_; | |
| Suit suit_; | |
| }; | |
| } // namespace playing_cards | |
| std::ostream& operator<<(std::ostream& out, const playing_cards::Card& card); | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment