?
Solved

A card game

Posted on 2005-03-06
34
Medium Priority
?
579 Views
Last Modified: 2012-06-27
Hello, I'm trying to learn how to make simply games with C++. With that in mind I want to manipulate cards i.e intial a deck of cards, shuffle a deck of cards, deal a deck of cards. I want to start with the basics. :)

Intialing a array for 52 deck of cards is easy

Ex:
contst int arraySize = 4;
char cards[arraySize] = {C2, D2, H2, S2}
 // these are the different suits in cards clover, diamond, heart, spade

Now of course I will have an array with all the suits but this is just an example. Now All I want to do right now is print out the intial deck, shuffle the cards so they are in different array indexes, and deal the cards to one player each thus having with this example four players. Once that is done then print out the cards that each player has.

Now I have been thinking of the best way to do this and seems that I will need an array for the intial cards and then an array for all four players as well. I want to do these actions within seperate functions so intialing the deck, shuffle, deal and print out four players deck with be sperate functions. Keep it clean and all. Is this a pratical way of thinking of this problem and also what would be the best if not better way of doing this?
0
Comment
Question by:DancingFighterG
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 16
  • 10
  • 7
34 Comments
 
LVL 8

Expert Comment

by:fatalXception
ID: 13472108
OK, if you are working in C++, you can use classes for this.
It will make it nice and organised.

I wrote a couple of card games way back in Uni, and developed several card "classes" along with a Deck class. Here's the file contents, feel free to use them.
Note: before I post these, to anyone who might have reservations about this, I'm only posting "complete" code because this is the first time in all my time spent on EE that I actually had a ready made answer, so I'm gonna use it.

First up is CCard.h, which represents one physical card:
/*
CCard.h - definition of the CCard class which is used to represent a single card
in the blackjack game
*/

#include <string>
using namespace std;

class CCard
{
public:
      //constructor and destructor
      CCard();
      //overidden constructor used when creating the deck.
      CCard(int suit,int value);
      ~CCard();

//public methods of the CCard class
//get_suit returns a string object with the suit's name e.g "Hearts"
      string get_suit();
//get_name returns a string object with the card's name e.g "King"
      string get_name();
//get_value returns a the value of the card. e.g 10
      int get_value();
//DEBUG ONLY
      void print();
private:
      int p_suit;                  //the suit of the card
      int p_value;            //the value of the card ace-king.

};
Next is CCard.cpp:

/*
CCard.cpp - main source file for the CCard class implementation
*/

#include <string>
#include <iostream>
using namespace std;


#include "CCard.h"
/*
The following data is private to the CCard module.
Rather than storing all the string names for the car suits and values
in the actual objects (which is wasteful of resources) we just store them
privately in the module
*/


char* suits[4] = {"Hearts","Diamonds","Clubs","Spades"};
char* names[13] = {"Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"};

//private function prototypes
string get_suitName(int suit);
string get_cardName(int value);
/*
end of private segment
*/

CCard::CCard()
{
      //default constructor
}

CCard::CCard(int suit, int value)
{
      //set the suit and value of the card.
      if (suit <0 || suit >3)
      {
            return;
      }
      if (value<0 || value >13)
      {
            return;
      }
      p_suit = suit;      
      p_value = value;
}

CCard::~CCard()
{
      //nothing to destroy here.
}

int CCard::get_value()
{
      
      return p_value+1;
}


string CCard::get_suit()
{
      //return a string name for the suit
      return get_suitName(p_suit);
}

string CCard::get_name()
{
      //return a name for the card value
      return get_cardName(p_value);

}

/*
These are a private functions in the CCard module, which return
the suit name and card name (eg Ace, Two, etc) for a given integer value
*/

string get_suitName(int suit)
{
      string suitName;
      //if an invalid suit, return invalid
      if (suit <0|| suit >3)
      {
            return "unknown";
      }
      //otherwise, return the string from the suits[] array of char*
      //remember to subtract 1 because the array is zero based!
      return suits[suit];

}

