Thread: Card Shuffle Help

  1. #16
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by citizen View Post
    I disagree - the algorithm mike suggested is the Knuth shuffle, which is a good shuffle because every card has an equal probability to be swapped with every other card. It's difficult to implement correctly, but I doubt it's any less efficient than what you've suggested. And in all honesty, I'd rather use a documented algorithm for shuffling. I don't think my feelings are that exceptional.
    Yes mikes algotithm is better (I did say probably the most efficient ), actually my method is The original Fisher-Yates (Kunth) method as described in wikipedia. My first thought was to swop two random positions, but I didn't like that much because you call rand twice per iteration, so I came up with the original Fisher-Yates shuffle, but that works fine in theory but is inefficient when you do it on a computer. Incidently I think mike has 53 cards in his pack!! (0-52)! (Well at least room for 53 anyway).

    Also I don't think you need to step to the last card in the pack as the chance it will be in that position, at that stage is 1 in 52 (I think) which is the same as any other position, but I guess it will do no harm to, however I think the Kunth method does not step to the last card anyway for the reason I described.
    Last edited by esbo; 04-02-2008 at 07:45 PM.

  2. #17
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,611
    I really see nothing strange with mike's deck of cards, though. the indices are 0 to 51. On the last iteration of his shuffling loop, i is 52, which would break it properly.

    And you can't exclude cards in the modern algorithm, otherwise your shuffle has a bias towards the card placement. Your generator could still select any of 52 indices to swap the last one with.

  3. #18
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by citizen View Post
    I really see nothing strange with mike's deck of cards, though. the indices are 0 to 51. On the last iteration of his shuffling loop, i is 52, which would break it properly.

    And you can't exclude cards in the modern algorithm, otherwise your shuffle has a bias towards the card placement. Your generator could still select any of 52 indices to swap the last one with.
    Yes I was wrong about the 53 cards thing, I always get confused with indexes and counts, but you can exclude stepping to the last card for swapping because the chance that it has been moved elsewhere through swopping is 50/51 which is already the same as any of the other cards. So it has not been excluded from the randomising algorithm, it just was not necessary to step to it because it's position would be already random due to the chance of it being moved by one of the previous swops. But it does no real harm to step to it barring a very slight increase in run time.
    Actually mikes allgorithm does step to the last card (I think) which is strictly unnecessary, and is possible why I got confused about the number of cards
    he was using.
    Last edited by esbo; 04-02-2008 at 08:39 PM.

  4. #19
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Incidently I don't really understand why C starts it's array indexes with 0 rather than 1, however I think I have mentioned that before, it would certaintly have saved me a lot of grief in the past (and present and future no doubt!!).

  5. #20
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    mike, i get a lot of errors with this..
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdlib.h>
    #include <time.h>
    #include <conio.h>
    
    
    int main()
    {
    	
        srand(time(NULL)); //Seed randomisation
    	/*char* GetSuit(Uint8 card){
    
    	char *suit[] = {"Clubs", "Diamonds", "Hearts", "Spades"};
    	 return suit[card/13];
    	}
    	char* GetRank(Uint8 card)
    	{
    	char *rank[] = {"Ace", "Two", "Three", "Four", "Five", 
    
            "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};
    	return rank[card%13];
    	}*/
    	    int deck[52];
    		
        int i, temp, random;
        // Init deck
        for(i=0; i<52; i++)
             deck[i] = i;
        //Shuffle deck
        for(i=0; i<52; i++)
        {
             random = rand() % 52;
             temp = deck[i];
             deck[i] = deck[ random ];
             deck[ random ] = temp;		 
    		
        }
    		char* GetSuit(Uint8 card){
    
    	char *suit[] = {"Clubs", "Diamonds", "Hearts", "Spades"};
    	 return suit[card/13];
    	}
    	char* GetRank(Uint8 card)
    	{
    	char *rank[] = {"Ace", "Two", "Three", "Four", "Five", 
    
            "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};
    	return rank[card%13];
    	}
    	printf("%d", deck[i]);
    _getche();
    return 0;
    }

  6. #21
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,611
    The main problem is that you have some functions written multiple times as well as inside of main(). Don't do that - write them once, somewhere else in the file.

  7. #22
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    the first section was commented out..but unfortunetley anyway i write this code i get errors. One beings that card is not defined..what is card supposed to be defined as? Here is code without the extra junk.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdlib.h>
    #include <time.h>
    #include <conio.h>
    
    
    int main()
    {
    	
    	char *suit[] = {"Clubs", "Diamonds", "Hearts", "Spades"};
    	 return suit[card/13];
    	 char *rank[] = {"Ace", "Two", "Three", "Four", "Five", 
    
            "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};
    	return rank[card%13];
    	
        srand(time(NULL)); //Seed randomisation
    
    	    int deck[52];
    		
        int i, temp, random;
        // Init deck
        for(i=0; i<52; i++)
             deck[i] = i;
        //Shuffle deck
        for(i=0; i<52; i++)
        {
             random = rand() % 52;
             temp = deck[i];
             deck[i] = deck[ random ];
             deck[ random ] = temp;		 
    		
        }
    	
    	
    	printf("%d", deck[i]);
    _getche();
    return 0;
    }

  8. #23
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Oh, yeah you want to remove the line that start with 'return' from main, but leave the return 0 at the end. Returning from main will basically quit your program.

  9. #24
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,611
    I find it simpler just to provide my own example than try to fix your version. The problem is that card is supposed to be a number in the pack. In your code, there used to be functions for finding out the pips on a card, and the suit of the card. Like this:
    Code:
    #include <stdlib.h>
    #include <time.h>
    #include <stdio.h>
    
    const char * what_pip( int this_card );
    const char * what_suit( int this_card );
    void make_deck( int * this_deck );
    void shuffle( int * this_deck );
    
    int main ( void )
    {
        int mypack[52];
        long card;
    
        make_deck( mypack );
        srand( (unsigned )time( NULL ) );
        shuffle( mypack );
        
        for ( card = 0; card < 52; card += 4 ) {
            printf( "&#37;s%s %s%s %s%s %s%s\n", 
                what_pip( mypack[card] ), what_suit( mypack[card] ),
                what_pip( mypack[card + 1] ), what_suit( mypack[card + 1] ), 
                what_pip( mypack[card + 2] ), what_suit( mypack[card + 2] ), 
                what_pip( mypack[card + 3] ), what_suit( mypack[card + 3] ) );
        }
        return 0;
    }
    
    const char * what_pip( int this_card )
    {
        const char * pips[] = { 
            "A", "2", "3", "4", "5", "6", "7", "8", "9",
            "T", "J", "Q", "K"
        };
        return pips[ this_card % 13 ];
    }
    
    const char * what_suit( int this_card )
    {
        const char * stacks[] = { "S", "H", "C", "D" };
        return stacks[ this_card / 13 ];
    }
    
    void make_deck( int * this_deck )
    {
        long idx;
        if ( this_deck == NULL ) return ;
    
        for ( idx = 0; idx < 52; idx++ ) {
            this_deck[idx] = idx;
        }
    }
    
    void shuffle ( int * this_deck )
    {
        long idx;
        if ( this_deck == NULL ) return ;
    
        for ( idx = 0; idx < 52; idx++ ) {
            int rnd = rand() / RAND_MAX / 52;
            int save = this_deck[idx];
            this_deck[idx] = this_deck[rnd];
            this_deck[rnd] = save;
        }
    }
    
    /** my output - 
    TS 7D 5H JS
    AD JD 7S 3D
    QC 7C JH JC
    KS 6H TD KD
    2S 8H 9H 3C
    QS QH TC 5C
    TH QD 8S AH
    AS 4H 4S 5D
    4C 6S KH KC
    6D 9C 5S 8D
    7H 3S 6C 2H
    8C 2C 9D 9S
    3H 4D AC 2D
    **/
    Nice and shuffled.

  10. #25
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    the only problem with what you have done is that the cards dont print out randomely

  11. #26
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Dude, just remove the return statements from your code

  12. #27
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,611
    And the only problem with what your post says is I'm not sure what the problem is.

    If you're running the executable multiple times in quick succession expecting a very different result each time, then rand() has a seed which isn't very good. If you're shuffling the same deck multiple times and the results aren't very different, you need a different approach to calling rand(), because the card selection is suffering from bias. You might want to read using rand() effectively to get some ideas on what to do about this (and how a PRNG will affect your card games in general).

    If you are trying to write a casino program and this isn't some academic venture, then you will have to write a stronger PRNG anyway, since rand() is not cryptographically random and wouldn't do for like, online poker. If you're looking for something with that kind of effectiveness, you need to learn and weigh these approaches.

    If my code is wrong because I chose to print out the whole deck in four columns so you could see the result of the shuffle, I'm sorry. You'll have to work out how to deal cards for the game you are playing yourself.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need Help With a BlackJack Program in C
    By Jp2009 in forum C Programming
    Replies: 15
    Last Post: 03-30-2009, 10:06 AM
  2. Bitwise Unwanted Output
    By pobri19 in forum C++ Programming
    Replies: 4
    Last Post: 09-15-2008, 04:07 AM
  3. Vector out of range program crash.
    By Shamino in forum C++ Programming
    Replies: 11
    Last Post: 01-18-2008, 05:37 PM
  4. Segmentation Fault - aaaaaaaah!
    By yogibear in forum C Programming
    Replies: 6
    Last Post: 10-01-2007, 03:21 AM
  5. Blackjack
    By Tommo in forum C Programming
    Replies: 10
    Last Post: 06-20-2007, 08:07 PM