943,568 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Unsolved
  • Views: 1707
  • C++ RSS
You are currently viewing page 2 of this multi-page discussion thread; Jump to the first page
Dec 24th, 2008
1

Re: Card Games

i mean...
something like this one...
c++ Syntax (Toggle Plain Text)
  1. //... 1
  2. myGame.deal();
  3. myGame.showdown();
  4. //... 2
  5. myGame.deal();
  6. myGame.showdown();
Reputation Points: 47
Solved Threads: 69
Posting Whiz
cikara21 is offline Offline
340 posts
since Jul 2008
Dec 24th, 2008
0

Re: Card Games

I see what you mean.

I was only worried to make it work so I forgot a couple of important things:

1 - At the beginning of the pokerGame::deal() function I had to clear all players' hands, something like
c++ Syntax (Toggle Plain Text)
  1. for(int i = 0; i < m_numPlayers; ++i) {
  2. m_players[i].getHand().clear();
  3. }
otherwise the next hand won't be dealt (because theirs are already full)

2 - At the end of the pokerGame::showdown() function I had to update the m_dealer variable with m_dealer = (m_dealer + 1) % m_numPlayers;
Thanks for making me notice these.

I am currently working on making it recognize the points, I'll post the whole program zipped as soon as I'm done with this

EDIT: Being the deck random shuffling seed initialised from the clock, dealing a couple of hands without anything in between will just result in the same hands dealt to different players. This won't be a problem during a game but I thought to mention it. (I tested this inserting and removing non-portable sleep(1); between the two pokerGame::deal() calls)
Last edited by mrboolf; Dec 24th, 2008 at 8:21 am.
Reputation Points: 134
Solved Threads: 18
Junior Poster
mrboolf is offline Offline
182 posts
since Jun 2008
Dec 24th, 2008
0

Re: Card Games

aye...g luck..
Reputation Points: 47
Solved Threads: 69
Posting Whiz
cikara21 is offline Offline
340 posts
since Jul 2008
Dec 24th, 2008
0

Re: Card Games

Ok just a little upgrade:

some minor changes throughout the code and it now recognizes the hands as real poker hands.

