| | |
Card Games
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
•
•
Join Date: Jun 2008
Posts: 182
Reputation:
Solved Threads: 18
Hi all there.
Given the huge amount of blackjack/card games threads and me being personally interested in poker and other games, I was feeling like starting to play with a few useful (at least I hope so) classes for dealing (no pun intended
) with card games.
I started my work on the paper first and I thought to write the following classes:
1 - A card class;
2 - A deck class containing all the (used) cards in the deck and functions such as deal, shuffle, etc.
3 - A hand class containing a variable set of cards (a deck object can deal hand objects) and a member value that can be accessed to give a score to the hand (for example in a poker game an unlucky hand containing only an Ace (high card) could have the value of 1, in a blackjack game the hand [A, J] will have the value of 21 etc.)
4 - A player class that contains a hand and a score (i.e. the money)
5 - A game class that contains a set of players, a deck and some functions implementing the rules.
Is that approach acceptable in your opinion? Do you have any criticism / suggestions? As always any hint is welcomed.
Please note that this thread is NOT urgent
it's not homework of any sort.
here's what I did so far (could be useful for some of the threads I read throughout the forum).
Thanks for your consideration and sorry for the long post
P.S.
In case you wonder, the prefix "french" is there because I'm developing also the "italian" equivalents of these classes (different cards, different decks ... definitely different games to play with
)
Given the huge amount of blackjack/card games threads and me being personally interested in poker and other games, I was feeling like starting to play with a few useful (at least I hope so) classes for dealing (no pun intended
) with card games.I started my work on the paper first and I thought to write the following classes:
1 - A card class;
2 - A deck class containing all the (used) cards in the deck and functions such as deal, shuffle, etc.
3 - A hand class containing a variable set of cards (a deck object can deal hand objects) and a member value that can be accessed to give a score to the hand (for example in a poker game an unlucky hand containing only an Ace (high card) could have the value of 1, in a blackjack game the hand [A, J] will have the value of 21 etc.)
4 - A player class that contains a hand and a score (i.e. the money)
5 - A game class that contains a set of players, a deck and some functions implementing the rules.
Is that approach acceptable in your opinion? Do you have any criticism / suggestions? As always any hint is welcomed.
Please note that this thread is NOT urgent
it's not homework of any sort.here's what I did so far (could be useful for some of the threads I read throughout the forum).
•
•
•
•
playingcards.h
c++ Syntax (Toggle Plain Text)
#include <vector> #include <string> #include <iostream> #include <algorithm> #include <stdexcept> #include <time.h> #ifndef H_PLAYINGCARDS #define H_PLAYINGCARDS enum frenchValue { ACE = 1, TWO = 2, THREE = 3, FOUR = 4, FIVE = 5, SIX = 6, SEVEN = 7, EIGHT = 8, NINE = 9, TEN = 10, JACK = 11, QUEEN = 12, KING = 13 }; enum frenchSuit { HEARTS = 1, DIAMONDS = 2, CLUBS = 3, SPADES = 4 }; class frenchCard; class frenchDeck; class emptyDeckException; std::ostream& operator<<(std::ostream& lhs, frenchCard& obj); std::ostream& operator<<(std::ostream& lhs, frenchDeck& obj); bool frenchSuitCompare(frenchCard op1, frenchCard op2); bool frenchValueCompare(frenchCard op1, frenchCard op2); class frenchCard { public: frenchCard(frenchValue v, frenchSuit s); friend std::ostream& operator<<(std::ostream& lhs, frenchCard& obj); friend bool frenchSuitCompare(frenchCard op1, frenchCard op2); friend bool frenchValueCompare(frenchCard op1, frenchCard op2); const static std::string strValues[13]; const static std::string strSuits[4]; frenchSuit getSuit() { return suit; } frenchValue getValue() { return value; } friend class frenchDeck; friend class frenchHand; friend class frenchPlayer; friend class frenchGame; private: frenchSuit suit; frenchValue value; }; class frenchDeck { public: frenchDeck(); virtual void build(); void shuffle(); void reinsert(); void discard(std::vector<frenchCard> ds); std::vector<frenchCard> deal(int nC); friend std::ostream& operator<<(std::ostream& lhs, frenchDeck& obj); protected: std::vector<frenchCard> deck; std::vector<frenchCard> discarded; int numCards; int position; }; class emptyDeckException : public std::runtime_error { public: emptyDeckException() : std::runtime_error("the deck is empty") { }; }; #endif // H_PLAYINGCARDS
•
•
•
•
playingcards.cpp
c++ Syntax (Toggle Plain Text)
#include "playingcards.h" bool frenchSuitCompare(frenchCard op1, frenchCard op2) { return (op1.suit < op2.suit) ? true : false; } bool frenchValueCompare(frenchCard op1, frenchCard op2) { return (op1.value < op2.value) ? true : false; } const std::string frenchCard::strValues[13] = { "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" }; const std::string frenchCard::strSuits[4] = { "Hearts", "Diamonds", "Clubs", "Spades" }; frenchCard::frenchCard(frenchValue v, frenchSuit s) { value = v; suit = s; } std::ostream& operator<<(std::ostream& lhs, frenchCard& obj) { lhs << obj.strValues[obj.value - 1] << " of " << obj.strSuits[obj.suit - 1]; return lhs; } void frenchDeck::build() { numCards = 52; position = 0; for(int i = 1; i <= 4; i++) { for(int j = 1; j <= 13; j++) { frenchSuit s = (frenchSuit) i; frenchValue v = (frenchValue) j; deck.push_back(frenchCard(v, s)); } } } frenchDeck::frenchDeck() { build(); } void frenchDeck::shuffle() { deck.clear(); build(); srand((unsigned)time(NULL)); std::random_shuffle(deck.begin(), deck.end()); } void frenchDeck::discard(std::vector<frenchCard> ds) { for(unsigned int i = 0; i < ds.size(); i++) { discarded.push_back(ds[i]); } } void frenchDeck::reinsert() { for(unsigned int i = 0; i < discarded.size(); i++) { deck.push_back(discarded[i]); } numCards += discarded.size(); discarded.clear(); srand((unsigned)time(NULL)); std::random_shuffle(deck.begin()+position, deck.end()); } std::vector<frenchCard> frenchDeck::deal(int nC) { std::vector<frenchCard> hand; if(numCards-position<nC) { if(discarded.empty()) { throw emptyDeckException(); } else { reinsert(); return deal(nC); } } for(int i = position; i < (position + nC); i++) { hand.push_back(deck[i]); } position += nC; return hand; } std::ostream& operator<<(std::ostream& lhs, frenchDeck& obj) { for(int i = obj.position; i < obj.numCards; i++) { lhs << obj.deck[i] << std::endl; } return lhs; }
•
•
•
•
hand.h
c++ Syntax (Toggle Plain Text)
#include "playingcards.h" #ifndef H_HAND #define H_HAND class frenchHand; class frenchHand { public: frenchHand(); frenchHand(std::vector<frenchCard> h); std::vector<frenchCard> operator=(std::vector<frenchCard> h); void setValue(int value) { handValue = value; } void sortByValue(); void sortBySuit(); int getValue() { return handValue; } int getNumCards() { return numCards; } frenchCard& operator[](int index) { return hand[index]; } std::vector<frenchCard> operator*() { return hand; } protected: std::vector<frenchCard> hand; int numCards; int handValue; }; #endif // H_HAND
•
•
•
•
hand.cpp
c++ Syntax (Toggle Plain Text)
#include "hand.h" frenchHand::frenchHand() { handValue = 0; } frenchHand::frenchHand(std::vector<frenchCard> h) { hand = h; numCards = h.size(); handValue = 0; } std::vector<frenchCard> frenchHand::operator=(std::vector<frenchCard> h) { hand = h; numCards = h.size(); handValue = 0; return h; } void frenchHand::sortBySuit() { std::sort(hand.begin(), hand.end(), frenchSuitCompare); } void frenchHand::sortByValue() { std::sort(hand.begin(), hand.end(), frenchValueCompare); }
•
•
•
•
a little testfile.cpp
c++ Syntax (Toggle Plain Text)
#include "playingcards.h" #include "hand.h" #include <iostream> using namespace std; int main(int argc, char *argv[]) { frenchDeck myDeck; myDeck.shuffle(); frenchHand myHand; myHand = myDeck.deal(5); cout << "RAW HAND:" << endl; for(int i = 0; i < myHand.getNumCards(); i++) { cout << " " << myHand[i] << endl; } myHand.sortBySuit(); cout << "HAND SORTED BY SUIT:" << endl; for(int i = 0; i < myHand.getNumCards(); i++) { cout << " " << myHand[i] << endl; } myHand.sortByValue(); cout << "HAND SORTED BY VALUE:" << endl; for(int i = 0; i < myHand.getNumCards(); i++) { cout << " " << myHand[i] << endl; } return EXIT_SUCCESS; }
Thanks for your consideration and sorry for the long post

P.S.
In case you wonder, the prefix "french" is there because I'm developing also the "italian" equivalents of these classes (different cards, different decks ... definitely different games to play with
) •
•
Join Date: Jan 2008
Posts: 3,813
Reputation:
Solved Threads: 501
There is no "right" and "wrong" in these types of designs, but rather "pros" and "cons". You are trying to write some generic classes so that you don't have to rewrite everything for each different game, which is good. At some point, the games get so dissimilar that it's no longer worth generalizing (i.e. the game of War might be so different from 7-card stud that it may be better to write them separately, whereas 5-card stud and 7-card stud are sufficiently similar to use most of the same underlying code). Where that cutoff is when you have to write different underlying classes is not always an easily defined line.
I don't know exactly what you are going for, but this may be a job for polymorphism, particularly on something like the card, deck, and game classes. Your mention of "Italian" versus "French" is a perfect example. The rules of 5-card stud will be the same in either, but you would want to change the "enum" values of both (i.e. "King" in French English, Italian, etc.). You have a "frenchHand" class. Maybe you should have a "hand" class and have "italianHand" and "frenchHand" be derived classes. Similarly when you get to implementing the different games, have a "Poker" class, then derived classes like "Stud" and "Draw" and then "5-card stud" and "7-card stud" deriving from "Stud".
If it were my design, I would pick about ten games, decide how they are similar and different, and derive my classes/design from that.
I don't know exactly what you are going for, but this may be a job for polymorphism, particularly on something like the card, deck, and game classes. Your mention of "Italian" versus "French" is a perfect example. The rules of 5-card stud will be the same in either, but you would want to change the "enum" values of both (i.e. "King" in French English, Italian, etc.). You have a "frenchHand" class. Maybe you should have a "hand" class and have "italianHand" and "frenchHand" be derived classes. Similarly when you get to implementing the different games, have a "Poker" class, then derived classes like "Stud" and "Draw" and then "5-card stud" and "7-card stud" deriving from "Stud".
If it were my design, I would pick about ten games, decide how they are similar and different, and derive my classes/design from that.
•
•
Join Date: Jun 2008
Posts: 182
Reputation:
Solved Threads: 18
•
•
•
•
I'd put the deal protocol in the game section as not all card games are dealt the same way.
@VernonDozier: Thank you too for the advices.
My short-term goal would be to make a Poker game - not that I'd like to play it more than others already existing, I want to do it mainly in the attempt of teaching myself something in the process. I like the subject and this seems a good exercise to me.
I'd like (long-term goal) to write a few games (some similar, some others not quite) for the same purpose: learn something.
I thought that I'd like to reuse as much code as it would be possible, so I'm walking this way and I'll keep you informed of any significant progress. Anything is welcomed as usual, many opinions feed the growing mind it's said