string get_cardName(int value)
{
      string cardName;
      //if inavlid value, return invalid
      if (value<0 || value>13)
      {
            return "unknown";
      }
      //otherwise return the string from the names[] array of char*
      //remember to subtract 1 because the array is zero based!
      return names[value];
}


//DEBUG ONLY
void CCard::print()
{
      cout <<"\n"<<get_name()<<" of "<<get_suit();
      cout <<"Value : "<<p_value;
      
}

Next is CDeck, which represents a Deck of cards. It has member functions to shuffle and deal cards:

/*
CDeck.h - definition of the CDeck class
which represents a deck of 52 cards.
The class has functions to shuffle the deck, deal out a card, etc.
It contains an array of 52 CCard object pointers which are dynamically created in the constructor
*/
#include "CCard.h"

class CDeck
{
public:      
//constructor / destructor
      CDeck();
      ~CDeck();
//methods of the deck
//function to shuffle the deck.
      void shuffle_deck();
//function to deal a card from the deck
      CCard* deal();
//function to check if the deck is empty
      bool is_empty();
//DEBUG ONLY
//function to dump all of the cards.
      void dump();
private:
//array of 52 CCard object pointers which represents the physical deck.
      CCard* p_deck[52];
//keeps track of the current card in the deck i.e the next one that will be dealt.
      int p_curCard;
//keeps track of whether or not the deck is all deal out or not.
 bool p_deckEmpty;
};

and finally Cdeck.cpp:
/*
CDeck.cpp - implementation file for the CDeck class.
*/
#include <iostream>
using namespace std;

//these two used just for random numer generation
#include <stdlib.h>
#include <time.h>

#include "CDeck.h"



CDeck::CDeck()
{
      /*when we initialise the deck, we need to create 52 separate card objects
      (we are not using jokers) and initialise each of them to be a unique
      card from each of the four suits.
      */
      //set the current card = 0;
      p_curCard = 0;
      for (int suit=0;suit<4;suit++)
      {
            for (int value=0;value<13;value++)
            {
                  /*create a new card object with the corresponding suit/value
                  and add it to the array at the correct position*/
                  p_deck[p_curCard] = new CCard(suit,value);

                  //DEBUG ONLY
                  //p_deck[p_curCard]->print();

                  p_curCard++;
            }//end for value
      }//end for suit
      //now, shuffle the cards
      shuffle_deck();
      //reset the current card (0 represents the "top" of the deck)
      p_curCard = 0;
      p_deckEmpty = false;
}




CDeck::~CDeck()
{
      //destroy all the CCard objects
      if (p_deck)
      {
            delete[] *p_deck;
      }
}


void CDeck::shuffle_deck()
{
      /*
      shuffle the deck to ensure some kind of random order for card deals.
      The simplest way to do this is to do 100 random "swaps" by looping
      100 times, picking two numbers between 0 and 51, and swapping p_deck[a] and p_deck[b]
      */
      //initialise the random number seed
      srand ((unsigned) time(NULL));
      for (int shuffle = 0;shuffle<100;shuffle++)
      {
            //pick a number between 0 and 51
            int a = rand()%51;
            int b = rand()%51;
            //the swap (standard enough)
            CCard* temp = p_deck[a];
            p_deck[a] = p_deck[b];
            p_deck[b] = temp;
      }//end for shuffle;
}

bool CDeck::is_empty()
{
      //just return p_deckEmpty
      return p_deckEmpty;
}
CCard* CDeck::deal()
{
      //return the next card

      //move to the next card;
      //p_curCard++;
      //are we past the end of the deck?
      if (p_curCard ==51)
      {
            //we have "used up" the deck. so shuffle it again, and reset the card counter
            //p_deckEmpty = true;
            shuffle_deck();
            p_curCard = 0;
            //return 0;
      }
            return p_deck[++p_curCard];
}

//DEBUG ONLY
//dump all the cards to screen
void CDeck::dump()

{
      for (int x=0;x<52;x++)
      {
            cout <<"Suit: ";
            cout <<p_deck[x]->get_suit()<<"  ";
            cout <<"Name: ";
            cout <<p_deck[x]->get_name()<<"\n";
            //cout <<p_deck[x]->get_value()<<"\n";
      }//end for x
}

