Dealing out cards

BlitzMax Forums/BlitzMax Programming/Dealing out cards

I have been using blitzmax for years, though I haven't taken great steps to learn it, I'm only now getting into GUI, and one particular problem has been bothering me. I can't seem to get the darn thing to deal out a deck of cards!

here's my most successful attempt, though it still won't work properly and I'm stumped. Can anyone help?



SeedRnd MilliSecs()

Global dealnum:Int
Global dealsuit:Int
Global dealtnum:Int[13]
Global dealtsuit:Int[4]
Global finalnum:String[13]
Global finalsuit:String[4]
Global cardnumber:Int[13]
Global cardsuit:Int[4]
Global deal:Int
Global dealdeal:Int
Global dealer:Int
Graphics 640,480'not neccessary for now, only feedback is through print commands.

While Not KeyHit(key_q)'mean loop, doesn't do anything yet
deala
'display
End
Wend

Function printatize()
If dealtsuit[c]=0
finalsuit[c]="Hearts"
EndIf
If dealtsuit[c]=1
finalsuit[c]="Diamonds"
EndIf
If dealtsuit[c]=2
finalsuit[c]="Clubs"
EndIf
If dealtsuit[c]=3
finalsuit[c]="Spades"
EndIf
If dealtsuit[c]=3
finalsuit[c]="Spades"
EndIf


'... and numbers
If dealtnum[i]=0
finalnum[i]="Two"
EndIf
If dealtnum[i]=1
finalnum[i]="Three"
EndIf
If dealtnum[i]=2
finalnum[i]="Four"
EndIf
If dealtnum[i]=3
finalnum[i]="Five"
EndIf
If dealtnum[i]=4
finalnum[i]="Six"
EndIf
If dealtnum[i]=5
finalnum[i]="Seven"
EndIf
If dealtnum[i]=6
finalnum[i]="Eight"
EndIf
If dealtnum[i]=7
finalnum[i]="Nine"
EndIf
If dealtnum[i]=8
finalnum[i]="Ten"
EndIf
If dealtnum[i]=9
finalnum[i]="Jack"
EndIf
If dealtnum[i]=10
finalnum[i]="Queen"
EndIf
If dealtnum[i]=11
finalnum[i]="King"
EndIf
If dealtnum[i]=12
finalnum[i]="Ace"
EndIf
End Function

Function deala()
For dealnum=0 To 12
For dealsuit=0 To 3
Cls
deal=Rnd(0,12)
dealtnum[deal]=dealnum
deal=Rnd(0,3)
dealtsuit[deal]=dealsuit
DrawText dealnum,1,1
printatize
Print finalnum[i]+" of "+finalsuit[c]
Flip
Next
Next
End Function

Function display()
For i=0 To 12
For c=0 To 3
printatize
Print finalnum[i]+" of "+finalsuit[c]
Next
Next
EndFunction

This doesn't quite work, but I hope it inspires you.
SuperStrict
SeedRnd MilliSecs()

Type TCard
	Field Face:String
	Field Suit:String
End Type

Type TDeck
	Field Cards:TCard[] 
	
	Method Create(NumCards:Int = 52) 
		Local Loop_Var:Int
		
		Cards:TCard = New TCard[NumCards] 
		For Loop_Var = 0 To Cards.Length - 1
			Cards[Loop_Var] = New TCard
		Next
	End Method
	
	Method Shuffle() 
		Local TempArray:TCard[Cards.Length] 
		Local Active:Int[Cards.Length] 
		Local Return_Array:TCard[Cards.Length] 
		Local Loop_Var:Int
		Local New_Field:Int
		Local TimesAccessed:Int
		
		TempArray = Cards
		
		For Loop_Var = 0 To Cards.Length - 1
			Repeat
				New_Field = Rnd(0, Cards.Length - 1) 
				If Active[New_Field] = False
					Return_Array[Loop_Var] = TempArray[New_Field] 
					Active[New_Field] = True
					Exit
				Else
					If TimesAccessed > 52
						Exit
					End If
				EndIf
				
				If Loop_Var = 51
					Return_Array[Loop_Var] = TempArray[New_Field] 
					Active[New_Field] = True
					Exit
				EndIf
			Forever
		Next
		Cards = Return_Array
	End Method
	
	Method Set() 
		Local Loop_Var1:Int
		Local Loop_Var2:Int
		Local Loop_Var3:Int
		
		For Loop_Var1 = 0 To 12
			For Loop_Var2 = 0 To 3
				If Loop_Var1 = 0
					Cards[Loop_Var3].Face = "Ace"
				ElseIf Loop_Var1 = 1
					Cards[Loop_Var3].Face = "2"
				ElseIf Loop_Var1 = 2
					Cards[Loop_Var3].Face = "3"
				ElseIf Loop_Var1 = 3
					Cards[Loop_Var3].Face = "4"
				ElseIf Loop_Var1 = 4
					Cards[Loop_Var3].Face = "5"
				ElseIf Loop_Var1 = 5
					Cards[Loop_Var3].Face = "6"
				ElseIf Loop_Var1 = 6
					Cards[Loop_Var3].Face = "7"
				ElseIf Loop_Var1 = 7
					Cards[Loop_Var3].Face = "8"
				ElseIf Loop_Var1 = 8
					Cards[Loop_Var3].Face = "9"
				ElseIf Loop_Var1 = 9
					Cards[Loop_Var3].Face = "10"
				ElseIf Loop_Var1 = 10
					Cards[Loop_Var3].Face = "Jack"
				ElseIf Loop_Var1 = 11
					Cards[Loop_Var3].Face = "Queen"
				ElseIf Loop_Var1 = 12
					Cards[Loop_Var3].Face = "King"
				EndIf
		
				If Loop_Var2 = 0
					Cards[Loop_Var3].Suit = "Spades"
				ElseIf Loop_Var2 = 1
					Cards[Loop_Var3].Suit = "Clubs"
				ElseIf Loop_Var2 = 2
					Cards[Loop_Var3].Suit = "Hearts"
				ElseIf Loop_var2 = 3
					Cards[Loop_Var3].Suit = "Diamonds"
				EndIf
			
				Loop_Var3:+1
			Next
		Next
	End Method