Thank you again for the advices, I liked particularly that one of making frenchHand a derived class of a general hand class.
•
•
Join Date: Jun 2008
Posts: 182
Reputation:
Solved Threads: 18
Ok, 11 days have passed and though busy with many other things I brought this some steps further.
I restructured slightly the whole design - basically now all the classes are enough abstract to deal with card games (exception: build method in deck class, but it could be overriden), or at least I hope so.
I confined the specialization in a pokerGame class that'll handle the actual game action.
As of now I'm stuck - there's probably a stupid reason to that but I can't see it. I find it difficult to manage this project because it's bigger than the other things I attempted ^^"
I was trying to write a deal and a showdown functions in the pokerGame class to test the mechanism of dealing cards to every player. Unexpectedly what caused me troubles was the showdown function.
If I uncomment that line it gives me segmentation fault when executing. I am using Code::Blocks and I have tried the debugger and though not being confident with it could have caused some misunderstanding I really can't see any problem there. Perhaps I'm just trying something still beyond my reach and I can't even use the debugger properly
The program is too long to post it here - I am going to post just a few extracts and attach an archive with the whole thing.
these are the other pieces of code that I think may be connected with the problem:
Well I think that's all... if I forgot something important please ask.
This is not homework and I'm not in a hurry but any hint would be much appreciated anyway
Meanwhile, thank you very much for your time if you read all this mess
P.S.
I tried to make the code readable and understandable but any criticism in that regard would be greatly appreciated too!
I restructured slightly the whole design - basically now all the classes are enough abstract to deal with card games (exception: build method in deck class, but it could be overriden), or at least I hope so.
I confined the specialization in a pokerGame class that'll handle the actual game action.
As of now I'm stuck - there's probably a stupid reason to that but I can't see it. I find it difficult to manage this project because it's bigger than the other things I attempted ^^"
I was trying to write a deal and a showdown functions in the pokerGame class to test the mechanism of dealing cards to every player. Unexpectedly what caused me troubles was the showdown function.
c++ Syntax (Toggle Plain Text)
// game.cpp void pokerGame::showdown() { for(unsigned int i = 0; i < m_players.size(); ++i) { if(m_players[i].getHand().getSize()!=0) { std::cout << m_players[i].getName() << "'s hand: "; std::cout /*<< m_players[i].getHand()*/ << std::endl; } } return; }
If I uncomment that line it gives me segmentation fault when executing. I am using Code::Blocks and I have tried the debugger and though not being confident with it could have caused some misunderstanding I really can't see any problem there. Perhaps I'm just trying something still beyond my reach and I can't even use the debugger properly

