Introduction:
How do you randomise a set of numbers without having any attempts clash with earlier ones? For instance, if using a random number generator (
Solution:
You start with the simple numbers 0 to 51 representing the various different cards and these are stored originally in memory locations with a base and offsets between 0 and 51. Note it is not necessary that any of these cards start in any logical or predetermined order. As long as each is there, which implies none can be duplicated.
This is an iterative process which terminates when all cards have been handled - or just those cards considered to be 'dealt' if dealing/selecting fewer than the full set. Today we will look at randomising the full set though. Consider the dealing phase to come afterwards and this illustrates the fullest set of the logic - some of which could be dispensed with if only dealing straight off the 'deck' and not requiring the full set to be randomised in place.
Key:
X = Random Number.
Y = Number of Items Left.
Z = Temp Variable (Used for swapping).
The first step of each iteration is to capture a new random number. In this explanation I will ignore seeding and always use
Multiply that random number by Y and chop any decimal places.
Y starts at 52 but is decremented in each iteration. This gives an even distribution of the numbers available in the range (1st: 0 to 51; 2nd: 0 to 50; 3rd 0 to 49; etc). This is the offset you need - now in X.
Decrement Y now to simplify next step.
Swap the current value found at offset X with that found in offset Y (after decrementing).
Rinse & repeat as long as Y is still greater than one (1).
Illustration:
For simplicity of illustration I will use a restricted set of just 8 items - 0 to 7. The logic works for any number but the illustrations get bigger and more complicated as that number increases.
The second column reflects the calculated offset to switch. Notice it's an integer by that point. Also notice that the second to last update switches column #2 with itself. Clearly this is unnecessary and has no effect. In actual code I would usually compare X & Y then only switch if they don't match.
How do you randomise a set of numbers without having any attempts clash with earlier ones? For instance, if using a random number generator (
Rnd([SeedCode])
in VBA.) and you want to emulate randomising a pack of cards without any card being selected more than once, as would be the case if simply using a random index into the original set (or pack) over and over again.Solution:
You start with the simple numbers 0 to 51 representing the various different cards and these are stored originally in memory locations with a base and offsets between 0 and 51. Note it is not necessary that any of these cards start in any logical or predetermined order. As long as each is there, which implies none can be duplicated.
This is an iterative process which terminates when all cards have been handled - or just those cards considered to be 'dealt' if dealing/selecting fewer than the full set. Today we will look at randomising the full set though. Consider the dealing phase to come afterwards and this illustrates the fullest set of the logic - some of which could be dispensed with if only dealing straight off the 'deck' and not requiring the full set to be randomised in place.
Key:
X = Random Number.
Y = Number of Items Left.
Z = Temp Variable (Used for swapping).
The first step of each iteration is to capture a new random number. In this explanation I will ignore seeding and always use
X = Rnd()
. A number may be passed as a parameter to control seeding but we're not interested in that here. Using the default means we'll get the next in the current sequence regardless of what that sequence is and how far through it we are already. All values returned are 0 <= X < 1. One (1) can never be returned but zero (0) can.Multiply that random number by Y and chop any decimal places.
X = Fix(X * Y)
Y starts at 52 but is decremented in each iteration. This gives an even distribution of the numbers available in the range (1st: 0 to 51; 2nd: 0 to 50; 3rd 0 to 49; etc). This is the offset you need - now in X.
Decrement Y now to simplify next step.
Y = Y - 1
Swap the current value found at offset X with that found in offset Y (after decrementing).
Z = Base(X): Base(X) = Base(Y): Base(Y) = Z
Rinse & repeat as long as Y is still greater than one (1).
Illustration:
For simplicity of illustration I will use a restricted set of just 8 items - 0 to 7. The logic works for any number but the illustrations get bigger and more complicated as that number increases.
Code:
[U][B]Apply Update[/B][/U] [U][B]Offset: 0 1 2 3 4 5 6 7[/B][/U] Values: 0 1 2 3 4 5 6 7 0.7055475==>5 Values: 0 1 2 3 4 [U]7[/U] 6 [B][U]5[/U][/B] 0.533424 ==>3 Values: 0 1 2 [U]6[/U] 4 7 [B][U]3[/U][/B] 5 0.5795186==>3 Values: 0 1 2 [U]7[/U] 4 [B][U]6[/U][/B] 3 5 0.2895625==>1 Values: 0 [U]4[/U] 2 7 [B][U]1[/U][/B] 6 3 5 0.301948 ==>1 Values: 0 [U]7[/U] 2 [B][U]4[/U][/B] 1 6 3 5 0.7747401==>2 Values: 0 7 [B][U]2[/U][/B] 4 1 6 3 5 0.01401764=>0 Values: [U]7[/U] [B][U]0[/U][/B] 2 4 1 6 3 5
Comment