End Type

Global MyDeck:TDeck = New TDeck
MyDeck.Create()
MyDeck.Set()
MyDeck.Shuffle() 
Local Loop_Var:Int

For Loop_Var = 0 To MyDeck.Cards.Length - 1
	Print MyDeck.Cards[Loop_Var].Face + " of " + MyDeck.Cards[Loop_Var].Suit
Next


might I ask why it doesn't work though? It seemed to run just fine, it fixed the problems I was having lol.
You've used a lot of stuff that I'm only slightly familiar with... can you please please please add notes so I know what's doing what? Thanks a million for replying! I'm specifically only slightly knowledgeable on the topic of types... I used to kinda know how to do a simple one, but I forgot lol.

Here's mine, I would've finished it about two hours ago if I wasn't watching TV at the same time :)
SuperStrict

SeedRnd( MilliSecs() )'seed the random number generator to help prevent pattern repeating

Global cardNames:String[] = ["Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"]
Global suits:String[] = ["Hearts", "Clubs", "Diamonds", "Spades"]
Global deck:TDeck = TDeck.Create()

Const SUIT_HEARTS:Int = 0
Const SUIT_CLUBS:Int = 1
Const SUIT_DIAMONDS:Int = 2
Const SUIT_SPADES:Int = 3

TPlayer.Create("Perturbatio")
TPlayer.Create("Barturpetio")
TPlayer.Create("Trupertabio")
TPlayer.Create("Bob")

deck.reset()

deck.Shuffle()

deck.Deal(7)

For Local p:TPlayer = EachIn TPlayer.list
	p.ShowHand()
Next



Type TPlayer
	Global list:TList
	Field Name:String
	Field Hand:TCard[]
	
	
	Method addCardToHand( card:TCard )
		Hand = Hand[..Hand.length+1]
		Hand[Hand.length-1] = card
	End Method
	
	
	Method ShowHand()
		Local out:String = ""
		Local total:Int
		For Local card:TCard = EachIn Hand
			out:+ "Card: "+card.Name+", Value: "+Min(10, card.Value)+"~r~n"
			
			total:+Min(10, card.Value)
		Next
		Print out+"~r~nName:"+Name+"~r~nTotal: "+total+"~r~n~r~n"
	End Method
	
	
	Function Create:TPlayer(Name:String)
		If list = Null Then list = New TList
		Local temp:TPlayer = New TPlayer
			temp.Name = Name
			list.addLast(temp)
		Return temp
	End Function
	
End Type



Type TCard
	Field Name:String
	Field Suit:Int
	Field Value:Int
	
	Function Create:TCard(value:Int, suit:Int)
		
		Local temp:TCard = New TCard
			temp.Name = cardNames[value-1]+" of "+suits[suit]
			temp.Suit = suit
			temp.Value = value
		Return temp
		
	End Function
End Type


