Shuffle card deck

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • JC

    Shuffle card deck

    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


  • James Rogers

    #2
    Re: Shuffle card deck

    "JC" <not_clancy1965 @hotmail.com> wrote in
    news:bkr39v$m0k $1@sun-news.laserlink. net:
    [color=blue]
    > 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[/color]

    Your random values are not guaranteed to be unique. When shuffling
    cards you have only one value of each card in a normal deck.

    You need an entirely different algorithm.

    Following is an example of defining a deck of cards, including the
    shuffle routine, using the Ada language:

    First I define a package specification for cards:

    -----------------------------------------------------------------------
    -- Cards.ads
    -- Package implementing a standard deck of playing cards
    -----------------------------------------------------------------------

    package Cards is

    type Card is private;

    -- Print the value of a card
    procedure Print(Item : in Card);

    type Deck is private;

    -- Create an initial deck (open a new deck of cards)
    function Fill_Deck return Deck;

    -- Print all the cards remaining in a deck
    procedure Print(Item : in Deck);

    -- Shuffle the deck (randomize the order of the cards in the deck)
    procedure Shuffle(The_Dec k : in out Deck);

    -- Deal the next card from the deck
    procedure Deal(The_Card : out Card; From : in out Deck);

    -- Return the number of cards left in the deck
    function Cards_Left(In_D eck : Deck) return Natural;

    -- Deck_Empty exception raised when trying to deal from an empty deck.
    Deck_Empty : Exception;

    private

    -- Define the face values of the cards
    type Pips is (Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten,
    Jack, Queen, King, Ace);

    -- Define the card suits
    type Suits is (Hearts, Spades, Clubs, Diamonds);

    -- A card is defined by its combination of face value
    -- and suit.
    type Card is record
    Pip : Pips;
    Suit : Suits;
    end record;

    -- Define the number of cards in a standard deck.
    subtype Deck_Index is integer range 1..52;

    -- Cards in the deck are accessed through an order list.
    -- The values in the order list are sorted to create a
    -- shuffled deck.
    type Order_List is array(Deck_Inde x) of Deck_Index;

    -- A deck is an order list, an index into the order list
    -- indicating the next card to deal, and a count of the
    -- number of cards left (not yeat dealt) in the deck.
    type Deck is record
    This_Order : Order_List;
    Deal_Next : Deck_Index := Deck_Index'Firs t;
    Num_Left : Natural := 0;
    end record;
    end Cards;

    Next I define the implementation of all the routines declared in
    the package specification above:

    -----------------------------------------------------------------------
    -- Cards.adb
    -- Implementation of the Cards package
    -----------------------------------------------------------------------

    with Ada.Numerics.Fl oat_Random;
    with Ada.Text_Io;

    package body Cards is

    ----------------
    -- The Card_Deck array is the only array in this package
    -- actually containing Card objects.
    -- A Deck is a data structure with an array of indexes into
    -- this single Card_Deck.
    -- A Deck is shuffled by randomizing that array of indexes.
    ----------------
    type Card_Deck is array(Deck_Inde x) of Card;

    --------------
    -- Internal Function: Initialize
    -- Purpose: Initialize the value of the common Card_Deck
    -- This function is called only once during the elaboration of
    -- this package. It is used to initialize the values in the
    -- All_Decks array.
    --------------
    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;

    All_Decks : constant Card_Deck := Initialize;

    -----------
    -- Procedure: Print
    -- Purpose: Print the value of a card on standard output
    -- The enumeration labels will be printed using instantiations
    -- of the generic package Ada.Text_IO.Enu meration_Io.
    -----------
    procedure Print(Item : in Card) is
    package Pip_Io is new Ada.Text_Io.Enu meration_IO(Pip s);
    package Suit_Io is new Ada.Text_Io.Enu meration_Io(Sui ts);
    begin
    Pip_Io.Put(Item => Item.Pip);
    Ada.Text_Io.Put (Item => " of ");
    Suit_Io.Put(Ite m => Item.Suit);
    Ada.Text_Io.New _Line;
    end Print;

    -----------------
    -- Function: Fill_Deck
    -- Purpose: Create a new card deck with all cards in order
    ----------------
    function Fill_Deck return Deck is
    Result : Deck;
    begin
    for Temp_Index in Deck_Index'Rang e loop
    Result.This_Ord er(Temp_Index) := Temp_Index;
    end loop;
    Result.Num_Left := Deck_Index'Last ;
    return Result;
    end Fill_Deck;

    ---------
    -- Procedure: Print
    -- Purpose: Print all the cards remaining in the deck
    ---------

    procedure Print(Item : in Deck) is
    begin
    if Item.Num_Left > 0 then
    for Temp_Index in Item.Deal_Next. .Deck_Index'Las t loop
    Print(All_Decks (Item.This_Orde r(Temp_Index))) ;
    end loop;
    else
    Ada.Text_Io.Put _Line("The deck is empty.");
    end if;
    end Print;

    ------------
    -- Procedure Swap
    -- Exchange two Deck_Index values
    -- This procedure is visible only to functions and procedures
    -- defined in this package body.
    --------------
    procedure Swap(Left, Right : in out Deck_Index) is
    Temp : Deck_Index := Left;
    begin
    Left := Right;
    Right := Temp;
    end Swap;

    -------------
    -- Procedure: Shuffle
    -- Purpose: Randomize the This_Order array for a deck to force
    -- random access to the deck of cards
    --
    -- This algorithm is order O(n) and will work with any discrete
    -- index type.
    -- The Ada.Numerics.Fl oat_Random routine is used so that the
    -- random number generator is reset only once per shuffle. This
    -- produces more random results than can be achieved by
    -- resetting the generator for each iteration as would be needed
    -- if the Ada.Numerics.Di screte_Random package had been used.
    ------------

    procedure Shuffle(The_Dec k : in out Deck) is
    use Ada.Numerics.Fl oat_Random;
    Seed : Generator;
    -- Max_Search is set to the 2nd to last value in Deck_Index
    Max_Search : Deck_Index := Deck_Index'Pred (Deck_Index'Las t);
    Difference : Integer;
    Rand_Value : Integer;
    Swap_Val : Deck_Index;
    begin
    Reset(Seed);
    The_Deck.Deal_N ext := Deck_Index'Firs t;
    The_Deck.Num_Le ft := Deck_Index'Last ;
    for Index in Deck_Index'Firs t .. Max_Search loop
    Difference := Deck_Index'Pos( Deck_Index'Last ) -
    Deck_Index'Pos( Index);
    Rand_Value := Integer( Random(Seed) * Float(Differenc e)) +
    Deck_Index'Pos( Index);
    Swap_Val := Deck_Index'Val( Rand_Value);
    Swap(The_Deck.T his_Order(Index ),
    The_Deck.This_O rder(Swap_Val)) ;

    end loop;
    end Shuffle;

    --------------------------------------------------------------------
    -- The Deal procedure produces the next card from the deck.
    -- It also updates the Deck data structure to account for
    -- another card being removed from the Deck, and finally, it
    -- updates the Deck's Deal_Next index to point to the next card
    -- to deal from the deck.
    -------------------------------
    procedure Deal(The_Card : out Card; From : in out Deck) is
    begin
    if From.Num_Left > 0 then
    The_Card := All_Decks(From. This_Order(From .Deal_Next));
    From.Num_Left := From.Num_Left - 1;
    if From.Deal_Next < Deck_Index'Last then
    From.Deal_Next := From.Deal_Next + 1;
    end if;
    else
    -- raise the Deck_Empty exception
    raise Deck_Empty;
    end if;
    end Deal;

    --------------------------------------------------------------------
    -- The function Cards_Left simply reports the number of cards not
    -- yet dealt from the deck. This number can be anything from 0
    -- through Deck_Index'Last .
    --------------------------------------------------------------------
    function Cards_Left(In_D eck : Deck) return Natural is
    begin
    return In_Deck.Num_Lef t;
    end Cards_Left;
    end Cards;

    Finally, I show a procedure to create a deck of cards and do the
    shuffling:

    -----------------------------------------------------------------------
    -- Card_Deck.adb
    -- This procedure is a test driver for the Cards package
    -----------------------------------------------------------------------

    with Ada.Text_Io;
    with Cards;

    procedure Card_Deck is

    My_Deck : Cards.Deck;
    This_Card : Cards.Card;

    begin

    -- Create a new deck of cards, like opening a new deck of
    -- cards. The deck returned is sorted by suit and value.
    My_Deck := Cards.Fill_Deck ;
    Ada.Text_Io.Put _Line("Initial Deck:");
    Cards.Print(My_ Deck);

    -- Shuffle the deck so that the cards are accessed in a
    -- random order.
    Cards.Shuffle(M y_Deck);
    Ada.Text_Io.New _Line(2);
    Ada.Text_Io.Put _Line("Shuffled Deck:");
    Cards.Print(My_ Deck);

    -- Deal out the cards, printing each dealt card.
    Ada.Text_Io.New _Line(2);
    Ada.Text_Io.Put _Line("Printing each card as it is dealt:");
    while Cards.Cards_Lef t(In_Deck => My_Deck) > 0 loop
    Cards.Deal(The_ Card => This_Card, From => My_Deck);
    Cards.Print(Thi s_Card);
    end loop;

    -- Attempt to deal one more card from the deck. This will raise
    -- the Deck_Empty exception.
    Ada.Text_Io.New _Line(2);
    Ada.Text_Io.Put _Line("Attempti ng to deal from an empty deck:");

    -- the following unnamed block encapsulates its own exception
    -- handler for the Cards.Deck_Empt y exception.
    begin
    Cards.Deal(The_ Card => This_Card, From => My_Deck);
    Cards.Print(Thi s_Card);
    exception
    when Cards.Deck_Empt y =>
    Ada.Text_Io.Put _Line(
    "ERROR: You attempted to deal from an empty deck.");
    end;

    -- Attempt to print an empty deck
    Cards.Print(My_ Deck);

    end Card_Deck;

    Jim Rogers

    Comment

    • JC

      #3
      Re: Shuffle card deck


      "James Rogers" <jimmaureenroge rs@att.net> wrote in message
      news:Xns93FFDD5 B76ABDjimmauree nrogers@204.127 .36.1...[color=blue]
      > "JC" <not_clancy1965 @hotmail.com> wrote in
      > news:bkr39v$m0k $1@sun-news.laserlink. net:
      >[color=green]
      > > 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[/color]
      >
      > Your random values are not guaranteed to be unique. When shuffling
      > cards you have only one value of each card in a normal deck.
      >
      > You need an entirely different algorithm.
      >
      > Following is an example of defining a deck of cards, including the
      > shuffle routine, using the Ada language:
      > Jim Rogers[/color]

      Thanks for the response. What I am looking for is just a Randomizing
      routine that could be applied to any situation.

      I have already created an array for the cards. I just want to randomize
      the index which I address them by, but sometimes 2 or even three cards of
      same suit and value are being drawn. I am guessing that my index itself has
      to have the duplicate values, since each of my 52 card array is unique.
      Don't know how much sense this makes to anyone.

      I wrote a video poker program on my Commodore 64 about twenty years ago,
      which was the first and last time I ever tried to write a real program. It
      worked great in that I got it to do exactly what I wanted, and I used a
      routine similar to the above, without have duplicate cards showing up.



      Comment

      • Steve Gerrard

        #4
        Re: Shuffle card deck

        In your code, C1 and C2 are not the indexes of the cards, they are the values.
        Yet you use them to decide which two cards to exchange, instead of the indexes
        where they came from.

        Say the first Int(Rnd * 52) came up 22, and the second one came up 37. Say that
        Cards(22) = 17, and Cards(37) = 24. Your code would then change the value of
        Cards(17) to 24 (same as Cards(37), which is unchanged), and change Cards(24) to
        17 (same as Cards(22), also unchanged). Now you have two 17's and two 22's.

        Try substituting this in the loop:

        c1 = (Int(Rnd * 52)) ' returns an index from 0 to 51
        c2 = (Int(Rnd * 52)) ' returns an index from 0 to 51

        temp = Cards(c1) 'save value of cards(c1)
        Cards(c1) = Cards(c2) 'assign cards(c2) to cards(c1)
        Cards(c2) = temp 'assign old cards(c1) to cards(c2)

        If c1 = c2, there is not much point in swapping a card with itself, so you could
        put in a test to skip those.

        Steve

        "JC" <not_clancy1965 @hotmail.com> wrote in message
        news:bkr39v$m0k $1@sun-news.laserlink. net...[color=blue]
        > 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
        >
        >[/color]


        Comment

        • JC

          #5
          Re: Shuffle card deck


          "Steve Gerrard" <notstevegerrar d@comcast.net> wrote in message
          news:YTSdnaELZd-XgeyiU-KYvg@comcast.co m...[color=blue]
          > In your code, C1 and C2 are not the indexes of the cards, they are the[/color]
          values.[color=blue]
          > Yet you use them to decide which two cards to exchange, instead of the[/color]
          indexes[color=blue]
          > where they came from.
          >
          > Say the first Int(Rnd * 52) came up 22, and the second one came up 37. Say[/color]
          that[color=blue]
          > Cards(22) = 17, and Cards(37) = 24. Your code would then change the value[/color]
          of[color=blue]
          > Cards(17) to 24 (same as Cards(37), which is unchanged), and change[/color]
          Cards(24) to[color=blue]
          > 17 (same as Cards(22), also unchanged). Now you have two 17's and two[/color]
          22's.[color=blue]
          >
          > Try substituting this in the loop:
          >
          > c1 = (Int(Rnd * 52)) ' returns an index from 0 to 51
          > c2 = (Int(Rnd * 52)) ' returns an index from 0 to 51
          >
          > temp = Cards(c1) 'save value of cards(c1)
          > Cards(c1) = Cards(c2) 'assign cards(c2) to cards(c1)
          > Cards(c2) = temp 'assign old cards(c1) to cards(c2)
          >
          > If c1 = c2, there is not much point in swapping a card with itself, so you[/color]
          could[color=blue]
          > put in a test to skip those.
          >
          > Steve
          >[/color]

          That's it! I know I shouldn't try to think on an empty brain...... I was not
          assigning Cards(c1) = Cards(c2) but instead, going straight to Cards(c1) =
          c2.

          Thanks, Steve!


          Comment

          • James Rogers

            #6
            Re: Shuffle card deck

            "JC" <not_clancy1965 @hotmail.com> wrote in
            news:bkr5qg$2b3 $1@sun-news.laserlink. net:
            [color=blue]
            > Thanks for the response. What I am looking for is just a Randomizing
            > routine that could be applied to any situation.[/color]

            The Shuffle procedure in my example does what you want.
            It is a reasonably efficient way to randomize a collection of objects
            and avoid duplicates.
            [color=blue]
            >
            > I have already created an array for the cards. I just want to
            > randomize
            > the index which I address them by, but sometimes 2 or even three cards
            > of same suit and value are being drawn. I am guessing that my index
            > itself has to have the duplicate values, since each of my 52 card
            > array is unique. Don't know how much sense this makes to anyone.[/color]

            There is nothing wrong with moving a single card more than once
            during a shuffle. What is wrong is having the same card value more
            than once in a single deck.

            Your deck is not properly constructed if you are generating the values
            more than once.

            Note that the example I showed created and initialized a deck of cards
            before shuffling them. No new card values were created. Only the order
            of the values was changed.

            My example optimized this a bit by using an ordering array, rather than
            actually moving about the cards in the card deck. The reason for this
            is that the cards may be constructed using a larger data representation,
            including information such as suit and pip value. Moving large values
            is less efficient than simply moving index values. My example simply
            moves around the index values.

            Using this scheme, I only have one deck of actual card values. The user
            "deck" really contains an ordering array of index values. This allows
            minimum use of memory and maximum shuffling speed. Users can appear to
            have individual decks, but all decks refer to a single set of actual
            card values. Each user simply sees those values in a different order.
            [color=blue]
            >
            > I wrote a video poker program on my Commodore 64 about twenty years
            > ago,
            > which was the first and last time I ever tried to write a real
            > program. It worked great in that I got it to do exactly what I wanted,
            > and I used a routine similar to the above, without have duplicate
            > cards showing up.[/color]

            My suspicion is that your current routine is somehow different from the
            one you used twenty years ago. That difference just might be important.

            Jim Rogers

            Comment

            • xyz

              #7
              Re: Shuffle card deck

              ' initialize the deck
              For i = 1 To 52
              cards(i) = i
              Next i

              ' shuffle the deck
              ' this shuffling assures that each card
              ' changes position at least once
              For N = 52 To 2 Step -1
              K = Int(N * Rnd) + 1
              TEMP = cards(N)
              cards(N) = cards(K)
              cards(K) = TEMP
              Next N

              ' array cards(i) now has the shuffled deck


              ==========
              On Tue, 23 Sep 2003 20:39:21 -0700, "JC" <not_clancy1965 @hotmail.com>
              wrote:
              [color=blue]
              >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
              >[/color]

              Comment

              • Calum

                #8
                Re: Shuffle card deck

                JC wrote:[color=blue]
                > 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)[/color]

                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;
                }


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

                Comment

                • Gorazd Bozic

                  #9
                  Re: Shuffle card deck

                  In article <Xns93FFDD5B76A BDjimmaureenrog ers@204.127.36. 1>,
                  James Rogers <jimmaureenroge rs@att.net> wrote:[color=blue]
                  >[/color]
                  ....[color=blue]
                  > -- Define the number of cards in a standard deck.
                  > subtype Deck_Index is integer range 1..52;[/color]

                  Just curious -- why not

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

                  Is that not possible? That would be consistent with the Initialize
                  function:
                  [color=blue]
                  > 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;[/color]

                  Cheers,
                  Gorazd
                  --
                  Gorazd Bozic <gbx@email.si >

                  Comment

                  • Rick Rothstein

                    #10
                    Re: Shuffle card deck

                    > I am very new to programming and learning on my own.[color=blue]
                    >
                    > Why do I keep getting duplicate values using this code? I want to shuffle[/color]
                    a[color=blue]
                    > 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[/color]

                    You already have answers to your main question, but I thought I'd offer this
                    previous post of mine in case the 2nd method used in it seemed useful to
                    you.

                    Rick - MVP

                    Not sure what "Hit or Miss" solitaire is, but here are two versions of a
                    card shuffling routine (depending on how you store the cards) that I have
                    posted previously.

                    FIRST METHOD
                    =============== ==
                    The following is a generalized "shuffling" routine. Give it an array of
                    elements and it will put them in random order and return the randomized
                    elements back in the original array that was passed to it. It only visits
                    *each* array element *once* so it is quick. The code takes care of running
                    the Randomize statement one time only (which is all that is necessary).

                    Sub RandomizeArray( ArrayIn As Variant)
                    Dim X As Long
                    Dim RandomIndex As Long
                    Dim TempElement As Variant
                    Static RanBefore As Boolean
                    If Not RanBefore Then
                    RanBefore = True
                    Randomize
                    End If
                    If VarType(ArrayIn ) >= vbArray Then
                    For X = UBound(ArrayIn) To LBound(ArrayIn) Step -1
                    RandomIndex = Int((X - LBound(ArrayIn) + 1) * _
                    Rnd + LBound(ArrayIn) )
                    TempElement = ArrayIn(RandomI ndex)
                    ArrayIn(RandomI ndex) = ArrayIn(X)
                    ArrayIn(X) = TempElement
                    Next
                    Else
                    'The passed argument was not an array
                    'Put error handler here, such as . . .
                    Beep
                    End If
                    End Sub

                    The passed array may be of any normal type -- integer, string, single, etc.
                    The neat thing is, if you pass an already randomized array to this routine,
                    those randomly ordered elements will be randomize -- sort of like shuffling
                    an already shuffled deck of cards. In your case, simply set up the array
                    (probably Global or Static if you want to use it over and over) something
                    like this

                    Dim DeckOfCards(1 To 52) As Long
                    For X = 1 To 52
                    DeckOfCards(X) = X
                    Next

                    and to shuffle (randomize) it, simply call

                    RandomizeArray DeckOfCards

                    Each array element will now hold a unique, random number from 1 through 52
                    for the above example.


                    SECOND METHOD
                    =============== ==
                    Here is another take on the same routine which actually returns "named"
                    cards such as 3 of Hearts (here your DeckOfCards is declared as a String:

                    Sub ShuffleDeck(Dec k() As String)
                    Dim X As Integer
                    Dim TempInt As Integer
                    Dim TempCard As String
                    Static TempDeck(1 To 52) As String
                    Static RanBefore As Boolean
                    If Not RanBefore Then
                    RanBefore = True
                    Randomize
                    If UBound(Deck) <> 52 Then
                    'Programmer passed an improper array
                    MsgBox "Deck array is dimensioned incorrectly"
                    Exit Sub
                    ElseIf TempDeck(52) = "" Then
                    'Initialize the deck of cards
                    For X = 1 To 52
                    If ((X - 1) Mod 13) = 0 Then
                    TempDeck(X) = "Ace"
                    ElseIf ((X - 1) Mod 13) = 10 Then
                    TempDeck(X) = "Jack"
                    ElseIf ((X - 1) Mod 13) = 11 Then
                    TempDeck(X) = "Queen"
                    ElseIf ((X - 1) Mod 13) = 12 Then
                    TempDeck(X) = "King"
                    Else
                    TempDeck(X) = CStr(1 + ((X - 1) Mod 13))
                    End If
                    TempDeck(X) = TempDeck(X) & " of "
                    If (X - 1) \ 13 = 0 Then
                    TempDeck(X) = TempDeck(X) & "Spades"
                    ElseIf (X - 1) \ 13 = 1 Then
                    TempDeck(X) = TempDeck(X) & "Hearts"
                    ElseIf (X - 1) \ 13 = 2 Then
                    TempDeck(X) = TempDeck(X) & "Diamonds"
                    ElseIf (X - 1) \ 13 = 3 Then
                    TempDeck(X) = TempDeck(X) & "Clubs"
                    End If
                    Next
                    End If
                    End If
                    'Let us shuffle the deck
                    X = 52
                    For X = 52 To 1 Step -1
                    TempInt = Int(X * Rnd + 1)
                    Deck(X) = TempDeck(TempIn t)
                    TempCard = TempDeck(X)
                    TempDeck(X) = TempDeck(TempIn t)
                    TempDeck(TempIn t) = TempCard
                    Next
                    End Sub

                    Everything is self-contained in this version; just pass it an array
                    dimensioned between 1 and 52 as in this example use:

                    Private Sub Command1_Click( )
                    Dim MyDeck(1 To 52) As String
                    ShuffleDeck MyDeck
                    Debug.Print MyDeck(1) & ", " & MyDeck(4) & ", " & MyDeck(43)
                    End Sub


                    Comment

                    • Rick Rothstein

                      #11
                      Re: Shuffle card deck

                      > Private Sub Command1_Click( )[color=blue]
                      > Dim MyDeck(1 To 52) As String
                      > ShuffleDeck MyDeck
                      > Debug.Print MyDeck(1) & ", " & MyDeck(4) & ", " & MyDeck(43)
                      > End Sub[/color]

                      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


                      Comment

                      • Arthur J. O'Dwyer

                        #12
                        Re: Shuffle card deck


                        On Wed, 24 Sep 2003, Calum wrote:[color=blue]
                        >
                        > 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;
                        > }[/color]

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

                        [color=blue]
                        > ** There is also an XOR hack:
                        > a = a^b, b = a^b, a = a^b;
                        > saves a register spill :-)[/color]

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

                        -Arthur

                        Comment

                        • Raoul Watson

                          #13
                          Re: Shuffle card deck


                          "Mel Wilson" <mwilson@the-wire.com> wrote in message
                          news:cibc/ks/KzxL089yn@the-wire.com...[color=blue]
                          > 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.[/color]

                          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
                          :)


                          Comment

                          • James Rogers

                            #14
                            Re: Shuffle card deck

                            gbx@email.si (Gorazd Bozic) wrote in news:bks861$hch $1@planja.arnes .si:
                            [color=blue]
                            > In article <Xns93FFDD5B76A BDjimmaureenrog ers@204.127.36. 1>,
                            > James Rogers <jimmaureenroge rs@att.net> wrote:[color=green]
                            >>[/color]
                            > ...[color=green]
                            >> -- Define the number of cards in a standard deck.
                            >> subtype Deck_Index is integer range 1..52;[/color]
                            >
                            > Just curious -- why not
                            >
                            > subtype Deck_Index is integer range Pips'Range * Suits'Range;[/color]

                            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.
                            [color=blue]
                            >
                            > Is that not possible? That would be consistent with the Initialize
                            > function:
                            >[color=green]
                            >> 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;[/color][/color]


                            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

                            Comment

                            • James Rogers

                              #15
                              Re: Shuffle card deck

                              "Raoul Watson" <WatsonR@Intell igenCIA.com> wrote in
                              news:NApcb.1846 $yU5.627@nwrdny 01.gnilink.net:
                              [color=blue]
                              >
                              >
                              > 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
                              >:)[/color]

                              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

                              Comment

                              Working...