I am trying to make a game similar to Memory, but I am struggling to find a way to mix up the cards while making sure that there are only 2 alike cards on the board. Is there a way to do it, or am I going about this all wrong?
Scrambling an Array
BlitzMax Forums/BlitzMax Beginners Area/Scrambling an Array I use this shuffle function:
Method Shuffle()
Local c:Object[]=ListToArray(Cards)
Local j:Int
Local card1:Object
For Local i:Int=c.length-1 To 0 Step -1
j=Rand(0, c.length-1)
card1=c[i]
c[i]=c[j]
c[j]=card1
Next
Cards=ListFromArray(c)
End Method
Method Shuffle()
Local c:Object[]=ListToArray(Cards)
Local j:Int
Local card1:Object
For Local i:Int=c.length-1 To 0 Step -1
j=Rand(0, c.length-1)
card1=c[i]
c[i]=c[j]
c[j]=card1
Next
Cards=ListFromArray(c)
End Method
I'm sorry but I don't understand. I am working with an array called "cards". It may have 104 cards, only 8, or something in between. Mostly, I'm confused where to put the method in my code (I thought you could only use methods with types), and I am still quite a bit unclear on how to use lists.
I use an index # for my crads. 0 to 51. 0 is ace of hearts, 1 is two of hearts, etc. Then I know
Index \ 13
0=Heart, 1=Spade, 2=Club, 3=Diamond.
Set you array of cards with indexes=0 to 51, I used an array of types for my cards (I actually use a TList, but an array would work fine), that can keep track of facedown, location, etc...
Type TCard
Field X:Int, Y:Int
Field FaceDown:Int
Field Index:Int
End Type
Local Cards:TCard[51]
For Local i:Int=0 to 51
TCard[i].Index=i
Next
Then I call that shuffle routine and it mixes them all up.
Index \ 13
0=Heart, 1=Spade, 2=Club, 3=Diamond.
Set you array of cards with indexes=0 to 51, I used an array of types for my cards (I actually use a TList, but an array would work fine), that can keep track of facedown, location, etc...
Type TCard
Field X:Int, Y:Int
Field FaceDown:Int
Field Index:Int
End Type
Local Cards:TCard[51]
For Local i:Int=0 to 51
TCard[i].Index=i
Next
Then I call that shuffle routine and it mixes them all up.
Try making another array and picking one at random from the source array and copying it to the destination array and then removing that item from the source array. Actually this works better with lists which you can transform into arrays and vice versa.
Here's a generic function that should shuffle an array of strings or types. Just pass the array to it as the first parameter.
If you want a detailed explanation of what the function code (and/or the example) is doing, let me know.
EDIT: Added a 'view undealt cards' toggle to the example.
SuperStrict '**** Shuffle function (Array of strings or user defined types required) Function Shuffle(arr:Object[] Var, topindex:Int = -1, fragmentation:Float = 1.0) SeedRnd MilliSecs() If (topindex < 0) Or (topindex > arr.length - 1) Then topindex = arr.length - 1 For Local n:Int = 1 To Int(topindex * fragmentation) Local i1:Int = Rand(0, topindex) Local i2:Int = Rand(0, topindex) Local temp:Object = arr[i1] arr[i1] = arr[i2] arr[i2] = temp Next EndFunction '**** Example Graphics 800, 800 Local Deck:TCard[] '<- ********** Local NumCards:Int Local LastDealtCard:Int RestoreData Cards ReadData NumCards Deck = New TCard[NumCards] For Local i:Int = 0 To NumCards - 1 Deck[i] = New TCard ReadData Deck[i].Label Next Shuffle Deck '<- ********** LastDealtCard = NumCards Local UndealtToggle:Int = True While Not KeyHit(KEY_ESCAPE) 'deal a card If KeyHit(KEY_SPACE) LastDealtCard :- 1 If LastDealtCard < 0 Notify "All cards dealt." End EndIf EndIf 'Undo last dealt card If KeyHit(KEY_BACKSPACE) And LastDealtCard < NumCards LastDealtCard :+ 1 EndIf 'shuffle remaining undealt cards If KeyHit(KEY_S) Shuffle Deck, LastDealtCard - 1 EndIf 'Toggle undealt card view If KeyHit(KEY_TAB) Then UndealtToggle = Not(UndealtToggle) Cls SetColor 0, 255, 255 DrawText "[S] - Shuffle undealt cards, [Space] - Deal a card, [BackSpace] - UNdeal card. [TAB] - Toggle undealt.", 2, 10 SetColor 255, 255, 255 DrawText "DEALT:", 10, 30 For Local i:Int = NumCards - 1 To LastDealtCard Step - 1 Local py:Int = ((NumCards - i) * 12) + 40 DrawText (NumCards - i) + ": " + Deck[i].Label, 10, py Next If UndealtToggle SetColor 255, 0, 0 DrawText "UNDEALT:", 200, 30 For Local i:Int = 0 To LastDealtCard - 1 Local py:Int = ((i + 1) * 12) + 40 DrawText (i + 1) + ": " + Deck[i].Label, 200, py Next EndIf Flip Wend End Type TCard Field Label:String End Type #Cards DefData 54 DefData "Ace, CLUBS", "2, CLUBS", "3, CLUBS", "4, CLUBS", "5, CLUBS" DefData "6, CLUBS", "7, CLUBS", "8, CLUBS", "9, CLUBS", "10, CLUBS" DefData "Jack, CLUBS", "Queen, CLUBS", "King, CLUBS" DefData "Ace, DIAMONDS", "2, DIAMONDS", "3, DIAMONDS", "4, DIAMONDS", "5, DIAMONDS" DefData "6, DIAMONDS", "7, DIAMONDS", "8, DIAMONDS", "9, DIAMONDS", "10, DIAMONDS" DefData "Jack, DIAMONDS", "Queen, DIAMONDS", "King, DIAMONDS" DefData "Ace, SPADES", "2, SPADES", "3, SPADES", "4, SPADES", "5, SPADES" DefData "6, SPADES", "7, SPADES", "8, SPADES", "9, SPADES", "10, SPADES" DefData "Jack, SPADES", "Queen, SPADES", "King, SPADES" DefData "Ace, HEARTS", "2, HEARTS", "3, HEARTS", "4, HEARTS", "5, HEARTS" DefData "6, HEARTS", "7, HEARTS", "8, HEARTS", "9, HEARTS", "10, HEARTS" DefData "Jack, HEARTS", "Queen, HEARTS", "King, HEARTS" DefData "Joker, RED", "Joker, BLACK"
If you want a detailed explanation of what the function code (and/or the example) is doing, let me know.
EDIT: Added a 'view undealt cards' toggle to the example.
I thought for a while and came up with an idea that seems to work on a similar concept as impixi's.
Function ScrambleCards(Array:CardType[]) Local Tmp:CardType For x=0 To Len(Array)-1 SeedRnd MilliSecs()*Rnd(100) Tmp=Array[0] Shuf=Rnd(Len(Array)-1) Array[0]=Array[Shuf] Array[Shuf]=Tmp Next 'MIX THE LAST ITEM WITH ANOTHER Shuf=Rnd(Len(Array)-1) tmp=Array[Shuf] Array[Shuf]=Array[Len(Array)-1] Array[Len(Array)-1]=Tmp EndFunction
You really don't want to call SeedRnd in your loop, as your loop will execute many times within 1 millisecond and you'll be reseeding it with the same value (and getting the same return value) until the millisecond timer ticks.
You don't need to call SeedRnd at all unless you want to be able to recreate a specific scramble at some point. Of course, in that case you should pass the Seed as a parameter (so that you can save the seed somewhere else and then pass it back tot he function to get the same results) and only call SeedRnd ONCE at the top of that code (not in a loop!)
You don't need to call SeedRnd at all unless you want to be able to recreate a specific scramble at some point. Of course, in that case you should pass the Seed as a parameter (so that you can save the seed somewhere else and then pass it back tot he function to get the same results) and only call SeedRnd ONCE at the top of that code (not in a loop!)