Type TDeck
	Field cards:TCard[52]
	
	
	Method Shuffle(numShuffles:Int = 20)
		Local Cut:TCard[]
		Local out:String
		
		For Local i:Int = 1 To numShuffles
		
			Local Split1:Int = Rand(20, 30) 'remove approximately half the pack from the bottom
				'Print Split1
				Cut = cards[Split1..]
				cards= cards[..Split1]
				
			Local Split2:Int = Rand(0, Len(Cut)/2) 'Drop part of that from the top onto the top of the main pack
				cards= Cut[..Split2]+cards'ConcatIntArray(Cut[..Split2], deck)
				Cut = Cut[Split2..]
				
			Local Split3:Int = Rand(0, Len(Cut)/2) 'drop the next part on top of that
				cards= Cut[..Split3]+cards'ConcatIntArray(Cut[..Split3], deck)
				Cut = Cut[Split3..]
			'drop the rest
			cards:+ Cut 'ConcatIntArray(Cut, deck)
			
		Next
		
		'Print out
		
	End Method
	
	
	Method pop:TCard()
		
		Local card:TCard
			card = cards[cards.length - 1] 'get the top card
			cards = cards[..cards.length - 1] 'wipe it from the cards array
		Return card
		
	End Method
	
	
	Method Deal(numCards:Int)
		If ( TPlayer.list.count() * numCards ) <= 52 Then
		
			For Local cardCount:Int = 1 To numCards
			
				For Local player:TPlayer = EachIn TPlayer.list
					
					player.addCardToHand(deck.pop())
					
				Next 'player
				
			Next 'cardCount
			
		Else
			RuntimeError "Not enough cards for all the players"
		EndIf
	End Method
	

	Method Reset()
		cards:TCard = New TCard[52]
		Local suit:Int = -1
		Local count:Int = 0
		For Local suit:Int = 0 To 3
			For Local value:Int = 1 To 13
				cards[ count ] = TCard.Create( value, suit )
				count:+1
			Next 'value
		Next 'suit
		
	End Method
	
	
	Function Create:TDeck()
		Local temp:TDeck = New TDeck
			temp.Reset()
		Return temp
	End Function
	
End Type


Sorry for the slow reply earlier, I was 4 hrs. late, but as my excuse, I live in the real world, and I had to write the code from scratch.

It works for the most part, but I thought I saw a repeat once. But I haven't seen it for a bit, so it might be ok.

First if you plan on doing much of anything with BlitzMax I'd suggest you get familiar with types. I'll see what I can do about adding comments.

Types are basically a way to organize information. Theoretically you can write programs without them, but it makes your job ALOT easier. Like arrays they organize information under a single name. Int and Stream are types, they're just preset and you don't have to declare them the same way in arrays.

Methods are like fields, except they're functions within the type.

When I created the TCard Type, every instance of the TCard set will have a String Variable named Suit, and a String Variable named Face.

Think of each type as a Templete, within each Templete it has preset Variables, so every Instance of the type/templete will have the variables declared in the type. You've used types before whether you know it or not.

I didn't comment on the setting Ace-King or Spades - Diamonds as i figured you'd figure it out.

SuperStrict
'Put into SuperStrict mode.
SeedRnd MilliSecs() 'Seed the random generator by milliseconds.

Type TCard 'Make a Card Type
	Field Face:String 'Have a Face field within the Card Type
	Field Suit:String 'Have a Suit field within the Card Type
End Type 'Close the Card Type

