449,071 Members | 1,089 Online Need help? Post your question and get tips & solutions from a community of 449,071 IT Pros & Developers. It's quick & easy.

# Shuffle card deck

 P: n/a 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 #1
23 Replies

 P: n/a "James Rogers" wrote in message news:Xn******************************@204.127.36.1 ... "JC" wrote in news:bk**********@sun-news.laserlink.net: 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 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 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. Jul 17 '05 #3

 P: n/a 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" wrote in message news:bk**********@sun-news.laserlink.net... 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 #4

 P: n/a "Steve Gerrard" wrote in message news:YT********************@comcast.com... 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 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! Jul 17 '05 #5

 P: n/a "JC" wrote in news:bk**********@sun-news.laserlink.net: Thanks for the response. What I am looking for is just a Randomizing routine that could be applied to any situation. 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. 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. 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. 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. 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 Jul 17 '05 #6

 P: n/a ' 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" wrote: 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 adeck of 52 cards. The logic seems right to me.RandomizeFor 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 CTIA Jul 17 '05 #7

 P: n/a JC wrote: 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) 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 :-) Jul 17 '05 #8

 P: n/a In article , James Rogers 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; 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'First; begin for The_Suit in Suits loop for The_Pip in Pips loop Result(Temp_Index) := (The_Pip, The_Suit); Temp_Index := Temp_Index + 1; end loop; end loop; return Result; end Initialize; Cheers, Gorazd -- Gorazd Bozic Jul 17 '05 #9

 P: n/a > 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 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(RandomIndex) ArrayIn(RandomIndex) = 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(Deck() 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(TempInt) TempCard = TempDeck(X) TempDeck(X) = TempDeck(TempInt) TempDeck(TempInt) = 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 Jul 17 '05 #10

 P: n/a > 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

 P: n/a 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

 P: n/a "Mel Wilson" 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

 P: n/a gb*@email.si (Gorazd Bozic) wrote in news:bk**********@planja.arnes.si: In article , James Rogers 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'First; begin for The_Suit in Suits loop for The_Pip in Pips loop Result(Temp_Index) := (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

 P: n/a "Raoul Watson" wrote in news:NA****************@nwrdny01.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

 P: n/a "JC" 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_Click() 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(nLeftPile, 0) Call DropSome(nRightPile, 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(mNewCards) = 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

 P: n/a 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? Youcan 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

 P: n/a "James Rogers" wrote in message news:Xn******************************@204.127.36.1 ... "Raoul Watson" wrote in news:NA****************@nwrdny01.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.Caption) - Val(Label1.Caption) End Sub Jul 17 '05 #18

 P: n/a In article , James Rogers 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 Jul 17 '05 #20

 P: n/a gb*@email.si (Gorazd Bozic) wrote in news:bl**********@planja.arnes.si: In article , James Rogers 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. I see what you mean. Your assumption of the Ada syntax is reasonable but not quite accurate. In Ada, the Range attribute evaluates to the full range of values, not the number of values, for a type. In other words, it evaluates to a list of all the valid values for a type. Every Ada enumerated type has several automatically defined attributes. Range is one. Another is Pos. The Pos attribute returns the position number of an enumeration value. There are also the attributes First and Last which evaluate to the lowest and highest valid value for the enumerated type. Using this information, I could have written my code as follows. Suits_Length : constant := Suits'Pos(Suits'Last) - Suits'Pos(Suits'First) + 1; Pips_Length : constant := Pips'Pos(Pips'Last) - Pips'Pos(Pips'First) + 1; type Deck_Index is range (1..Suits_Length * Pips_Length); This would have caused the compiler to calculate the values, eliminating any possible counting error on my part. If I wanted to define the card deck in a generic package I would have been forced to use this approach. I was taking a short cut. You are correct that this approach is generally stronger. Jim Rogers Jul 17 '05 #21

 P: n/a I'll be happy to send anyone my Ada textbooks...Don't need them anymore :-D Jul 17 '05 #22 