Hope this helps you (C++ gurus, feel free to take me down for any bad coding ;p)

If you are having trouble using these classes, please, feel free to post back here and I'll try to help more. Also, if you would like AND as long as nobody has any objections, I'll upload one of my old projects that uses these to an ftp server of your choice, so you can see how it works.
But as I said, ONLY if nobody objects, because in general that would get me in trouble as far as my reading of the EE policy goes.

~later
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13479408
Look at that:   http:Q_21308184.html

Regards, Alex


0
 

Author Comment

by:DancingFighterG
ID: 13487960
quick question. I'm building a main to print some other things out. What would main for this look like fatalXception so I could run this classes?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 8

Expert Comment

by:fatalXception
ID: 13488072
for example, to emulate a "hand" of five cards.
#include <string>
#include <iostream>
using namespace std;

#include "CDeck.h"

CDeck* myDeck;
CCard* myCard[5];

int  main()
{
   myDeck = new CDeck;   //create a new CDeck Object
//get five cards
 for (int x=0;x<5;x++)
   {
       myCard[x] = NULL;
       myCard[x] = myDeck->deal();
       myCard[x]->print();
}

return 0;
}

hth, if you need more info let me know, as I mentioned, I can supply some of my old projects (blackjack, etc) if you need them.
0
 

Author Comment

by:DancingFighterG
ID: 13488145
Well, for simplicity my whole goal right now is simply deal out 13 cards to four players. I also want to sort the intial deck and the hands of the players using the function bubble sort but I won't implimit that until I get this working first. It's like having a bridge card game.
0
 
LVL 8

Expert Comment

by:fatalXception
ID: 13488344
When you create the CDeck object, it is shuffled for you in the constructor.

To do what you want to do (this is the basic way)
CDeck* theDeck;
CCard* hand1[13];
CCard* hand2[13];
CCard* hand3[13];
CCard* hand4[13];

theDeck = new CDeck;
for (int x=0;x<13;x++)
{
   hand1[x] = theDeck->deal();
   hand2[x] = theDeck->deal();
   hand3[x] = theDeck->deal();
   hand4[x] = theDeck->deal();
}

each player will have a random hand of 13 cards each. At this point the CDeck will be "empty" so if you ask it to deal() again it will just reshuffle itself again. There is potentially a bug here because the player's hands would then change (as they are pointers to cards), but as I don't know any card games that use more that one deck, you would just re-deal the hands anyway.

If you are developing a game that needs to deal more than 52 cards (e.g multiple decks) then I would return copies of the cards, and not pointers, from the CDeck class.
0
 

Author Comment

by:DancingFighterG
ID: 13488349
Quesiton Fatal, where would I place a statment that would see the whole deck shuffled. I'm trying to debug and see the whole deck shuffled. Could I use that dump functions that you have? or would I simply just use a for loop in the suffle sections and print out cards 13 at a time. So for example:

D9  SJ HA C3
DQ S5
.    .
.    .
.    .
.
.
.
.
.
.
.
.
.
.
0
 

Author Comment

by:DancingFighterG
ID: 13488397
Got it, so then I would use the print function to print out the hands!
0
 
LVL 8

Expert Comment

by:fatalXception
ID: 13488415
You can use the dump function to see all the cards in the Deck.
If you'd like to see the deck unshuffled first, you will need to take out the call to shuffle_deck(); in the CDeck() constructor, and call it manually, e.g

CDeck* myDeck = new CDeck();
//show the deck
myDeck->dump();
//shuffle it
myDeck->shuffle_deck();
//show it again
myDeck->dump();

Although the deck is "sorted" before this anyway and is of dubious value in a "real" game.
0
 
LVL 8

Expert Comment

by:fatalXception
ID: 13488457
>>Got it, so then I would use the print function to print out the hands!

As we say in the West of Ireland, now you're suckin' diesel! (roughly translated, "yes")