Type TDeck 'Make a Deck Type
	Field Cards:TCard[] 'Make a Cards field that's an Array, that contains Null elements as I want to set how many elements later.
	
	Method Create(NumCards:Int = 52) 'Create a Create method with a parameter of NumCards to set the number of Elements in Cards.
		Local Loop_Var:Int 'Create a Loop Variable that I'm going to use and re-use later.
		
		Cards:TCard = New TCard[NumCards] 'Redeclare the Array so I can have a custom number of cards for Cards with Jokers.
		For Loop_Var = 0 To Cards.Length - 1 'Go in a loop from 0 to the Length of the Cards Array - 1
			Cards[Loop_Var] = New TCard 'Declare the Type
		Next
	End Method 'End the method
	
	Method Shuffle() 'Create a Shuffle method that will mix up the cards.
		Local TempArray:TCard[Cards.Length] 'A Temporary array that we will test against, it will be equal to the Cards Array.
		Local Active:Int[Cards.Length] 'An array that we use to ensure that no cards are repeated.
		Local Return_Array:TCard[Cards.Length] 'This will be the new Cards Array.
		Local Loop_Var:Int 'Loop Variable
		Local New_Field:Int 'A random number used for the mixing
		Local TimesAccessed:Int 'Helps us determine what field to acess of the Arrays.
		
		TempArray = Cards 'Set the TempArray and all its fields to that of the Card Array.
		
		For Loop_Var = 0 To Cards.Length - 1 'Enter a for loop
			Repeat 'A repeat forever loop
				New_Field = Rnd(0, Cards.Length - 1) 'Random number 
				If Active[New_Field] = False 'If we haven't used this field before
					Return_Array[Loop_Var] = TempArray[New_Field] 'Set the new Cards field uip
					Active[New_Field] = True 'Make sure we don't use it again
					Exit 'Exit the Repeat...Forver loop
				Else 'Otherwise.
					If TimesAccessed > 52 'If we've gone through it too many times.
						Exit 'Exit repeat forever loop
					End If
				EndIf
				
				If Loop_Var = 51 'If this is the last appropriate card
					Return_Array[Loop_Var] = TempArray[New_Field] 'Set it up
					Active[New_Field] = True
					Exit 'Exit out of the repeat forever loop
				EndIf
			Forever
		Next
		Cards = Return_Array 'Set the Cards array to the new correct array.
	End Method
	
	Method Set() 
		Local Loop_Var1:Int 'Loop Variable 1
		Local Loop_Var2:Int 'Loop Variable 2
		Local Loop_Var3:Int 'Loop Variable 3
		
		For Loop_Var1 = 0 To 12 'Cycle through 13 times (once for each card)
			For Loop_Var2 = 0 To 3 'Cycle through 4 times (once for each suit)
				If Loop_Var1 = 0 'If its ace
					Cards[Loop_Var3].Face = "Ace"
				ElseIf Loop_Var1 = 1
					Cards[Loop_Var3].Face = "2"
				ElseIf Loop_Var1 = 2
					Cards[Loop_Var3].Face = "3"
				ElseIf Loop_Var1 = 3
					Cards[Loop_Var3].Face = "4"
				ElseIf Loop_Var1 = 4
					Cards[Loop_Var3].Face = "5"
				ElseIf Loop_Var1 = 5
					Cards[Loop_Var3].Face = "6"
				ElseIf Loop_Var1 = 6
					Cards[Loop_Var3].Face = "7"
				ElseIf Loop_Var1 = 7
					Cards[Loop_Var3].Face = "8"
				ElseIf Loop_Var1 = 8
					Cards[Loop_Var3].Face = "9"
				ElseIf Loop_Var1 = 9
					Cards[Loop_Var3].Face = "10"
				ElseIf Loop_Var1 = 10
					Cards[Loop_Var3].Face = "Jack"
				ElseIf Loop_Var1 = 11
					Cards[Loop_Var3].Face = "Queen"
				ElseIf Loop_Var1 = 12
					Cards[Loop_Var3].Face = "King"
				EndIf
		
				If Loop_Var2 = 0
					Cards[Loop_Var3].Suit = "Spades"
				ElseIf Loop_Var2 = 1
					Cards[Loop_Var3].Suit = "Clubs"
				ElseIf Loop_Var2 = 2
					Cards[Loop_Var3].Suit = "Hearts"
				ElseIf Loop_var2 = 3
					Cards[Loop_Var3].Suit = "Diamonds"
				EndIf
			
				Loop_Var3:+1 'Increment the 3rd Loop Variable by 1 AKA add to it by 1
			Next
		Next
	End Method
End Type

Global MyDeck:TDeck = New TDeck 'Make a new deck
MyDeck.Create() 'Use the create Method of the deck
MyDeck.Set() 'Use the Set Method of the deck
MyDeck.Shuffle() 'Use the Shuffle Method of the deck
Local Loop_Var:Int 'A LoopVariable

For Loop_Var = 0 To MyDeck.Cards.Length - 1 'Cycle through the cards.
	Print MyDeck.Cards[Loop_Var].Face + " of " + MyDeck.Cards[Loop_Var].Suit 'Print it out.
Next


This way in order to make a traditional Card Deck, all you have to do is:
NewDeck:TDeck
NewDeck.Create()
NewDeck.Set()

And its all ready to be used, then to shuffle it, you do:
NewDeck.Shuffle()


The reason I make you Set and Shuffle is you may not want that, with a little more work, and merging with Perturbatio's this could work for most decks. Like you could have another method that would be, "SetPokerDeck()" or something like that I think.

wow thanks both of you :) I wasn't expecting people to write code from scratch thanks a million!
I'm still reading through your comments Corin, but it seems to be very well documented now I'll fiddle around with it to see what I can mess with now :D

Your welcome, Good, these are important concepts, some I overuse, but important none the less. :D

It was a good chance to flex my programming muscles anyway. :D

you're gonna get sick of me lol I'm sure I'll have more questions for you before we're through with this :P

I doubt it, however I suggest checking out talk.christiandevs.com That's where I hang out alot, is not just Christians, but there's a great community if I do say so myself, and a couple BM users.