Thread: Deck Shuffle

  1. #1
    Registered User
    Join Date
    Jan 2006
    Location
    Boston, Massachusetts
    Posts
    23

    Deck Shuffle

    What I want to do is shuffle the cards like a person does. Split the deck roughly in half, then shuffle the two halves together from the bottom up by alternating between the havles and placing 1-4 cards from the halves in the orginal deck until all 52 cards are back in the original deck. Then repeat a good number of times to get the deck shuffled as if it has been used for years. I thought I had this all set. But if I try to shuffle it more than five times this way I get a segmentatin fault, and when I do it five times it isnt shuffled enough. So, with out further waiting here is the code.

    card struct
    Code:
    enum suit {hearts,diamonds,spades,clubs};
        
    struct card{
            
      suit s;     //takes values of the enum
      int value;  //1-13, where 1=A,11-13=J,Q,K
      bool dis_or_played; //has the card been discarded/played from a hand?
            
    };
    deck class
    Code:
    class Deck{
        
      friend class Player;
            
    public:
      Deck();             //create deck
      void shuffle();     //shuffle deck
      void deal();        //deal to players and the kitty
            
    private:
      card d[52];        //the deck
      int next_card;   //next card to be dealt
            
    };
    shuffle function(maybe be a little hard to understand with the way I have it set up)
    Code:
    void Deck::shuffle(){
        
      time_t seconds;
      time(&seconds);
      srand((unsigned int)seconds);
    
      random_shuffle(d[0],d[51]);
            
      int b = rand() % (32 - 20 + 1) + 20;
      int t = (52 - b);
      card *temp1[b];
      card *temp2[t];
      int j=0;
      int c = rand() % (4 - 1 + 1) +1;
      int temp1_index = b-1;
      int temp2_index = t-1;
      int deck_index = 51;
            
      for(int h=0; h<5; h++){
        for(int i=0; i<b; i++){
          temp1[i] = &d[i];
        }
            
        for(int i=b; i<52; i++){
          temp2[j] = &d[i];
          j++;
        }
               
        while(deck_index>=0){
          if(temp1_index>=0 && (temp1_index + 1)>=c){
    	for(int i=0; i<c; i++){
    	  d[deck_index] = *temp1[temp1_index];
    	  temp1_index--;
    	  deck_index--;
    	}
          }
          else{
    	int rest = temp1_index + 1;
    	for(int i=0; i<rest; i++){
    	  d[deck_index] = *temp1[temp1_index];
    	  temp1_index--;
    	  deck_index--;
    	}
          }
            
          if(temp2_index>=0 && (temp2_index + 1)>=c){
    	for(int i=0; i<c; i++){
    	  d[deck_index] = *temp2[temp2_index];
    	  temp2_index--;
    	  deck_index--;
    	}
          }
          else{
    	int rest = temp2_index +1;
    	for(int i=0; i<rest; i++){
    	  d[deck_index] = *temp2[temp2_index];
    	  temp2_index--;
    	  deck_index--;
    	}
          }
        }
      }       
    }

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    First, I would only call srand() once at the beginning of the program, not every time you shuffle. Second, random_shuffle takes the first and one past the last element, so you should be using random_shuffle(d[0],d[52]); instead of d[51]. Third, you might already know this, but random_shuffle completely shuffles the deck by itself without any need to do your own shuffling.

    For the actual problem of getting your human-esque shuffling code to work, I did notice that you never reset j to 0 inside your shuffle loop. The first time through it runs from 0 to t, but the second time through it is still at t so you are accessing the temp2 array out of bounds. Unluckily for you this doesn't cause a problem until the 5th time through.

    I didn't look any further so there may be other problems.

    One last note, card *temp1[b]; uses a non-constant value as the size of the array. This isn't legal in C++ but works on gcc because the C language allows it. You might consider changing that to a dynamic array (or even better a vector) if you plan on using your code on other compilers.

  3. #3
    Registered User
    Join Date
    Jan 2006
    Location
    Boston, Massachusetts
    Posts
    23
    The random_shuffle was an attempt to do the shuffling a different way. But that didn't work because the array I pass isnt of type RandomAccessIterator or something. So just disregard that.

    The setting of the j to 0 was the problem with getting the fault. But, after having it loop 1000 times the shuffle still doesn't seem to shuffle anything. Any idea?

    The top half of the deck is all the red suits and the bottom the black. But when I deal only like two of the players have a black card in their hand and by a I mean ONE!
    Last edited by pjharris; 01-03-2006 at 01:26 PM. Reason: reword

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Rather than cutting the deck, which you seem to be trying to do, why not just swap random pairs of cards several times?

    Code:
    i = rand() % 52;
    j = rand() % 52;
    temp = deck[i]; deck[i] = deck[j]; deck[j] = temp;

  5. #5
    Registered User
    Join Date
    Jan 2006
    Location
    Boston, Massachusetts
    Posts
    23
    Quote Originally Posted by Salem
    Rather than cutting the deck, which you seem to be trying to do, why not just swap random pairs of cards several times?

    Code:
    i = rand() % 52;
    j = rand() % 52;
    temp = deck[i]; deck[i] = deck[j]; deck[j] = temp;
    I dont want to have to deal with getting duplicate cards in the deck. And I am trying to get a more realistic type of shuffle, seeing as I have seen some programs deal really weird when it comes to the way the game I am writing deals the cards.

    I was thinking about doing that, but I figured I would come here for help with the way I was thinking of doing it.

    Thanks for the suggestion though.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> But that didn't work because the array I pass isnt of type RandomAccessIterator or something.

    Sorry, it should be random_shuffle(d, d+52). If you just want to get a real shuffle, calling that once is all you have to do.

    Now that you set j = 0 inside the loop, what about deck_index, temp1_index and temp2_index? This is why it is better style to declare your variables inside the smallest scope that you can. I would move all your local variables inside your first for loop, and remember to reset any variables that are re-used inside the while loop.

    One other potential problem with your code... you are storing pointers in your temp arrays. The pointers point at positions in the deck, not values. So when you update the value during the shuffle, the temp array gets modified indirectly. I think the temp arrays should hold cards, not card pointers.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > I dont want to have to deal with getting duplicate cards in the deck
    What duplicates?
    You initialise 52 cards with say 52 unique cards, and you swap pairs a number of times. The uniqueness property does NOT change, but the order property does.
    How is this not a shuffle?

  8. #8
    Registered User
    Join Date
    Jan 2006
    Location
    Boston, Massachusetts
    Posts
    23
    Quote Originally Posted by Salem
    > I dont want to have to deal with getting duplicate cards in the deck
    What duplicates?
    You initialise 52 cards with say 52 unique cards, and you swap pairs a number of times. The uniqueness property does NOT change, but the order property does.
    How is this not a shuffle?
    Simmer down there buddy. I was wrong. It does shuffle. I just didn't see it because of the way it was written with everything on three lines.
    Last edited by pjharris; 01-03-2006 at 04:34 PM. Reason: correction

  9. #9
    Registered User
    Join Date
    Jan 2006
    Location
    Boston, Massachusetts
    Posts
    23
    Thank you Daved, my shuffle works now. It was all about the indices to my arrays and resetting j in the loop. Your help is much appreciated.

  10. #10
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    And I am trying to get a more realistic type of shuffle, seeing as I have seen some programs deal really weird
    Yep, if the deal ever seems strange, it can't be random because with random deals there are always cards from every suit and no pairs. Oops, gotta run...I think I see a goblin lurking in the shadows of my bedroom.

  11. #11
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    Quote Originally Posted by pjharris
    And I am trying to get a more realistic type of shuffle, seeing as I have seen some programs deal really weird when it comes to the way the game I am writing deals the cards.
    Just to really nail down a point that 7stud was making (and for fun), let's test your ability to judge randomness. If you want to.

    Write down a random sequence of 1's and 0's, one hundred digits long, where each digit represents the outcome of a coin flip. But don't actually flip coins, try to make it look like you did flip coins, with a typical sort of outcome, and write the digits manually. Here's one example that's five digits long. It represents a heads-tails-heads-tails-heads coin toss sequence.

    Code:
    10101
    Can you make your sequence of digits indistinguishable from real coin tosses, or will you be exposed as a faker? :-)

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Yep, if the deal ever seems strange, it can't be random because with random deals there are always cards from every suit
    Being dealt SA,SK,SQ,SJ,S10 is just as likely as being dealt C2,H4,D6,S8,C10
    The fact that one is far more desirable than the other is not a property of randomness.

    Deal yourself many 1000's of hands, and count how many times each card comes up. If you're getting roughly equal numbers of each card, then you might be onto something.

  13. #13
    Registered User
    Join Date
    Jan 2006
    Location
    Boston, Massachusetts
    Posts
    23
    Quote Originally Posted by Rashakil Fol
    Can you make your sequence of digits indistinguishable from real coin tosses, or will you be exposed as a faker? :-)
    I get it. But like I said with the shuffle that I saw, and for the type of game that I am making it for(not poker or blackjack or any other casino card game game) the shuffle seemed a little off. I didn't say it wasn't shuffling, I said it was off. And I know about probability and all that stuff. It's just a preference with the way I want to shuffle the deck.

  14. #14
    Registered User
    Join Date
    Jan 2006
    Location
    Boston, Massachusetts
    Posts
    23
    Quote Originally Posted by Daved
    One last note, card *temp1[b]; uses a non-constant value as the size of the array. This isn't legal in C++ but works on gcc because the C language allows it. You might consider changing that to a dynamic array (or even better a vector) if you plan on using your code on other compilers.
    How would a dynamic array or vector be better for what I am doing? I guess because it isn't legal in C++ and I am using g++ as my compiler. So, I guess I don't understand the reason given. So, please elaborate on that too.

    And why is a vector better than dynamic array(haven't used either)?

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Many people change compilers, or re-use code on different projects that use different compilers. When you try to use that code on another compiler that doesn't support non-constant array sizes, it won't work. Also, when you post it on a website like this, only people with g++ will be able to run and test your code without making changes.

    The gcc compiler allows it for a reason, so if you know you are only going to use g++ and you don't plan on using this code much elsewhere, then it is perfectly acceptable to take advantage of the feature. Besides, it might even be added to the C++ standard in the future.

    A vector is better than a C style dynamic array because it encapsulates the memory management and provides a safer interface than plain arrays.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. shuffle 2-dimensional array
    By patkhor in forum C Programming
    Replies: 5
    Last Post: 11-26-2008, 03:51 PM
  2. Question about engine design.
    By Shamino in forum Game Programming
    Replies: 9
    Last Post: 01-29-2008, 10:53 AM
  3. Blackjack
    By Tommo in forum C Programming
    Replies: 10
    Last Post: 06-20-2007, 08:07 PM
  4. Card shuffle and deal want to put on Stack
    By sugie in forum C++ Programming
    Replies: 4
    Last Post: 12-12-2005, 08:40 PM
  5. Replies: 2
    Last Post: 11-07-2003, 12:21 AM