You can just loop through the array (e.g hand1) and use print() to print each card.
you can also call the CCard's get_value() function to retrun an integer "value" of the card from 1-13, although depending on the game you might want to change this (e.g in Blackjac Ace can be 1 or 11 depending on what you already have in your hand)
0
 

Author Comment

by:DancingFighterG
ID: 13488778
Last question because I know it has to getting late there. This is a simple formatting issue. Formatting has not been my strong suit on code. How would you go about being able to print the hands and deck out in the following format:

C2   D2   H2   S2
C3   D3   H3   S3
C4   D4   H4   S4
C5   D5   H5   S5
C6   D6   H6   S6
C7   D7   H7   S7
C8   D8   H8   S8
C9   D9   H9   S9
CT   DT   HT   ST
CJ   DJ   HJ   SJ
CQ   DQ   HQ   SQ
CK   DK   HK   SK
CA   DA   HA   SA

0
 
LVL 8

Expert Comment

by:fatalXception
ID: 13493993
Modify the CCard print() function and the char* suits array to have just "C","H", etc.
Then just print the values in a loop.
OR create a separate class called CCHand which represents one hand in the game.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13494093
That sample should meet all of your requirements:

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <time.h>
using namespace std;

enum CardColor { Diamonds, Hearts, Spades, Clubs, MaxColor };
enum CardRank { Ace, King, Queen, Jack, Ten, Nine, Eight, Seven, Six, Five, Four, Three, Two, MaxRank };

const char* g_allColors[]  = { "Diamonds", "Hearts", "Spades", "Clubs", };
const char* g_allColAbbs[] = { "D", "H", "S", "C", };
const char* g_allRanks[]   = { "A ", "K ", "Q ", "J ", "10", "9 ", "8 ", "7 ", "6 ", "5 ", "4 ", "3 ", "2 " };

class PlayingCard
{
   CardColor m_cc;
   CardRank  m_cr;

public:
    PlayingCard(CardColor cc,  CardRank  cr) :  m_cc(cc), m_cr(cr) {}
    friend ostream& operator << (ostream& os, const PlayingCard& card)
    {
        os << g_allColAbbs[card.m_cc] << '-' << g_allRanks[card.m_cr];
        return os;
    }
    bool operator < (const PlayingCard& card) const
    {
        return (m_cc < card.m_cc) || (m_cc == card.m_cc && m_cr < card.m_cr);
    }
};

class Cards
{
protected:
    vector<PlayingCard> m_cards;
public:
    int size() { return m_cards.size(); }
    friend ostream& operator << (ostream& os, const Cards& cards)
    {
        for (int i = 0; i < cards.m_cards.size(); ++i)
        {
            os << cards.m_cards[i] << ' ';
            if ( (i % 4 ) == 3)
                os << endl;
        }
        return os;
    }
};

class Pack : public Cards
{
public:
     Pack()
     {
         for (CardColor i = Diamonds; i <= Clubs; i = (CardColor)(i + 1) )
             for (CardRank n = Ace; n <= Two; n = (CardRank)(n + 1) )
                 m_cards.push_back(PlayingCard(i, n));
     }
     friend class Deck;
};

class Deck : public Cards
{
public:
    Deck()
    {
        Pack pack;
        srand(time(NULL));  // seed randomizer
        for (int i = pack.m_cards.size(); i > 0; --i)
        {
            int n = rand()%i;
            m_cards.push_back( pack.m_cards[n] );
            pack.m_cards.erase( &pack.m_cards[n] );
        }
    }

    friend class Hand;
   
};

class Hand : public Cards
{
public:
    Hand() {}
    void deal(Deck& deck, int nCards)
    {
        for (int i = 0; i < nCards; ++i)
        {
            m_cards.push_back( deck.m_cards[deck.size()-1] );
            deck.m_cards.erase( &deck.m_cards[deck.size()-1] );
        }
    }

    void sort()
    {
        std::sort(m_cards.begin(), m_cards.end());
    }
   
};


int main()
{
   Deck deck;

   cout  << deck << endl;

   Hand hand1, hand2;
   hand1.deal(deck, 4);
   hand2.deal(deck, 4);
   hand1.deal(deck, 4);
   hand2.deal(deck, 4);

   cout  << deck << endl;
   cout  << hand1 << endl;
   cout  << hand2 << endl;

   hand1.sort();
   hand2.sort();

   cout  << hand1 << endl;
   cout  << hand2 << endl;

   return 0;
}

Regards, Alex
0
 

Author Comment

by:DancingFighterG
ID: 13501653
Ok, I tried to modify the print functions so that I get four rows of numbers put I'm not getting what I wanted. Here is the print function:

void BridgeCards::print()
{
     cout <<"\n"<< get_suit()  <<""<<  get_name()<< endl;
    // cout <<"Value : "<< p_value;
       cout << endl;
     
}

I ried using the value of the cards with a mod operation to see if I could just print up to thirteen cards then start a new line but that wasn't workin. Please advise!
0
 
LVL 8

Expert Comment

by:fatalXception
ID: 13504134
That print function only prints out one card at a time.
You might want to remove the last cout<<endl

And call the function from within a loop
for (int x=0;x<4;x++)
{
    hand1[x]->print();
    cout <<" ";
}
cout <<"\n";

something like that.
0
 

Author Comment

by:DancingFighterG
ID: 13532142
Ok, this is how the output looks:

DISPLAY THE FULL DECK INITIAL DECK OF CARDS
HQ
CA
S6
DJ
DK
HK
SQ
C7
D9
D5
H4
D10
C10
HA
S10
C3
CJ
C5
S9
S2
CQ
S5
H10
D8
CK
H9
H8
D2
S8
SJ
S4
C6
C8
D6
H7
C2
S7
C4
H2
DQ
C9
D7
H6
SA
S3
D4
H3
DA
HJ
H5
D3
SK

DISPLAY THE FULL DECK SHUFFLED DECK OF CARDS
D10
H8
S3
D8
H9
C10
D3
C8
S5
C5
DJ
H10
C2
HQ
HJ
S8
S7
S4
DA
C9
C4
SA
D5
CQ
H2
D9
C7
S10
H3
H5
H6
C6
D6
S9
SQ
D2
D4
SJ
CA
CK
H7
S2
HK
DQ
D7
CJ
S6
HA
H4
DK
C3
SK
DISPLAY THE CAREDS FOR THE FOUR PLAYERS AS DELT TO PLAYERS

Player-1  Player-2  Player-3 Player-4

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

C4

DK

H10

H9

Press any key to continue


I want to get it where there is a column of 13 cards, then another columns of 13 cards. Overall I'm trying to get 4 columns of thirteen cards. Man, I hate formatting up I need to do it to get better at it. Also, say I wanted to sort the cards in a way that I get all the clovers starting with for example Clover 2 - Clover Ace and put all those in rows of 4. I'm thinking that some sort of bubble sort would be the best method.
0
 

Author Comment

by:DancingFighterG
ID: 13542113
Hey Alex, I was looking at your approach as well and I was wondering how would header files look for your example.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13542247
>>>> I was wondering how would header files look for your example

The sample needs no header files as all declarations are in the one cpp file.

But of course you could put all class/enum declarations to header file, say cards.h, protect it by

#ifndef CARDS_H
#define CARDS_H

#include <iostream>
#include <vector>
#include <string>
using namespace std;

// put here all class/enum declarations


#endif // CARDS_H


and include it somewhere at the top of the remaining cpp file.

Regards, Alex
0
 

Author Comment

by:DancingFighterG
ID: 13542292
One other thing, I was trying to make a function to randomize the cards in the deck. Fatal made one for me put it uses arrays to do swaps. How would go about doing the same thing with vectors. Could you give me an example of this.
0
 

Author Comment

by:DancingFighterG
ID: 13542316
So for example I would put:

class PlayingCard
{
   CardColor m_cc;
   CardRank  m_cr;

public:
    PlayingCard(CardColor cc,  CardRank  cr) :  m_cc(cc), m_cr(cr) {}
    friend ostream& operator << (ostream& os, const PlayingCard& card)
    {
        os << g_allColAbbs[card.m_cc] << "" << g_allRanks[card.m_cr];
        return os;
    }
    bool operator < (const PlayingCard& card) const
    {
        return (m_cc < card.m_cc) || (m_cc == card.m_cc && m_cr < card.m_cr);
    }
};

in the header file right.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13542335
Look at that snippet of my example above:

class Deck : public Cards
{
public:
    Deck()
    {
        Pack pack;
        srand(time(NULL));  // seed randomizer
        for (int i = pack.m_cards.size(); i > 0; --i)
        {
            int n = rand()%i;
            m_cards.push_back( pack.m_cards[n] );
            pack.m_cards.erase( &pack.m_cards[n] );
        }
    }

    friend class Hand;
   
};

In the constructor of class Deck you get a randomized selection of the pack. That selection was added to the vector member of class Deck using the vector::push_back member function.

Regards, Alex


0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13542403
I wrote this sample some months before for another question. I see now that it is more complex than I remembered. Therefore, I will add some comments to class Deck and it's constructor that might help you to understand what happens.

// class Deck gives a shuffled pack of 52 cards  
class Deck : public Cards
{
public:
    // default constructor
    Deck()
    {
        // get a pack of sorted cards as a helper
        Pack pack;
        // seed randomizer with the current time thus getting new
        // shuffles any new second
        srand(time(NULL));  
        // loop all cards of the pack backwards
        for (int i = pack.m_cards.size(); i > 0; --i)
        {
            // get a randomized number between 0 and i-1
            // at the beginning of the loop, n is between 0 ... 51
            // at the end of the loop, n = 0
            int n = rand()%i;
            // put the found card to the new deck
            m_cards.push_back( pack.m_cards[n] );
            // delete the card from the initial pack, thus we couldn't get more than once
            pack.m_cards.erase( &pack.m_cards[n] );
        }
    }

    // That is the next class representing one of the players,
    // i. e. all cards he gets after dealing
    friend class Hand;
   
};


Hope, that helps

Alex
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13542466
The PlayingCard class represents only one card. To work with vectors you need class Cards that already is implemented by using a vector. What exactly is your question?

Note, the PlayingCard\Cards example of fatal is much simpler than the one I gave you. On the other hand, my sample is complete, compilable and tested. But, you shouldn't mix these samples as they don't have much in common.

Regards, Alex
 
0
 

Author Comment

by:DancingFighterG
ID: 13542499
Well, I wanted to build a function that randomizes the cards anytime that I want too. I noticed that the cards where random from the beginning but I like having control too randomize the cards at will. For example:

void shuffle(Deck& deck, int nCards)
            {
                  Pack pack;
                  srand(time(NULL));  // seed randomizer
                  for (int i = pack.m_cards.size(); i > 0; --i)
                  {
                        int n = rand()%i;
                        m_cards.push_back( pack.m_cards[n] );
                        pack.m_cards.erase( &pack.m_cards[n] );
                  }
            }

This is what I have now for a shuffe functions. It's not working correctly though!
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13542559
>>>> void shuffle(Deck& deck, int nCards)

Better turn it to a member function of class Deck

void Deck::shuffle()
{
     // we don't need a pack as we could the deck itself
     srand(time(NULL));  // seed randomizer
     for (int i = m_cards.size(); i > 0; --i)
     {
           int n = rand()%i;
           // we append the card found to the deck ...
           m_cards.push_back(m_cards[n] );
           // ... and remove it from it's old place
           deck.m_cards.erase( &pack.m_cards[n] );
     }
}

You also could call  m_cards.clear() to make the deck empty and then use a new pack to get a new shuffle.

Regards, Alex
0
 

Author Comment

by:DancingFighterG
ID: 13542621
So I would place this function inside the class deck right?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13542708
class Deck : public Cards
{
public:
    Deck()
    {
        Pack pack;
        srand(time(NULL));  // seed randomizer
        for (int i = pack.m_cards.size(); i > 0; --i)
        {
            int n = rand()%i;
            m_cards.push_back( pack.m_cards[n] );
            pack.m_cards.erase( &pack.m_cards[n] );
        }
    }