The program is too long to post it here - I am going to post just a few extracts and attach an archive with the whole thing.
c++ Syntax (Toggle Plain Text)
/* this is the main program (if you download the file, the commented part not present here is another (previous) test that works fine */ #include "card.h" #include "hand.h" #include "deck.h" #include "game.h" int main() { std::vector<std::string> names; names.push_back("Ludovico"); names.push_back("Cpu"); std::vector<bool> areCpu; areCpu.push_back(false); areCpu.push_back(true); std::vector<float> initialScores; initialScores.push_back(4000.0); initialScores.push_back(4000.0); pokerGame myGame(names, areCpu, initialScores); myGame.deal(); myGame.showdown(); return EXIT_SUCCESS; }
these are the other pieces of code that I think may be connected with the problem:
c++ Syntax (Toggle Plain Text)
// pokerGame class declaration class pokerGame { public: pokerGame(std::vector<std::string> names, std::vector<bool> areCpu, std::vector<float> initialScores); void deal(); void showdown(); std::vector<player> getPlayers() { return m_players; } deck getDeck() { return m_deck; } int getNumPlayers() { return m_numPlayers; } protected: value m_minInDeck; std::vector<player> m_players; deck m_deck; int m_numPlayers; unsigned int m_dealer; // position of the dealer relative to m_players vector };
c++ Syntax (Toggle Plain Text)
// pokerGame class constructor and deal function pokerGame::pokerGame(std::vector<std::string> names, std::vector<bool> areCpu, std::vector<float> initialScores) : m_deck(names.size()) { m_numPlayers = names.size(); m_minInDeck = (value) (11 - m_numPlayers); unsigned int handsize = 5; for(int i = 0; i < m_numPlayers; ++i) { m_players.push_back(player(handsize, initialScores[i], names[i], areCpu[i])); } srand((unsigned)time(NULL)); m_dealer = rand() % m_numPlayers; } void pokerGame::deal() { m_deck.build(); m_deck.shuffle(); for(int j = 0; j < 5; ++j) { for(unsigned int i = 0; i < m_players.size(); ++i) { m_players[(i+m_dealer+1)%m_numPlayers].deal(m_deck.deal()); std::cout << "dealing to " << m_players[(i+m_dealer+1)%m_numPlayers].getName() << std::endl; } } return; }
c++ Syntax (Toggle Plain Text)
// player class declaration class player { public: player(unsigned int handsize, float initialScore = 0., std::string name = "Player", bool isCpu = false); bool deal(card c) { return m_hand.deal(c); } hand& getHand() { return m_hand; } float getScore() { return m_score; } std::string getName() { return m_name; } bool isCpu() { return m_isCpu; } protected: unsigned int m_handsize; hand m_hand; bool m_isCpu; float m_score; // it's money in poker, could be anything in other games std::string m_name; };
Well I think that's all... if I forgot something important please ask.
This is not homework and I'm not in a hurry but any hint would be much appreciated anyway

