473,830 Members | 2,045 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Shuffle card deck

JC
I am very new to programming and learning on my own.

Why do I keep getting duplicate values using this code? I want to shuffle a
deck of 52 cards. The logic seems right to me.

Randomize

For C = 0 To 1000

C1 = Cards(Int(Rnd * 52)) ' returns a number from 0 to 51

C2 = Cards(Int(Rnd * 52)) ' returns a number from 0 to 51
Cards(C1) = C2 ' Value of C2 is assigned to Card in location Cards(C1)
Cards(C2) = C1 ' Value of C1 is assigned to Card in location Cards(C2)

Next C

TIA
Jul 17 '05
23 12965
> Private Sub Command1_Click( )
Dim MyDeck(1 To 52) As String
ShuffleDeck MyDeck
Debug.Print MyDeck(1) & ", " & MyDeck(4) & ", " & MyDeck(43)
End Sub


I'm not sure why I opted to use the above code originally when I chose to
demo the function. The deck of cards is completely randomized after the
function call, so selecting cards is as simple as iterating through the
array sequentially. Perhaps a better demo code would have been this

Private Sub Command1_Click( )
Dim X As Long
Dim MyDeck(1 To 52) As String
ShuffleDeck MyDeck
For X = 1 To 5
Debug.Print MyDeck(X)
Next
End Sub

which, in effect, deals out a random hand of 5 cards.

Rick - MVP
Jul 17 '05 #11

On Wed, 24 Sep 2003, Calum wrote:

When you swap two things you need a temporary**! Why loop to 1000? You
can loop just 52 times if you swap each card with a randomly chosen other.

for(int c=0; c<52; ++c)
{
Card &a = cards[c];
Card &b = cards[rnd(52)]; // For a suitably defined rnd

Card t = a; // Not expensive if Card is 4 bytes or 1 byte
a = b;
b = t;
}
Geez Louise, isn't this a FAQ *somewhere*?
The above algorithm *does* *not* *generate*
*a* *uniform* *distribution*! Get that through
your head! Arrrgh!

** There is also an XOR hack:
a = a^b, b = a^b, a = a^b;
saves a register spill :-)


....at the cost of producing incorrect results
when &a == &b, as is likely with your algorithm
as it stands.

-Arthur

Jul 17 '05 #12

"Mel Wilson" <mw*****@the-wire.com> wrote in message
news:cibc/ks/Kz*******@the-wire.com...
I would go with
For C = 0 to 51
Cards(C) = C
Next C
DeckCount = 52

Function DealOne
If DeckCount < 1
DeckCount = 52 ' simulate reshuffle and keep going
End If
I = Int (Rnd * DeckCount) ' a random place in the deck
DeckCount = DeckCount - 1 ' decrease the card count
X = Cards(I) ' the card to deal
Cards(I) = Cards(DeckCount ) ' swap dealt card with last card
Cards(DeckCount ) = X
DealOne = X ' return the dealt card
End Function

For I = 0 to 6
RummyHand(I) = DealOne()
Next I
This code probably contains errors -- my Basic is in bad shape

Good Luck. Mel.


I agree. Why not pick randomly from a sequential deck. No one knows the deck
is "not shuffled" and drawing randomly is the same as having a shuffled deck
:)
Jul 17 '05 #13
gb*@email.si (Gorazd Bozic) wrote in news:bk******** **@planja.arnes .si:
In article <Xn************ *************** ***@204.127.36. 1>,
James Rogers <ji************ **@att.net> wrote:
...
-- Define the number of cards in a standard deck.
subtype Deck_Index is integer range 1..52;


Just curious -- why not

subtype Deck_Index is integer range Pips'Range * Suits'Range;


The reason is pretty simple. Both Pips and Suits are defined as
enumerated types. In Ada enumerated types are non-numeric discrete
types. There is no multiplication operation defined for any
emumerated type.

Is that not possible? That would be consistent with the Initialize
function:
function Initialize return Card_Deck is
Result : Card_Deck;
Temp_Index : Integer := Deck_Index'Firs t;
begin
for The_Suit in Suits loop
for The_Pip in Pips loop
Result(Temp_Ind ex) := (The_Pip, The_Suit);
Temp_Index := Temp_Index + 1;
end loop;
end loop;
return Result;
end Initialize;