testmain.cpp provides a little example of a 4-hand "match" (there's still to do comparison between points to decide winner...).
No action at all but it kinda works so far

I hope this'll help someone other than me, in the meantime I am much grateful for any criticism and I want to thank all of you spending time with this
Attached Files
File Type: zip pokerGame.zip (7.3 KB, 25 views)
Reputation Points: 134
Solved Threads: 18
Junior Poster
mrboolf is offline Offline
182 posts
since Jun 2008
Dec 24th, 2008
0

Re: Card Games

Please make the following changes (if you can) so I don't have to re-make them the next time I re-import your code:

Add #include <time.h> to deck.cpp and game.cpp

(You know you're only supposed to call srand() once per program run, right?)

Add #include <algorithm> to game.cpp and hand.cpp
Reputation Points: 344
Solved Threads: 116
Practically a Master Poster
Murtan is offline Offline
670 posts
since May 2008
Dec 24th, 2008
0

Re: Card Games

Ok changes made next attachment (to appear after christmas I guess) will have them.

srand() call in deck::build was there because I used deck class directly before writing pokerGame class - now it's gone as it should, thanks for noticing!
Last edited by mrboolf; Dec 24th, 2008 at 12:35 pm.
Reputation Points: 134
Solved Threads: 18
Junior Poster
mrboolf is offline Offline
182 posts
since Jun 2008
Dec 24th, 2008
0

Re: Card Games

I'm seeing an assertion (for array index out of bounds) on the last line posted below:

c++ Syntax (Toggle Plain Text)
  1. void pokerGame::showdown() {
  2. m_points.clear();
  3. m_points.reserve(m_numPlayers);
  4. for(int i = 0; i < m_numPlayers; ++i) {
  5. if(m_arePlaying[(i+m_turn)%m_numPlayers]) {
  6. m_points[(i+m_turn)%m_numPlayers] = pokerPoint(m_players[(i+m_turn)%m_numPlayers].getHand(), m_minInDeck);

The clear() gets rid of all of the elements in the vector.
You call reserve() which makes sure the array can hold that many but doesn't fill it.
You could call resize() to actually change the size of the vector, but it appears that it would require pokerPoint to have a default constructor and it doesn't have one.

What do you think about giving pokerPoint a default constructor that sets it to a non-hand (or really low hand if a non-hand isn't possible). Then instead of calling clear() and reserve(), leave the pokerPoint instances in but call a new method pokerPoint::update(hand h, value minInDeck) passing in the players hand. This new method would update the pokerPoint based on the new hand. (You could keep re-constructing them to get the points, but is there a value added to create/destroy/re-create?)

I may try to do something like that myself just to get it running again.
Reputation Points: 344
Solved Threads: 116
Practically a Master Poster
Murtan is offline Offline
670 posts
since May 2008
Dec 24th, 2008
1

Re: Card Games

ok, I did the default constructor and called resize(). The assert is gone and the program runs.

I also did a little more playing, I added a third player 'Bob' who is also a CPU (not that it really matters right now).

Here's the output from my last run:

C++ Syntax (Toggle Plain Text)
  1. ### HAND 1 ###
  2. CPU's hand: Nine of Hearts, Ten of Spades, Jack of Hearts, Queen of Spades, King of Spades
  3. Bob's hand: Ace of Spades, Eight of Spades, Jack of Diamonds, Jack of Spades, Queen of Hearts
  4. Ludovico's hand: Eight of Hearts, Nine of Diamonds, Ten of Clubs, Jack of Clubs, Queen of Clubs
  5.  
  6. CPU has Straight, King high
  7. Bob has One Pair, Jack
  8. Ludovico has Straight, Queen high
  9.  
  10. ### HAND 2 ###
  11. Bob's hand: Ace of Hearts, Eight of Diamonds, Ten of Diamonds, Jack of Clubs, King of Clubs
  12. Ludovico's hand: Eight of Clubs, Nine of Spades, Queen of Diamonds, Queen of Spades, King of Diamonds
  13. CPU's hand: Ace of Diamonds, Ace of Clubs, Nine of Diamonds, Ten of Hearts, King of Hearts
  14.  
  15. Bob has High Card, Ace
  16. Ludovico has One Pair, Queen
  17. CPU has One Pair, Ace
  18.  
  19. ### HAND 3 ###
  20. Ludovico's hand: Ace of Hearts, Ace of Diamonds, Eight of Diamonds, Jack of Diamonds, Queen of Diamonds
  21. CPU's hand: Nine of Diamonds, Ten of Spades, Jack of Spades, King of Diamonds, King of Clubs
  22. Bob's hand: Eight of Hearts, Ten of Diamonds, Jack of Hearts, Jack of Clubs, King of Hearts
  23.  
  24. Ludovico has One Pair, Ace
  25. CPU has One Pair, King
  26. Bob has One Pair, Jack
  27.  
  28. ### HAND 4 ###
  29. CPU's hand: Ace of Clubs, Eight of Diamonds, Eight of Spades, Jack of Hearts, Queen of Hearts
  30. Bob's hand: Nine of Diamonds, Ten of Hearts, Ten of Spades, Queen of Diamonds, King of Clubs
  31. Ludovico's hand: Ace of Spades, Nine of Hearts, Nine of Clubs, Nine of Spades, King of Diamonds
  32.  
  33. CPU has One Pair, Eight
  34. Bob has One Pair, Ten
  35. Ludovico has Three Of A Kind, Nine

I don't know about you, but I'd almost like to see the hands in a short form, something like this:
C++ Syntax (Toggle Plain Text)
  1. ### HAND 4 ###
  2. CPU's hand: AC, 8D, 8S, JH, QH
  3. Bob's hand: 9D, 10H, 10S, QD, KC
  4. Ludovico's hand: AS, 9H, 9C, 9S, KD
  5.  
  6. CPU has One Pair, Eight
  7. Bob has One Pair, Ten
  8. Ludovico has Three Of A Kind, Nine
  9.  

Also when I was going through fixing it so it would run again, I spent more time actually looking at the design. I have a couple of comments. First, although you can declare a lot of classes and/or methods as friends, it is generally not good design. If there is a motivating reason, go ahead, but for simple things you can avoid it.

As an example, card had 7 friends:
c++ Syntax (Toggle Plain Text)
  1. friend std::ostream& operator<<(std::ostream& lhs, card& obj);
  2. friend bool suitCompare(card op1, card op2);
  3. friend bool valueCompare(card op1, card op2);
  4. friend class deck;
  5. friend class hand;
  6. friend class player;
  7. friend class pokerGame;

almost all of those are friends so they can access the protected data members:
c++ Syntax (Toggle Plain Text)
  1. protected:
  2. suit m_suit;
  3. value m_value;

But you provided public accessors for those items, they're even inline so in theory you don't even pay the price of a call. (But you could change them later if you needed to and no-one would REALLY care.)
c++ Syntax (Toggle Plain Text)
  1. suit getSuit() { return m_suit; }
  2. value getValue() { return m_value; }

I would recommend that you re-visit all of your friend relationships to determine if they are really adding value. (I still have the pokerPoints output operator friendship, he's pretty connected, but I'm still not sure about him.)

You also have at least 2 copies of the string arrays for the card names and the suit names. (One in card and one in game.) Also when people are using the arrays, they are always doing something like strValue[foo.m_value - 1] (with the non-friendship it looks more like strValue[foo.getValue()-1] . So I added a couple of static methods to card to do the lookup (and then I hid the arrays).
c++ Syntax (Toggle Plain Text)
  1. static std::string const & valueText(value v);
  2. static std::string const & suitText(suit s);
These methods can be accessed like card::valueText(foo.getValue()) and return a constant reference to the string from the hidden array.

Speaking of constant references, const can be your friend (sometimes he's a little painful at first, but you'll come to love him too). There were several places where you're passing literal copies of objects or passing non-constant references. (If you pass a non-constant reference, the function or method you call could change the object you pass them.) It's normally good form when you're writing a method that does not need to make changes to a parameter passed by reference to make it a const reference.

A side effect of this is that when you're working with const references, you can only call methods of the object that have been marked const. So, for example, I marked card's accessors (to get the suit and the value) as const because they will not change the card. So they could be called from someone that had a const reference to a card.
c++ Syntax (Toggle Plain Text)
  1. suit getSuit() const { return m_suit; }
  2. value getValue() const { return m_value; }

The last thing (I remember) doing to card was moving the sort compare functions from being external friends to public static members of the class. (As members of the class, they get 'free' permission to access the protected data members.) Ok, so here's the class header:
c++ Syntax (Toggle Plain Text)
  1. #ifndef H_FRENCH_CARD
  2. #define H_FRENCH_CARD
  3.  
  4. #include <iostream>
  5. #include <string>
  6.  
  7. enum value { ACE = 1, TWO = 2,
  8. THREE = 3, FOUR = 4,
  9. FIVE = 5, SIX = 6,
  10. SEVEN = 7, EIGHT = 8,
  11. NINE = 9, TEN = 10,
  12. JACK = 11, QUEEN = 12,
  13. KING = 13
  14. };
  15.  
  16. enum suit { HEARTS = 1, DIAMONDS = 2, CLUBS = 3, SPADES = 4 };
  17.  
  18. class card {
  19. public:
  20. card(value v, suit s);
  21. card(const card &cpy);
  22. card & operator=(const card &op2);
  23.  
  24. static std::string const & valueText(value v);
  25. static std::string const & suitText(suit s);
  26. static bool cmpSuit(card const & x, card const & y);
  27. static bool cmpValue(card const & x, card const & y);
  28. static bool cmpValueAceHigh(card const & x, card const & y);
  29.  
  30. suit getSuit() const { return m_suit; }
  31. value getValue() const { return m_value; }
  32.  
  33. protected:
  34. suit m_suit;
  35. value m_value;
  36. };
  37.  
  38. // Helper operator to output the 'text' version of a card
  39. std::ostream& operator<<(std::ostream& lhs, card const & obj);
  40.  
  41. #endif // H_CARD

The cmpValueAceHigh() comparison function could be used in hand sorting (oh, say from pokerPoints) to sort the hand by value and to get the ace to the end of the array. It would tend to make the hand outputs a little prettier and might allow you to be more generic in some of the 'if I have an ACE' code in pokerPoints. I was thinking about it, and wrote the comparison, but I haven't really looked into using it.

Here's the source to match the header:
c++ Syntax (Toggle Plain Text)
  1. #include "card.h"
  2.  
  3. const std::string strValues[13] = { "Ace", "Two", "Three",
  4. "Four", "Five", "Six",
  5. "Seven", "Eight", "Nine",
  6. "Ten", "Jack", "Queen", "King" };
  7.  
  8. const std::string strSuits[4] = { "Hearts", "Diamonds", "Clubs", "Spades" };
  9.  
  10. std::string const & card::valueText(value v)
  11. {
  12. return strValues[static_cast<int>(v) - 1];
  13. }
  14.  
  15. std::string const & card::suitText(suit s)
  16. {
  17. return strSuits[static_cast<int>(s) - 1];
  18. }
  19.  
  20. bool card::cmpSuit(card const & x, card const & y)
  21. {
  22. return x.m_suit < y.m_suit;
  23. }
  24.  
  25. bool card::cmpValue(card const & x, card const & y)
  26. {
  27. return x.m_value < y.m_value;
  28. }
  29.  
  30. bool card::cmpValueAceHigh(card const & x, card const & y)
  31. {
  32. return x.m_value != ACE && x.m_value < y.m_value;
  33. }
  34.  
  35. card::card(value v, suit s) {
  36. m_value = v;
  37. m_suit = s;
  38. }
  39.  
  40. card::card(const card & cpy) {
  41. m_value = cpy.m_value;
  42. m_suit = cpy.m_suit;
  43. }
  44.  
  45. card & card::operator=(const card &op2) {
  46. m_value = op2.m_value;
  47. m_suit = op2.m_suit;
  48. return *this;
  49. }
  50.  
  51. std::ostream& operator<<(std::ostream& lhs, card const & obj) {
  52. lhs << card::valueText(obj.getValue()) << " of " << card::suitText(obj.getSuit());
  53. return lhs;
  54. }

note that to implement the above changes, there were ripples through almost all of the other project files. Fairly straightforward, but they were there.
Last edited by Murtan; Dec 24th, 2008 at 3:18 pm. Reason: spelling
Reputation Points: 344
Solved Threads: 116
Practically a Master Poster
Murtan is offline Offline
670 posts
since May 2008

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: Dependency line needs colon or double colon operator
Next Thread in C++ Forum Timeline: Help with simple classes-constructors





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC