|
Wrong site, we try and support, help coders. try rentacoder[^]
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Hi,
I'm shuffling a deck of cards, but seem to keep getting more than one of the same card, after the shuffle. So, I tried quite a bit trying to set the value of the card to not equal the subnum of the card, but it didn't work. Any ideas would be much appreciated. Thanks. Here's part of the code:
Private Sub Start_Click()
Dim arrDeck(52)
Randomize
CardCount = 1
Do While CardCount < 53
arrDeck(CardCount) = -1
CardCount = CardCount + 1
Loop
CardCount = 1
Counter = 0
Do While CardCount < 53 And Counter < 53
3 CardVal = Int((52 * Rnd) + 1)
If arrDeck(CardVal) = -1 Then
arrDeck(CardVal) = CardCount
Subnum = Counter
Image1(Subnum) = Image1(CardVal)
Image1(Subnum).Visible = True
CardCount = CardCount + 1
Counter = Counter + 1
Else: GoTo 3
End If
Loop
End Sub
|
|
|
|
|
have you tried applying a number between 1 and 52 to each card, the as each number is picked randomly it is added to an array.
on the next random call, it is checked to the contents of the array, and if found to have been picked already is rejected.
It will slow doown as the cards are dealt, but then that array will be filled from 1 to 52 in random order, just apply the numbers back to the cards to give a random shuffle.
------------------------------------
"I am always serious about what I do, not necessarily about how I do it."
Tom Baker
|
|
|
|
|
Thank you; I will try this...I appreciate your time.
|
|
|
|
|
You can add your cards to a collection and then pull the cards from random positions out of that collection and add them to another collection.
Private Function GetShuffledDeck() as List(Of Integer)
Dim cards As New List(Of Integer)
For i As Integer = 0 To 51
cards.Add(i)
Next
Dim RNG As New Random()
Dim deck As New List(Of Integer)
While cards.Count > 0
Dim cardNum As Integer
cardNum = RNG.Next(0, cards.Count)
deck.Add(cards(cardNum))
cards.RemoveAt(cardNum)
End While
Return deck
End Function
|
|
|
|
|
Wow, thanks! This does make total sense, except I have one question which might be a "newbie type:" Cards.Add(i) would produce 0 -51 cards right? Then deck.Add(cards(cardNum" would produce a random ineger and remove at cardnum....since it is in the same function, then there is an end value of 52 right? It seems confusing to me on how the end value is represented in your shuffle procedure. Thanks very much for your time! You are AWESOME!
|
|
|
|
|
ymilan wrote: since it is in the same function, then there is an end value of 52 right?
I don't get what your referring to. There is a COUNT of 52 items, 0 to 51 inclusive. The reason I wrote the method this way is because you can eliminate the top part the populates Cards with 0 to 51 and just pass in a collection of cards of any order. This method would then just "shuffle" a randomized deck. For example, you could have a method that passes a deck into this shuffle method a few times, passing in the deck that was returned, to really shuffle the deck.
Also, you can create your own Card class and replace the List(Of Integer) references with List(Of Card) instead.
|
|
|
|
|
Ok, I get it now. I was thinking along those lines, but got confused. Thanks.
|
|
|
|
|
Here's a possible solution.
Note that I have not Dimmed all the variables.
It's a classic way to do shuffling of card decks.
Private Sub Start_Click()
Dim arrDeck(52)
Randomize
' Fill deck with cards in order 1 to 52
CardCount = 1
Do While CardCount <= 52
arrDeck(CardCount) = Cardcount
CardCount = CardCount + 1
Loop
' Shuufle the deck - end value (100) could be anything, bigger it is the more shuffled deck is
Counter = 0
Do While Counter <= 100
' Get two random card positions
card1 = Int((52 * Rnd) + 1)
card2 = Int((52 * Rnd) + 1)
' Swap cards at these positions
tmpCard = arrDeck(card1)
arrDeck(card1) = arrDeck(card2)
arrDeck(card2) = tmpCard
Loop
' Now output immages in order of deck
CardCount = 1
Do While CardCount <= 52
Subnum = arrDeck(CardCount)
Image1(Subnum).Visible = True
CardCount = CardCount + 1
Loop
End Sub
Regards
David R
|
|
|
|
|
I went to compile this code in MS VB and it rejected as Compile Error all the values that were not dimmed....any ideas why? Thanks in advance.
|
|
|
|
|
Hmm, seems to compile, but when I click the start button, the program hangs....any ideas?
|
|
|
|
|
Not without seeing the actual code you did and where it is called. I don't think there's anything in it that should cause a hang.
I did not Dim all the variables because I was not sure what you had already declared.
Obviously they need to be Dimmed somewhere.
Regards
David R
|
|
|
|
|
' I x'd out the lines to show what I am trying to do...
Option Explicit
Public Sub Main()
Start_Game.Show
End Sub
Private Sub Exit_Click()
MsgBox ("Thank you for playing! Good bye")
End
End Sub
Private Sub Start_Click()
Dim arrDeck(52)
Randomize
Dim Cardcount As Integer
Dim Counter As Integer
Dim Card1 As Integer
Dim Card2 As Integer
'Dim CardVal As Integer
'Dim SubNum As Integer
' Fill deck with cards in order 1 to 52
Cardcount = 1
Do While Cardcount <= 52
arrDeck(Cardcount) = Cardcount
Cardcount = Cardcount + 1
Loop
' Shuffle the deck - end value (100)
Counter = 0
Do While Counter <= 100
' Get two random card positions
Card1 = Int((52 * Rnd) + 1)
Card2 = Int((52 * Rnd) + 1)
' Swap cards at these positions
Tmpcard = arrDeck(Card1)
arrDeck(Card1) = arrDeck(Card2)
arrDeck(Card2) = Tmpcard
'CardVal = Tmpcard ? Looking for a single value out of the random cards you made...
Loop
' Now output images in order of deck
Cardcount = 1
Counter = 0
' It seems I need a counter in here for Subnum, 0-52 so it can display the cards from 0-52 slots,
' But the array of a single value out of the random cards you made need to be set to another counter,
' Right? I'm not sure...I x'd out the lines to show what I meant...
'Do While Cardcount <= 52 And Counter < 53
'If arrDeck(CardVal) = -1 Then
' arrDeck(CardVal) = Cardcount
'Image1(Cardcount) = CardVal
' Subnum = Counter
'Image1(Subnum).Visible = True
Cardcount = Cardcount + 1
'Counter = Counter + 1
' End If
Loop
End Sub
|
|
|
|
|
I'm not sure why you need all the counters. Your Counter is always one less than Cardcount so is effectively redundant. In Do While Cardcount <= 52 And Counter < 53 both parts of the condition will have same logical value.
What is Image1() - it looks like an array but has a Visible property.
And this line implies that it is an array of integer: Image1(Cardcount) = CardVal
In any case here's a new version of the code that shuffles the images directly.
You would need to Dim tmpImage as an appropriate type.
To get a single random image after shuffling you could just use Image1(1) i.e. the top of the pack; or you could use tmpImage.
Private Sub Start_Click()
Randomize
'Dim tmpImage As ????
Dim card1 As Integer
Dim card2 As Integer
Dim counter As Integer
' Shuffle the images - end value (100)
Counter = 0
Do While Counter <= 100
' Get two random image positions
card1 = Int((52 * Rnd) + 1)
card2 = Int((52 * Rnd) + 1)
' Swap images at these positions
tmpImage = Image1(card1)
Image1(card1) = Image1(card2)
Image1(card2) = tmpImage
Loop
' Now output images in order
counter = 1
Do While counter <= 52
Image1(counter).Visible = True
counter = counter + 1
Loop
End Sub
What version of VB are you using? I'd assumed VB.NET but I can't see where Image1() would fit in. But, IIRC, in VB6 there is an Image control (not used VB6 for about 5 years).
EDIT: forgot to Dim counter
Regards
David R
|
|
|
|
|
Ok, sure then, I can just pass the images through directly...then having overkill of counting. I see now. Thanks.
As far as the version, perhaps this would be good to ask this question also, I'm using VB6 because that's all I have. It costs for VB.NET right? Not sure. I'm doing a specific game for my Mom, that's why I haven't upgraded am just using an older version.
Images() was the visual image of the card I created on the form.
|
|
|
|
|
Glad to be of some help - my VB6 is a bit rusty but I should have spotted the use of Image1()
You'll probably find that Dave K's solution won't work - it's .NET stuff.
You can download VB.NET Express editions for free. There's two versions - 2005 and 2008. Probably best to go for 2008. Worth looking into. You can see what's available at http://www.microsoft.com/express/[^]
Regards
David R
|
|
|
|
|
Ok, I set tmpImage to As Image, is that correct? Then would I have the change the last few lines to reflect
Do While Counter <= 52
Image1(TmpImage).Visible = True
Counter = Counter + 1
Loop
If so, gives an error like object variable or with block variable not set
debugs on TmpImage = Image1(Card1)
|
|
|
|
|
If tmpImage is an Image (it has to be whatever is in Image1() so what type of object does Image1() store?) then you can't use it as an index to Image1().
Using counter as the index will make all the images visible.
I don't have VB6 running anymore so I'm relying on memory.
Regards
David R
|
|
|
|
|
Image1() stores an array... 0-52, was created automatically when I set up the cards on the form.
|
|
|
|
|
It must be an array of something - the same type as the cards?
Can yo see the code that fills the array? That should tell you what the type is.
As an alternative, you could try Dimming tmpImage As Variant - that would allow it to hold anything. But you still can't use it as an index into the array.
Regards
David R
|
|
|
|
|
It's an array of images, as in I click on one of the images on the form and it states image1(0) Image
That's what it states, so I should set tmpImage to Image, but it still produces the same error.
Should I try a third integer variable to use with tmpImage, as in tmpImage(Card3) and have Card3 be a random number?
|
|
|
|
|
Should I dim tmpimage as image and set it using a set statement to an array of an index? or integer?
How would I do that?
|
|
|
|
|
I'd forgotten you need to use Set when dealing with 'objects - mea culpa.
So in the shuffle loop you need this:
Set tmpImage = Image1(card1)
Set Image1(card1) = Image1(card2)
Set Image1(card2) = tmpImage
tmpImage must be of the same type as whatever the Image1() array holds (or it could be Variant). It can't be an Integer nor an array of anything. All it's used for is to allow items in the Image1() array to be swapped. It has no other use in the code.
How many images do you want to display at once? If you only want one then the second loop is not needed. You could just do something like Image1(1).Visible = True to display the first image.
Regards
David R
|
|
|
|
|
Ok, great! I had to put in counter + 1 though for it to partially work...
Set tmpImage = Image1(Card1)
Set Image1(Card1) = Image1(Card2)
Set Image1(Card2) = tmpImage
Counter = Counter + 1
Loop
But also, it doesn't show the first card; tried changing counter to equal 0, but didn't help; any ideas?
|
|
|
|
|
Can't believe I made such a blunder - but it's because I would normally use a For loop like so (and I'm writing the code in Notepad so no help from the editor ).
For counter = 0 to 100
' Get two random image positions
card1 = Int((52 * Rnd) + 1)
card2 = Int((52 * Rnd) + 1)
' Swap images at these positions
Set tmpImage = Image1(card1)
Set Image1(card1) = Image1(card2)
Set Image1(card2) = tmpImage
Next counter
Then I don't have to increase counter , the loop does it for me. Note that counter is just counting the numbers of swaps done - it has nothing to do with the number of images it could be set to do 1000 or whatever you like.
All this loop does is shuffle the images. It does not display them in any way - that's down to the Image1(x).Visible = True where x is the number of the image you want to display.
Not sure why it's not displaying. You might try refreshing the the form (i.e add Form.Refresh or a DoEvents after setting Image1(1).Visible = True .
Regards
David R
|
|
|
|