To achieve the equivalent of what you want in Ada I would need to define
Card_Deck as a two dimensional array of something. What would it be an
array of? Since the index values are not numeric types it could not be
an array of integers. It would need to be an array of Suits and Pips,
expressed as an Ada record, which is what a Card is defined to be.
This means that I do not have any advantage in using an indexing
array. I still need to handle multiple copies of each full deck.

The next problem you have is creating random instances of that record
type for your shuffle procedure. The problem gets a lot more complex
and a lot uglier if we follow this path.

Jim Rogers
Jul 17 '05 #14
"Raoul Watson" <Wa*****@Intell igenCIA.com> wrote in
news:NA******** ********@nwrdny 01.gnilink.net:


I agree. Why not pick randomly from a sequential deck. No one knows
the deck is "not shuffled" and drawing randomly is the same as having
a shuffled deck
:)


Because that is not efficient.
Every card must have a flag indicating whether or not it has been dealt.
Your random pick will frequently pick a card that has already been dealt,
requiring you to pick another card until you find one that has not yet
been dealt. This problem gets worse as you deal more cards. Dealing the
last card from the deck can be very slow.

The efficient algorithm is:

Assuming the deck array is indexed from 0 through 52:

Current_Index = 0

while Current_Index < 51 loop
swap(Card[Current_Index],
Card[(random * (52 - Current_Index + 1)) + Current_Index];
Current_Index = Current_Index + 1;
end loop;

The above algorithm assumes the swap procedure will exchange the
array values, and that the random function will return a random
number between 0 and 1. It also assumes an implicit conversion
from floating point values to integer values.

Note that the shuffle algorithm marches through the array.
It ensures that every position is swapped with some other
position. It performs N-1 swaps if N is the number of cards
in the deck.

Once the array has been shuffled you only need to keep track
of which index is the next to be dealt. No unnecessary
repeated attempts.

Jim Rogers
Jul 17 '05 #15

"JC" <no************ @hotmail.com> wrote in message
news:bk******** **@sun-news.laserlink. net...
I want to shuffle a deck of 52 cards.


This is just for fun, since there has been some discussion about "really random"
and stuff.

This code does not attempt to be truly random; instead, it attempts to simulate
what happens when humans shuffle cards. That is, it splits the deck into two
piles, and then drops cards alternately from the two piles. The initial split is
26 +/- 4 in each pile, and each drop is between 1 to 4 cards. The PNorm function
returns more 1's than 4's, but by a crude mechanism, not a real distribution.

The interesting thing is how much order remains after just one shuffle. Don't
expect real randomization from just one shuffle of a deck!

Steve

---this is the form code for a form with a single button called cmdShuffle.

Option Explicit

Private mDeck(1 To 52) As Integer
Private mNewDeck(1 To 52) As Integer
Private mNewCards As Integer

Private Sub Form_Load()
Dim n As Integer

'open the new pack of cards
For n = 1 To 52
mDeck(n) = n
Debug.Print mDeck(n),
Next n
Debug.Print

'seed the random generator
Randomize Timer

End Sub

Private Sub cmdShuffle_Clic k()
Dim nLeftPile As Integer
Dim nRightPile As Integer
Dim nSplit As Integer
Dim n As Integer

'reset index
mNewCards = 0

'split into approximately two halves
nSplit = 24 + PNorm()
nLeftPile = nSplit
nRightPile = 52 - nLeftPile

'alternately drop some from each pile, till they are all gone
Do Until nLeftPile = 0 And nRightPile = 0
Call DropSome(nLeftP ile, 0)
Call DropSome(nRight Pile, nSplit)
Loop

'copy the new deck into the main deck
For n = 1 To 52
mDeck(n) = mNewDeck(n)
Debug.Print mDeck(n),
Next n
Debug.Print

End Sub

Private Sub DropSome(ByRef Pile As Integer, ByVal Offset As Integer)
Dim nDrop As Integer
Dim n As Integer

If Pile > 0 Then

'decide how many to drop from this pile
nDrop = PNorm()
If nDrop > Pile Then
nDrop = Pile
End If

'drop each card from the "pile" into the new deck
For n = 1 To nDrop
mNewCards = mNewCards + 1
mNewDeck(mNewCa rds) = mDeck(Offset + Pile)
Pile = Pile - 1
Next n

End If

End Sub

Private Function PNorm() As Integer
'a very pseudo normal random number - more like a triangle, actually...

Dim nNum As Integer

'random int from 0 to 9
nNum = CInt(Rnd * 10)

If nNum < 4 Then
'(0 to 3) average 40% of these
PNorm = 1

ElseIf nNum < 7 Then
'(4 to 6) average 30% of these
PNorm = 2

ElseIf nNum < 9 Then
'(7 to 8) average 20% of these
PNorm = 3

Else
'(9) average 10% of these
PNorm = 4
End If

End Function
Jul 17 '05 #16
Arthur J. O'Dwyer wrote:
On Wed, 24 Sep 2003, Calum wrote:
When you swap two things you need a temporary**! Why loop to 1000? You
can loop just 52 times if you swap each card with a randomly chosen other.

for(int c=0; c<52; ++c)
{
Card &a = cards[c];
Card &b = cards[rnd(52)]; // For a suitably defined rnd

Card t = a; // Not expensive if Card is 4 bytes or 1 byte
a = b;
b = t;
}

Geez Louise, isn't this a FAQ *somewhere*?
The above algorithm *does* *not* *generate*
*a* *uniform* *distribution*! Get that through
your head! Arrrgh!


Feel better now?

Oh, ooops, did I write rnd(52) instead of rnd(c)? Must have gotten
corrupted on the news server somehow, cough splutter...

Yes the above algorithm is ever-so-slightly biased, linear-congruential
RNG notwithstanding . *Hangs head in shame* :-)
** There is also an XOR hack:
a = a^b, b = a^b, a = a^b;
saves a register spill :-)

