Thread: Need help with a card dealing program using classes

  1. #16
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    OK I think I need to help more. Just fill an array with all the card values and use a shuffling algorithm. This meets all the requirements because by filling an array with all the possibilities you ensure that each card is represented once, and with the shuffling algorithm, you give them random placement. What you do with the constructor depends on your expectations. What is the initial state of a card deck? Write out your answer in the constructor.

  2. #17
    Registered User
    Join Date
    Dec 2009
    Posts
    120
    Do you mean fill the array with the random numbers? That's not really what I am supposed to do. I am supposed to fill the array from 0-51 then add the randomness when I deal the card. Then after the card is pulled from the deck and randomized, I put it in position 51 and decrement the array by 1. Then I pull another card, randomize it, then put that card in position 50, then decrement by 1 again. It seems like I have everything working properly, I am just not putting the card at the end of the array, or I'm not decrementing it correctly? Or both?

  3. #18
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    >> Do you mean fill the array with the random numbers?

    I mean exactly what I said. How else will you know what you've dealt already versus not?

    Consider if

    Cards mydeck;

    creates a pack of cards like you buy at the store (ordered). Now let's assume you've built methods that do what they say.

    mydeck.shuffle();
    for (int count = 0; count < 52; count++) std::cout << mydeck.deal();

    If I do this then I've obviously dealt all the cards out, and notice I only had to shuffle them once. The particular stuff your instructor notes in the assignment like, "The services provided by the class should be the ability to deal a single card from the set of undealt cards, and the ability to shuffle the deck by setting the last card position back to 51," are merely implementation details he would like to see.
    Last edited by whiteflags; 11-24-2010 at 06:59 PM.

  4. #19
    Registered User
    Join Date
    Dec 2009
    Posts
    120
    Okay, but is there a obvious reason as to why my method is not working? To just take the last card dealt and put it at the end of the array then decrement the pointer down one each time a card is dealt? Am I close? Is that a possible method?

  5. #20
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463
    Quote Originally Posted by Bubba View Post
    I'm a bit late to this thread but you don't have to use a structure and could just use the raw numbers. Suits are composed of a set number of cards so you could translate the number into whatever output you want.

    Figuring out how to shuffle the deck by passing through the deck exactly one time and yet ensuring every card is shuffled is a very good exercise. In fact I've used it as an interview question b/c it allows me to see someone work through a problem step by step which is invaluable when it comes to analyzing how different people approach problems.

    I'd be interested to see your first attempt at your own shuffle algorithm here in this thread. This will definitely get you thinking and I'm curious as to what you will come up with.
    Here is my take at the shuffle algorithm:
    Code:
    #ifndef CARD_H_
    #define CARD_H_
    
    struct Deck_Card
    {
      int val;
      int suit;
    };
    
    class Card
    {
     private:
      Deck_Card Deck[52];
     public:
        Card();
        ~Card();
       void Card_Shuffle(int nn = 52);
       void Show();
    };
    
    #endif
    Code:
    #include <iostream>
    #include "card.h"
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    Card:: Card()
    {
      int i;
      int j;
      // Generating the ordered set/ordered Deck of Card
      // i to generate number from 1-13
      // j to generate the suites;
      for ( i = 0; i < 13; i++ )
        {
          for(j = 0; j < 4; j++)
    	{
    	  if ( (4*i+j) > 52) break;
    	  Deck[4*i+j].val = i+1;
    	  Deck[4*i+j].suit = j;
    	}
        }
    }
    Card::~Card()
    {}
    
    void Card::Card_Shuffle(int nn)
    {
      // nn is the number of times to switch position of 2 random cards. Default nn=52
      srand(time(NULL));
      Deck_Card temp;
    // n and m are the position of 2 cards in a deck. 
      int n,m; 
      int i;
      for (i = 0 ; i < nn ; i++)
        {
          // generating two random position
         n = rand() % 52;
         m = rand() % 52;
         // n and m must have different values
         while ( n == m)
    	{
    	  n = rand() % 52;
    	  m = rand() % 52;
    	}
         // switch the position
          temp = Deck[n];
          Deck[n] = Deck [m];
          Deck[m] = temp;
        }
    }
    
    void Card::Show()
    {
      string suit[4] = {"Hearts","Diamonds","Club", "Spades"};
      for (int i = 0; i < 52; i++) 
       cout << Deck[i].val << " of "<<suit[ Deck[i].suit] << endl;
    }
    Code:
    #include <iostream>
    #include "card.h"
    
    int main()
    {
      Card deck1;
      deck1.Show();
      deck1.Card_Shuffle();
      std:: cout << " Shuffled Deck: " << std::endl; 
      deck1.Show();
      return 0;
    }
    Here is my take on this one. This was a good exercise. I don't quite understand what you meant by "passing through the deck exactly one time." What I did was just generate the random positions of two cards in the deck and switch them. The shuffle is quite good after just iterate that for 52 times. I think a better way would be generating a set random unique number from 0 to 51. The uniqueness property makes it harder because I don't think C would check for that. I'll try that method later.
    I guess i could use enqueue and dequeue to take the 2 set of 5 cards out. And, if I want to reshuffle the rest of the cards, then I could've use dynamic array for "Deck".

  6. #21
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Fortunately that is a pretty poor algorithm, as it should be completely possible to have a card stay in its original position. If you always randomize again when n == m, you are trying too hard.

    It's pretty stacked.

    Nice job on nick's homework, overall.

  7. #22
    Registered User
    Join Date
    Dec 2009
    Posts
    120
    Quote Originally Posted by whiteflags View Post
    Fortunately that is a pretty poor algorithm, as it should be completely possible to have a card stay in its original position. If you always randomize again when n == m, you are trying too hard.

    It's pretty stacked.
    Was this to me or nimitzhunter? Now I'm getting even more confused!

  8. #23
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Of course it's to the other guy: you didn't write a shuffle algorithm!

  9. #24
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463
    Quote Originally Posted by whiteflags View Post
    Fortunately that is a pretty poor algorithm, as it should be completely possible to have a card stay in its original position. If you always randomize again when n == m, you are trying too hard.

    It's pretty stacked.

    Nice job on nick's homework, overall.
    Whiteflags,
    You are right. In your opinion, what is a better way to doing this? i think of writing it into something like this:
    Code:
    class Card
    {
     private:
      Deck_Card Deck[52];
      Deck_Card * Shuffled_Deck;
      int k; // number of card left in the deck
     public:
      Card();
      ~Card();
      void Card_Shuffle();
      void Show();
      void Deal();
    };
    where the constructor is and the method Card_Shuffle is:
    Code:
    Card:: Card()
    {
      k = 52;
        for ( int i = 0; i < 13; i++ )
        {
          for(int j = 0; j < 4; j++)
    	{
    	  if ( (4*i+j) > 52) break;
    	  Card::Deck[4*i+j].val = i+1;
    	  Card::Deck[4*i+j].suit = j;
    	}
        }
      Shuffled_Deck = new Deck_Card[k];
      for (int i = 0; i < k; i++)
        Shuffled_Deck[i] = Deck[i];
    }
    
    void Card::Card_Shuffle()
    {
      srand(time(NULL));
      int n;
      for ( int i = 0 ; i < k; i++)
        {
          n = rand() % k;
          Shuffled_Deck[i] = Deck[n];
          Shuffled_Deck[n] = Deck[i];
        }
    }
    I would like to declare " Deck_Card Deck[52];" as:
    Code:
     static Deck_Card Deck[52];
    But I can't find out how to initialize the static member array.

  10. #25
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by nick753 View Post
    Okay, but is there a obvious reason as to why my method is not working? To just take the last card dealt and put it at the end of the array then decrement the pointer down one each time a card is dealt? Am I close? Is that a possible method?
    I really must apologize for kind of ignoring this.

    There is a reason what you did does not work. Seeding rand() is very important because even if this

    Code:
    {
       int i;
       int deck[52];
       int the_card;
    
       int suit, value;
    
       int randcard = rand()% 52;
     
    
      for (i = 0; i < 52; i++)
        {
          deck[i]=i;
         }
     
        suit = deck[randcard] % (4+1)  * 100;
        value = deck[randcard] % 13 + 1;
    
        *card = deck[randcard];
        *card --;
    
        the_card = suit+value;
    
    
         return the_card;
    }
    is perfect, you will get the same sequence of cards no matter when you start the program. And there are compounding problems that make this way less than perfect.

    Remember, the index is what is random here, not the value. If you want to choose a random index, instead, that is fine, but you need to rewrite that completely. You have no way of knowing which cards are discarded as of yet. You can change that. Here's how.

    You'd still fill an array with card values in that case but you would have to swap the card into the last position of the array after it is going to be returned. OK, so say last starts out at 51. You pick out randcard and swap out deck[randcard] with deck[last--]. Then you pick randcard from 0 to last next time. Get what happened?

    This means that calling shuffle() just restores last to 51 for the next deal().

    Just as an aside, I would still fill an array with card values. It's simpler, and unless you're really sure what you did for the value currently works (because I'm not), you should change it. Modular arithmetic is kinda different: 0 divides into 52 as evenly as 52 does, so you end up with two possible zero results. This is also why anything like rand() % N; is not as good as it could be ... but this (again) explains it better than I will.

  11. #26
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by nimitzhunter View Post
    Whiteflags,
    In your opinion, what is a better way to doing this?
    I was not really concerned about your implementation details. I was pointing out a problem with your shuffling. There are many ways to write a shuffle but in each case you are merely choosing a possible permutation of a finite set out of all the possible sets. The wiki article I've linked to earlier, explains how to do it correctly.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. im a noob at c++, do you think so?
    By belRasho in forum C++ Programming
    Replies: 6
    Last Post: 04-25-2010, 11:02 PM
  2. Bingo Card Program. Any input?
    By dukebdx12 in forum C++ Programming
    Replies: 5
    Last Post: 02-15-2008, 03:00 PM
  3. Replies: 2
    Last Post: 11-07-2003, 12:21 AM
  4. Card Dealing Problem
    By curlious in forum C++ Programming
    Replies: 16
    Last Post: 08-19-2003, 06:47 PM
  5. card shuffling dealing question
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 04-03-2002, 08:37 PM