Meanwhile, thank you very much for your time if you read all this mess

P.S.
I tried to make the code readable and understandable but any criticism in that regard would be greatly appreciated too!
•
•
Join Date: May 2008
Posts: 538
Reputation:
Solved Threads: 86
I took the zip file and made a MS project around it.
I had to add
I then uncommented your troublesome line:
It runs ok, but the output is strange:
I think the problem is here:
I had to add
#include <algorithm> to hand.cpp but other than that it compiled.I then uncommented your troublesome line:
c++ Syntax (Toggle Plain Text)
void pokerGame::showdown() { for(unsigned int i = 0; i < m_players.size(); ++i) { if(m_players[i].getHand().getSize()!=0) { std::cout << m_players[i].getName() << "'s hand: "; std::cout << m_players[i].getHand() << std::endl; } } return; } void pokerGame::showdown() { for(unsigned int i = 0; i < m_players.size(); ++i) { if(m_players[i].getHand().getSize()!=0) { std::cout << m_players[i].getName() << "'s hand: "; std::cout << m_players[i].getHand() << std::endl; } } return; }
It runs ok, but the output is strange:
C++ Syntax (Toggle Plain Text)
dealing to Ludovico dealing to Cpu dealing to Ludovico dealing to Cpu dealing to Ludovico dealing to Cpu dealing to Ludovico dealing to Cpu dealing to Ludovico dealing to Cpu Ludovico's hand: Ace of Nine, Two of Spades, Four of Five, Three of Six, Four of Six Cpu's hand: Ace of Ace, Ace of Five, Two of Four, Ace of Six, Two of Seven
I think the problem is here:
c++ Syntax (Toggle Plain Text)
void deck::build(int numPlayers) { m_discarded.clear(); m_dealt.clear(); m_deck.clear(); if(numPlayers == 0) { for(int i = 1; i <= 4; ++i) { for(int j = 1; j <= 13; ++j) { // -- a card expects value , suit which is what we say we're passing // -- but j is 1-13 and i is 1-4 m_deck.push_back(card((value) i, (suit) j)); } } return; } for(int i = 1; i <= 4; ++i) { m_deck.push_back(card((value) 1, (suit) i)); for(int j = 11 - numPlayers; j <= 13; ++j) { m_deck.push_back(card((value) j, (suit) i)); } } return; }
•
•
Join Date: Jun 2008
Posts: 182
Reputation:
Solved Threads: 18
You're great
that was driving me mad.
Actually there was a double error, it shouldn't have entered the if because the line
A lucky error though, because it made "me" (well, you!) discover the other, nasty error.
I still don't understand why it would caused a segfault to me while just a wrong output to you though.
Well, thank you again!
that was driving me mad. Actually there was a double error, it shouldn't have entered the if because the line
m_deck.build(); in pokerGame::deal() should have been m_deck.build(m_numPlayers); .A lucky error though, because it made "me" (well, you!) discover the other, nasty error.
I still don't understand why it would caused a segfault to me while just a wrong output to you though.
Well, thank you again!
Last edited by mrboolf; Dec 23rd, 2008 at 5:40 pm.
![]() |
Similar Threads
- nVidia Card; Games with presistant white flickering. (Monitors, Displays and Video Cards)
- Card Games Help!!!! (Java)
- Card Game Help (Java)
- Nvidia graphics card catastrophic failure (Windows NT / 2000 / XP)
- Games act weird (Troubleshooting Dead Machines)
Other Threads in the C++ Forum
- Previous Thread: Dependency line needs colon or double colon operator
- Next Thread: Help with simple classes-constructors
| Thread Tools | Search this Thread |
api array based binary c++ c/c++ calculator char char* class classes code coding compile console conversion count database delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp iamthwee ifstream input int integer java lib linkedlist linker linux list loop looping loops map math matrix memory multiple news number numbertoword output parameter pointer problem program programming project python random read recursion recursive reference return rpg sorting string strings struct temperature template templates test text text-file tree unix url variable vector video visualstudio win32 windows winsock wordfrequency wxwidgets