....at the cost of producing incorrect results
when &a == &b, as is likely with your algorithm
as it stands.


Good point, but I didn't use it for this algorithm did I? It was just
in case someone took issue with the word "need". I thought that little
snippet was a bit of fun, oh dear.

Calum

Jul 17 '05 #17

"James Rogers" <ji************ **@att.net> wrote in message
news:Xn******** *************** *******@204.127 .36.1...
"Raoul Watson" <Wa*****@Intell igenCIA.com> wrote in
news:NA******** ********@nwrdny 01.gnilink.net:


I agree. Why not pick randomly from a sequential deck. No one knows
the deck is "not shuffled" and drawing randomly is the same as having
a shuffled deck
:)
Because that is not efficient.
Every card must have a flag indicating whether or not it has been dealt.
Your random pick will frequently pick a card that has already been dealt,
requiring you to pick another card until you find one that has not yet
been dealt.


Jim.. if you draw the card you simply zero the array. If it's zero it's not
pickable.
This problem gets worse as you deal more cards. Dealing the last card from the deck can be very slow.


Well.. you either haven't been programming for very long or you have no idea
about processor power. On a very old 166 Pentium 1, VB can loop 50,000
(fifty thousand times) executing a random statement plus two IF then
statements in less than 8/10 eight tenth of a second. Slow ? Yeah sure not
nano second.

Why don't you try this on your PC.. if it takes more than three-tenth of a
second, you have a very slow PC :)

Private Sub Command1_Click( )
Dim k, x
Label1.Caption = Timer
For x = 1 To 50000
k = Int((52 * Rnd) + 1)
Next x
Label2.Caption = Timer
Label3.Caption = Val(Label2.Capt ion) - Val(Label1.Capt ion)
End Sub

Jul 17 '05 #18
"Raoul Watson" <Wa*****@Intell igenCIA.com> wrote in
news:WQ******** *********@nwrdn y01.gnilink.net :

"James Rogers" <ji************ **@att.net> wrote in message
news:Xn******** *************** *******@204.127 .36.1...
"Raoul Watson" <Wa*****@Intell igenCIA.com> wrote in
news:NA******** ********@nwrdny 01.gnilink.net:
>
>
> I agree. Why not pick randomly from a sequential deck. No one knows
> the deck is "not shuffled" and drawing randomly is the same as
> having a shuffled deck
>:)
Because that is not efficient.
Every card must have a flag indicating whether or not it has been
dealt. Your random pick will frequently pick a card that has already
been dealt, requiring you to pick another card until you find one
that has not yet been dealt.


Jim.. if you draw the card you simply zero the array. If it's zero
it's not pickable.


That is yet another inefficiency. Did you ever study algorithms?
This problem gets worse as you deal more cards. Dealing the last card from the deck can be very slow.


Well.. you either haven't been programming for very long or you have
no idea about processor power. On a very old 166 Pentium 1, VB can
loop 50,000 (fifty thousand times) executing a random statement plus
two IF then statements in less than 8/10 eight tenth of a second. Slow
? Yeah sure not nano second.


