Scrambling an Array

BlitzMax Forums/BlitzMax Beginners Area/Scrambling an Array

CASO(Posted 2007) [#1]
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?


TaskMaster(Posted 2007) [#2]
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


CASO(Posted 2007) [#3]
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.


TaskMaster(Posted 2007) [#4]
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.


Grey Alien(Posted 2007) [#5]
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.


impixi(Posted 2007) [#6]
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.


CASO(Posted 2007) [#7]
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



SculptureOfSoul(Posted 2007) [#8]
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!)