    void shuffle();   // take the implemention from above and put it somewhere in the
                           // cpp file below class declaration

    friend class Hand;
   
};

Be aware, that a new Deck already is shuffled. From a logical point of view it makes no sense to reshuffle a Deck. Better create a new one, e. g. if you want to play a new game.

Look at the main function:

int main()
{
   string input;
   
   while (true)
   {
     cout << "Do you want to play a new game? ";
     cin >> input;
     if (input == "N' or input == 'n')
         break;

     Deck deck;

     cout  << deck << endl;

     Hand hand1, hand2;
     hand1.deal(deck, 4);
     hand2.deal(deck, 4);
     hand1.deal(deck, 4);
     hand2.deal(deck, 4);

     cout  << deck << endl;
     cout  << hand1 << endl;
     cout  << hand2 << endl;

     hand1.sort();
     hand2.sort();

     cout  << hand1 << endl;
     cout  << hand2 << endl;

     // add code to play a game
     ...
  }
  return 0;
}

Here a new Deck already shuffled was created in the loop and you don't need shuffling anymore.

Regards, Alex
0
 

Author Comment

by:DancingFighterG
ID: 13542972
It gives me the error that deck is not in the class. This is where I have it:

class Hand : public Cards
{
public:
    Hand() {}
    void deal(Deck& deck, int nCards)
    {
        for (int i = 0; i < nCards; ++i)
        {
            m_cards.push_back( deck.m_cards[deck.size()-1] );
            deck.m_cards.erase( &deck.m_cards[deck.size()-1] );
        }
    }

    void sort()
    {
        std::sort(m_cards.begin(), m_cards.end());
    }
   
};


void Deck::shuffle()
{
     // we don't need a pack as we could the deck itself
     srand(time(NULL));  // seed randomizer
     for (int i = m_cards.size(); i > 0; --i)
     {
           int n = rand()%i;
           // we append the card found to the deck ...
           m_cards.push_back(m_cards[n] );
           // ... and remove it from it's old place
           deck.m_cards.erase( &pack.m_cards[n] );
     }
};
0
 

Author Comment

by:DancingFighterG
ID: 13543042
Question on a header file. For this particular type of code since these are all classes, it wouldn't be like putting prototypes in a header file. So what kind of declarations would you put in a header file for classes like this one.
0
 

Author Comment

by:DancingFighterG
ID: 13543048
I'm sorry for being such a nag but I've learned c++ in a different way so some off the things that you are doing are new to me. :)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13543191
>>>> deck.m_cards.erase( &pack.m_cards[n] );

It should be

     m_cards.erase( &pack.m_cards[n] );

as we have a member function now.

>>>> So what kind of declarations would you put in a header file for classes like this one.

I don't know if I understood the question, but principally a class header file needs all includes of class members and arguments that are not pointers or references. For pointers and references you only need a forward declaration of the class. Then a class header must contain the full class declaration. Some people use a header and a cpp file for any class. I personally prefer to have all classes of a class tree in one header and have one cpp file for all implementations. The main function normally would be in an own cpp file named as the project. For EE samples it is easier to have one source (and no header files) that easily can be copied and put to a new project.

>>>> ... for being such a nag but I've learned c++ in a different way ...

No problem, I am glad if you think that my comments are helpful.

Regards, Alex
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 600 total points
ID: 13543261
Oops! It is    

     m_cards.erase( &m_cards[n] );

What we are doing her is to remove the card we got by random as we already appended it as the bottommost card. So, shuffling is done by drawing an arbitrary card from the deck and put it below the deck (holding the finger between the card and the deck). Then draw the next card from the remaining deck, and so on.

Regards, Alex
 
0
 

Author Comment

by:DancingFighterG
ID: 13961080
Thanks Alex for the help. I figured out what I wanted too do with the stuff that you gave me but I forgot to give you points. Thanks again!! I have another one though.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
Suggested Courses
Course of the Month10 days, 21 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question