Wrong on both counts. I have been programming since 1972.
I do understand the speed of a 3 GHz processor.

Obviously you come from the school of thought that creates fatware.
Do you really believe that efficiency is unnecessary if a processor
is fast? 8/10 of a second on a multi-GHz processor is an eternity.
Why do you want to buy a fast processor then force it to execute
slow code? That simply wastes the resources of the processor.

Why don't you try this on your PC.. if it takes more than three-tenth
of a second, you have a very slow PC :)

<snip irrelevant example>

0.3 seconds. Let's see, that is 300000 nanoseconds, or 900000 cycles for
a 3GHz processor.

An algorithm that takes 300000 cycles (0.1 seconds) is very inefficient
compared to another algorithm that achieves the same goals yet takes only
5769 cycles (0.002 seconds). Why are you satisfied with making your
fast processor behave as though it was operating at only 2% of its
actual speed? You are effectively making your 3GHz processor run at 58
MHz. By today's standards that is terrible performance.

If you want to benefit from all your system's performance you cannot
run grossly inefficient software on the machine. Overall system performance
is achieved through the combined effects of fast hardware and efficient
software. Just as slow hardware will reduce your performance, inefficient
software will also reduce performance. It is a waste of money to buy
fast hardware so that you can run inefficient software.

You buy fast hardware because performance matters. You then claim that it
is acceptable to run slow software because performance does not matter.
I do not think such a position is well reasoned.

Jim Rogers
Jul 17 '05 #19
In article <Xn************ *************** *@204.127.36.1> ,
James Rogers <ji************ **@att.net> wrote:

The reason is pretty simple. Both Pips and Suits are defined as
enumerated types. In Ada enumerated types are non-numeric discrete
types. There is no multiplication operation defined for any
emumerated type.


This is not what I meant. If you can get the number of elements in an
enumerated type (I assume the attribute is called Range):

Suits'Range = 4
Pips'Range = 13

So if you take these two numbers, surely you can multiply them and get
52 as a result. So instead of using a hardcoded number, you would use
the actual number of all possible cards as defined by those two
types. That would allow you to change the definition of Pips or Suits
and avoid having to recalculate by hand and change another constant in
a program.

I guess if you make a mistake in a constant, the Initialize function
will generate an exception. If you use Suits'Range * Pips'Range, it will
not as the types will be consistant with the range of Deck_Index.
--
Gorazd Bozic <gb*@email.si >
Jul 17 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
2245
by: DaveLessnau | last post by:
I'm trying to learn C on my own and, apparently, my brain went on vacation somewhere. I just can't figure out how to parse the following function call: "void fillDeck( Card * const wDeck, const char * wFace, const char * wSuit)" Card is aliased before that call with: "typedef struct card Card"
6
6225
by: CaseyB | last post by:
If I wanted to create a game like Solitaire that would first randomly shuffle a deck of cards, I figured out that all I had to use is the Random() class or rnd and make sure I use the Randomize function so as not to get the same card twice. BUT I noticed that some Solitaire games allow you to select one of the 4,294,967,296 possibilities in a 52 card deck. I want to do something similar, after I shuffle the deck I want to show the number...
4
9196
by: Pratik | last post by:
For the time being, I'm doing a simple swap method for my deck of cards using the random number generator in cstdlib. I've created a dynamic array of a type class Card. When I go to shuffle it and then later print the shuffled deck, some of the values overlap -- I can't figure out why. Here's my code: void shuffle() { for (counter = 0; counter < 120; counter++) {
4
1502
by: tvance929 | last post by:
Hey everyone, I created a theDeck class that creates a 52 card int List. Inside of this class I have a ShuffleCards method. I simply want 2 seperate decks that I can then shuffle and then count a few cards out of each deck.
8
5059
by: l1nuxxx | last post by:
I have a file well call file.pl. It's a card sorting program. I need to create a lib fuction with part of the original file that shuffles the deck of cards. After it shuffles the first deck and deals a hand of cards I need it to call the shuffling function again before dealing another hand. I call the lib function file file-lib.pl. here's the contents i have for file.pl #!/usr/bin/perl require 'file-lib.pl'; my @startingdeck = ("A...
0
9793
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10774
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10526
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10206
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9315
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7746
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5780
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4411
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3076
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.