dcsimg
A Flash Developer Resource Site

Results 1 to 14 of 14

Thread: [disc] shuffling cards

  1. #1
    Senior Member
    Join Date
    Feb 2004
    Posts
    312

    [disc] shuffling cards

    which way would be best to simulate shuffling of 52 cards deck?
    i have this video poker game i made a few months ago and i was playing around with it today and i wasn't too pleased with the shuffling method.
    Code:
    var Shuffled:Array = new Array();
    deck = [52cards in deck];
    do {
    	index = Math.floor(Math.random()*deck.length);
    	Shuffled[i] = deck[index];
    	//Shuffled=[card33,card13,card2,card38,card15];//test
    	deck.splice(index,1);
             i++;
    	}while (deck.length != 0);
    any idea on how i can improve it?

  2. #2
    Student
    Join Date
    Apr 2001
    Location
    -
    Posts
    4,756
    is this supposed to be AS3?
    because in AS2 and AS1 you can just use Math.random(deck.length);, AS3 not anymore.
    The code looks messed up to me,- but that might be because it´s not a style I´d choose or like. For example why is the while (deck.length != 0); at the bottom of the snippet?,- shouldn´t that be above.

    while (deck.length != 0); can be shorten to: while (deck.length > 0);

  3. #3
    :
    Join Date
    Dec 2002
    Posts
    3,518

    Maybe try something like this...

    Code:
    var deck = new Array();
    for (var i = 1; i <= 52; i++) {
    	deck.push(i);
    }
    for (var i = 1; i <= 52; i++) {
    	var index = Math.floor(Math.random() * 51);
    	var tmp1 = deck[index];
    	deck[index] = deck.pop();
    	deck.push(tmp1);
    }
    trace(deck)

  4. #4
    Student
    Join Date
    Apr 2001
    Location
    -
    Posts
    4,756
    @ dawsonk: that looks very clean

  5. #5
    Senior Member
    Join Date
    Feb 2004
    Posts
    312
    code is in as2.
    i don't know why i picked do{}while at the time. The code works fine as it is though. All it does is, randomly picks an element from the deck array and puts it in the shuffle array then removes the element from the deck array.
    I thought maybe someone would give me a better method on how to shuffle an array with a more relasitic result rather than just using a simple random function. That's why i named the topic disc
    i don't know if i'm making myself clear.

  6. #6
    Senior Member webgeek's Avatar
    Join Date
    Sep 2000
    Posts
    1,356
    That's how people typically do it but you are at the whim of the random number generator. To make it more "random" you can use a different RNG. You can also just run your previous algo a few times in a loop. That will increase the "randomness" a bit too.

    I tried to find how Flash implements Math.random but I didn't see anything after a minute or two of looking. I'm guessing that they use the current timestamp as the seed for the number and if that's the case you can wait 1 millisecond between loops and increase the variance.

    This was such a problem with a game Electrotank wrote that I had to port a "seedable" RNG over to ActionScript so that we could produce consistent results.

  7. #7
    5+5=55 Schfifty Five's Avatar
    Join Date
    Jun 2006
    Posts
    698
    Or another way would start off with the cards in order, then loop through a few thousand times picking one card from each half of the deck and swapping them.

  8. #8
    Student
    Join Date
    Apr 2001
    Location
    -
    Posts
    4,756
    did you expect that the expierence would be different if you mix a few random functions ? - personally I dont think so.
    Maybe add a function that checks if 2 the same cards are followed by each other,- and if so shuffle those (aka spread them) with the rest of the cards that need to be shuffled. That way you prevent the same cards to be followed directly by each other.

  9. #9
    Senior Member webgeek's Avatar
    Join Date
    Sep 2000
    Posts
    1,356
    did you expect that the expierence would be different if you mix a few random functions ? - personally I dont think so.
    Mixing would needlessly complicate things. I was suggesting instead using a different RNG entirely. Depending on how "random" things need to be you can use "better" RNG algos. Specifically, if you go here:
    http://en.wikipedia.org/wiki/Pseudo-...mber_generator
    and look at the "Problems with deterministic generators" section you can see where they list the issues. Better generators (like the ones used for cryptography) will take longer to run but produce more variable results. Is it likely that anyone would notice the difference? No, but it would produce a more statistically viable distribution. If you were refering to my "1 millisecond delay" comment, that is explained in the code sample I included below.

    Maybe add a function that checks if 2 the same cards are followed by each other,- and if so shuffle those (aka spread them) with the rest of the cards that need to be shuffled. That way you prevent the same cards to be followed directly by each other.
    Actually doing this makes it less random because you are manually injecting a pattern. If the RNG in question is good enough then you don't need to touch the output it generates.

    With that said, the algo listed in the first post and updated later is probably not the best approach. This massive amount of code from the Collections class in Java appears to be a much better way to do it. I ripped out anything not directly pertinent but it's still quite large:

    Code:
    /**
    * Constant used to decide cutoff for when a non-RandomAccess list should
    * be treated as sequential-access. Basically, quadratic behavior is
    * acceptable for small lists when the overhead is so small in the first
    * place. I arbitrarily set it to 16, so it may need some tuning.
    */
    private static final int LARGE_LIST_SIZE = 16;
    
    /**
    * Determines if a list should be treated as a sequential-access one.
    *
    * @param l the list to check
    * @return <code>true</code> if it should be treated as sequential-access
    */
    private static boolean isSequential(List l) {
    	return ! (l instanceof RandomAccess) && l.size() > LARGE_LIST_SIZE;
    }
    
    
    /**
    * Cache a single Random object for use by shuffle(List). This improves
    * performance as well as ensuring that sequential calls to shuffle() will
    * not result in the same shuffle order occurring: the resolution of
    * System.currentTimeMillis() is not sufficient to guarantee a unique seed.
    */
    Private static Random defaultRandom = null;
    
    /**
    * Shuffle a list according to a given source of randomness. The algorithm
    * used iterates backwards over the list, swapping each element with an
    * element randomly selected from the elements in positions less than or
    * equal to it (using r.nextInt(int)).
    * <p>
    *
    * This algorithm would result in a perfectly fair shuffle (that is, each
    * element would have an equal chance of ending up in any position) if r were
    * a perfect source of randomness. In practise (eg if r = new Random()) the
    * results are merely very close to perfect.
    * <p>
    *
    * This method operates in linear time. To do this on large lists which do
    * not implement {@link RandomAccess}, a temporary array is used to acheive
    * this speed, since it would be quadratic access otherwise.
    *
    * @param l the list to shuffle
    * @param r the source of randomness to use for the shuffle
    * @throws UnsupportedOperationException if l.listIterator() does not
    *         support the set operation
    */
    
    public static void shuffle(List l, Random r) {
    	int lsize = l.size();
    	ListIterator i = l.listIterator(lsize);
    	boolean sequential = isSequential(l);
    	Object[] a = null; // stores a copy of the list for the sequential case
    	if (sequential) {
    		a = l.toArray();
    	}
    	for (int pos = l, size - 1; pos > 0; --pos) {
    		// Obtain a random position to swap with. pos + 1 is used so that the range of the random number includes the current position.
    		int swap = r.nextInt(pos + 1);
    		// Swap the desired element.
    		Object o;
    		if (sequential) {
    			o = a[swap];
    			a[swap] = i.previous();
    		} else {
    			o = l.set(swap, i.previous());
    		}
    		i.set(o);
    	}
    }

  10. #10
    Student
    Join Date
    Apr 2001
    Location
    -
    Posts
    4,756
    atleast there is a geek not just in your nick

  11. #11
    Now tell me whos watchin...... samvillian's Avatar
    Join Date
    Feb 2007
    Location
    Where do you live?
    Posts
    539
    render got told... lol...
    anyway..

  12. #12
    Member
    Join Date
    Mar 2007
    Posts
    33
    @webgeek
    What algorithm did you use for the seedable RNG algorithm? I'm going to need one soon but haven't looked into it so I could use some direction.

  13. #13
    Senior Member webgeek's Avatar
    Join Date
    Sep 2000
    Posts
    1,356
    IIRC it is a tweaked version of the Park-Miller algo. Tweaked because I wanted the seed to be passed in rather then time based. If you google, you can find a fair number of JS implementations of it these days.

    This is the generator we use in our Mah Jong and Regal Solitaire games. By using this seedable generator we can save/load games by the seed itself. It worked beautifully in the end.

  14. #14
    Senior Member
    Join Date
    Nov 2006
    Posts
    115
    You should use Classes.

    Class Card:
    contains suit and number (and maybe next card of same number / suit [to be used later])

    Class Deck:
    contains an array of Objects Card
    function Deal Card: randomly selects a card from the deck and removes it from the array (using pop() method)

    Class Hand:
    contains an array of cards (or a linked list which can be used to determine what kind of hands this can hand can form)
    also contains function which can be used to compare to other hands to determine what hand is better (this can get a little tricky in certain games (if wild cards exist and if there are shared cards (texas hold em)) [It becomes a huge mess in omaha]
    and if hi/lo game a function which compares for a lo hand
    (could add function to remove a card as well if playing draw poker)

    Anyway if you program it correctly using classes will allow you add new complications to your game with greater ease as well as it should be easier to re-use. If you don't know OOP you should learn it, since it is great

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center