Card games...
Blitz3D Forums/Blitz3D Beginners Area/Card games...
| ||
| I want to make a certain card game(normal deck of cards) that involves getting a 3 card hand and discarding and picking up cards etc. Since there are 52 cards and you can't get the same card twice, I can't use: card1=Rnd(0,52)... What way can I pick a random card(or 3) and not pick up the same card accidentally and stuff? I want there to be all the cards except the two jokers(50?) available to pick up at random and start off with at random. |
| ||
| First, a full deck without jokers is 52, not 50. The only way to do this that I can think of is make an array of 52, and when a card is chose, 9 of clubs for instance, take its respective variable, cards(9) and change it to True, ie. 1. So just do random, and say If cards(rand(0,52))=0 then... and so on.
SeedRnd Millisecs()
Dim cards(52)
Repeat
card=Rand(1,52)
If cards(card)=0 then
cards(card)=1
playgame(card)
End if
Until gameover=True
End
Hope it helps! |
| ||
| Thanks. Kind of like this? Graphics 800,600 SetBuffer BackBuffer() SeedRnd MilliSecs() While Not KeyHit(1) Dim cards(52) card=Rand(1,52) If cards(card)=0 Then cards(card)=1 playgame(card) End If If cards(Rand(0,52))=1 :kind$="Spades":name$="Ace":amount=11:EndIf If cards(Rand(0,52))=2 :kind$="Spades":name$="2":amount=2:EndIf If cards(Rand(0,52))=3 :kind$="Spades":name$="3":amount=3:EndIf If cards(Rand(0,52))=4 :kind$="Spades":name$="4":amount=4:EndIf If cards(Rand(0,52))=5 :kind$="Spades":name$="5":amount=5:EndIf If cards(Rand(0,52))=6 :kind$="Spades":name$="6":amount=6:EndIf If cards(Rand(0,52))=7 :kind$="Spades":name$="7":amount=7:EndIf If cards(Rand(0,52))=8 :kind$="Spades":name$="8":amount=8:EndIf If cards(Rand(0,52))=9 :kind$="Spades":name$="9":amount=9:EndIf If cards(Rand(0,52))=10 :kind$="Spades":name$="10":amount=10:EndIf If cards(Rand(0,52))=11 :kind$="Spades":name$="Jack":amount=10:EndIf If cards(Rand(0,52))=12 :kind$="Spades":name$="Queen":amount=10:EndIf If cards(Rand(0,52))=13 :kind$="Spades":name$="King":amount=10:EndIf If cards(Rand(0,52))=14 :kind$="Clubs":name$="Ace":amount=11:EndIf If cards(Rand(0,52))=15 :kind$="Clubs":name$="2":amount=2:EndIf If cards(Rand(0,52))=16 :kind$="Clubs":name$="3":amount=3:EndIf If cards(Rand(0,52))=17 :kind$="Clubs":name$="4":amount=4:EndIf If cards(Rand(0,52))=18 :kind$="Clubs":name$="5":amount=5:EndIf If cards(Rand(0,52))=19 :kind$="Clubs":name$="6":amount=6:EndIf If cards(Rand(0,52))=20 :kind$="Clubs":name$="7":amount=7:EndIf If cards(Rand(0,52))=21 :kind$="Clubs":name$="8":amount=8:EndIf If cards(Rand(0,52))=22 :kind$="Clubs":name$="9":amount=9:EndIf If cards(Rand(0,52))=23 :kind$="Clubs":name$="10":amount=10:EndIf If cards(Rand(0,52))=24 :kind$="Clubs":name$="Jack":amount=10:EndIf If cards(Rand(0,52))=25 :kind$="Clubs":name$="Queen":amount=10:EndIf If cards(Rand(0,52))=26 :kind$="Clubs":name$="King":amount=10:EndIf If cards(Rand(0,52))=27 :kind$="Hearts":name$="Ace":amount=11:EndIf If cards(Rand(0,52))=28 :kind$="Hearts":name$="2":amount=2:EndIf If cards(Rand(0,52))=29 :kind$="Hearts":name$="3":amount=3:EndIf If cards(Rand(0,52))=30 :kind$="Hearts":name$="4":amount=4:EndIf If cards(Rand(0,52))=31 :kind$="Hearts":name$="5":amount=5:EndIf If cards(Rand(0,52))=32 :kind$="Hearts":name$="6":amount=6:EndIf If cards(Rand(0,52))=33 :kind$="Hearts":name$="7":amount=7:EndIf If cards(Rand(0,52))=34 :kind$="Hearts":name$="8":amount=8:EndIf If cards(Rand(0,52))=35 :kind$="Hearts":name$="9":amount=9:EndIf If cards(Rand(0,52))=36 :kind$="Hearts":name$="10":amount=10:EndIf If cards(Rand(0,52))=37 :kind$="Hearts":name$="Jack":amount=10:EndIf If cards(Rand(0,52))=38 :kind$="Hearts":name$="Queen":amount=10:EndIf If cards(Rand(0,52))=39 :kind$="Hearts":name$="King":amount=10:EndIf If cards(Rand(0,52))=40 :kind$="Diamonds":name$="Ace":amount=11:EndIf If cards(Rand(0,52))=41 :kind$="Diamonds":name$="2":amount=2:EndIf If cards(Rand(0,52))=42 :kind$="Diamonds":name$="3":amount=3:EndIf If cards(Rand(0,52))=43 :kind$="Diamonds":name$="4":amount=4:EndIf If cards(Rand(0,52))=44 :kind$="Diamonds":name$="5":amount=5:EndIf If cards(Rand(0,52))=45 :kind$="Diamonds":name$="6":amount=6:EndIf If cards(Rand(0,52))=46 :kind$="Diamonds":name$="7":amount=7:EndIf If cards(Rand(0,52))=47 :kind$="Diamonds":name$="8":amount=8:EndIf If cards(Rand(0,52))=48 :kind$="Diamonds":name$="9":amount=9:EndIf If cards(Rand(0,52))=49 :kind$="Diamonds":name$="10":amount=10:EndIf If cards(Rand(0,52))=50 :kind$="Diamonds":name$="Jack":amount=10:EndIf If cards(Rand(0,52))=51 :kind$="Diamonds":name$="Queen":amount=10:EndIf If cards(Rand(0,52))=52 :kind$="Diamonds":name$="King":amount=10:EndIf Flip Cls Wend |
| ||
You could use a couple of variables to generate random cards and random suits, seperately. Save you a big chuck of code like that :)global kind$="" global name$="" global amount=0 global no_suits=4; set up number of suits global no_cards_suit=13; number of cards in each suit dim cards(no_suits,no_cards_suit); dim the array dim suit_name$(no_suits) ; set up the suits array, so you can easily pull names from it suit_name$(1)="Spades" suit_name$(2)="Clubs" suit_name$(3)="Hearts" suit_name$(4)="Diamonds" repeat suit=rand(1,4) ; generate a random suit card=rand(1,13) ; generate a random card number until cards(suit,card)=1 ; keep looping till you find a card that is 'there' cards(suit,card)=0 if card=1 then name$="Ace":kind$=suit_name$:amount=11 elseif card=11 then name$="Jack":kind$=suit_name$:amount=10 elseif card=12 then name$="Queen":kind$=suit_name$:amount=10 elseif card=13 then name$="King":kind$=suit_name$:amount=10 else name$=card:kind$=suit_name$:amount=card end if Post back if you need any more help with that, as i haven't fully commented it :) |
| ||
I get an error when I try to run it "Identifier 'suit_name' may not be used like this." like this:Global kind$="" Global name$="" Global amount=0 Global no_suits=4; set up number of suits Global no_cards_suit=13; number of cards in each suit Dim cards(no_suits,no_cards_suit); dim the array Graphics 800,600 SetBuffer BackBuffer() SeedRnd MilliSecs() While Not KeyHit(1) Dim suit_name$(no_suits) ; set up the suits array, so you can easily pull names from it suit_name$(1)="Spades" suit_name$(2)="Clubs" suit_name$(3)="Hearts" suit_name$(4)="Diamonds" Repeat suit=Rnd(1,4) ; generate a random suit card=Rnd(1,13) ; generate a random card number Until cards(suit,card)=1 ; keep looping till you find a card that is 'there' cards(suit,card)=0 If card=1 Then name$="Ace":kind$=suit_name$:amount=11 ElseIf card=11 Then name$="Jack":kind$=suit_name$:amount=10 ElseIf card=12 Then name$="Queen":kind$=suit_name$:amount=10 ElseIf card=13 Then name$="King":kind$=suit_name$:amount=10 Else name$=card:kind$=suit_name$:amount=card End If Flip Cls Wend |
| ||
The suit_name$ is declared as a dimmed array.If card=1 Then name$="Ace":kind$=suit_name$:amount=11 ElseIf card=11 Then name$="Jack":kind$=suit_name$:amount=10 ElseIf card=12 Then name$="Queen":kind$=suit_name$:amount=10 ElseIf card=13 Then name$="King":kind$=suit_name$:amount=10 Else name$=card:kind$=suit_name$:amount=card End If In this section of code it should be used as suit_name$(array_index) |
| ||
| ah, yes thanks. |
| ||
| I believe it would be much better to use a linked list versus an array. That way when a card is "dealt", you can remove it from the list, and you don't have to worry about randomly picking that index again, and again, and again (like when all the cards except for a few are picked). This is (basically) what I did for my blackjack game: Const NUM_SUITS = 4 Const NUM_RANKS = 13 Const NUM_CARDS = NUM_SUITS * NUM_RANKS Type NewCard Field Suit%, Rank% End Type Type ShuffledCard Field Suit%, Rank% End Type Function ShuffleDeck() ; Create new, unshuffled deck For i% = 1 To NUM_SUITS For j% = 1 To NUM_RANKS source.NewCard = New NewCard source\Suit = i source\Rank = j Next Next ; Create "Shuffled" deck For i = NUM_CARDS To 1 Step -1 card% = Rand(1, i) source = First NewCard For j = 1 To card - 1 : source = After source : Next If source <> Null Then shuffled.ShuffledCard = New ShuffledCard ; inserts card into shuffled deck shuffled\Suit = source\Suit shuffled\Rank = source\Rank Delete source ; removes card from unshuffled deck Else Notify "Trying to access null source card" End EndIf Next End Function |
| ||
Here's what I use to shuffle a deck. It's kind of like soja's method only without the linked list, it uses an array.Graphics 800,600,32,2 SetBuffer BackBuffer() SeedRnd MilliSecs() reseed = Rand(1,1000) ;this compensates for known Random bug (just ask 'Morduun' 8) reseed = Rand(1,1000) ClsColor 0,96,192 Cls Flip Dim cards%(52) shuffle() ;Now that the cards are shuffled you can walk through ;the array, just as you would a real deck of cards For i% = 1 To 13 y% = y% + 15 Text 10, y, getSuit$(cards(i)) Text 210, y, getSuit$(cards(i+13)) Text 410, y, getSuit$(cards(i+26)) Text 610, y, getSuit$(cards(i+39)) Text 320, 570, "( Press any key to exit )" Next Flip WaitKey() End Function shuffle%() ;Load the cards() array with 52 unique numbers ;(they just happen to be sequential for now) For i% = 1 To 52 cards(i) = i Next ;Simulate shuffling deck 7 times For i = 1 To 7*52 ;Use indices swap1 and swap2 to scramble deck swap1% = Rand(1,52) swap2% = Rand(1,52) ;Ensure indices don't point to same element While swap1 = swap2 swap2 = Rand(1,52) Wend ;OK, two different elements, perform swap temp% = cards(swap1) cards(swap1) = cards(swap2) cards(swap2) = temp Next End Function Function getSuit$( integer%) ;1-13 is a spade, 14-26 is a heart, 27-39 is a club, 40-52 is diamond If integer < 14 Then suit$ = "Spades" If integer > 13 And integer < 27 Then suit$ = "Hearts" If integer > 26 And integer < 40 Then suit$ = "Clubs" If integer > 39 Then suit$ = "Diamonds" ;now we know the suit, make 'integer' a number between 0 and 12 integer = integer Mod 13 Select integer Case 1: value$ = "Ace" Case 11: value$ = "Jack" Case 12: value$ = "Queen" Case 0: value$ = "King" Default: value$ = Str(integer) End Select Return value$ + " of " + suit$ End Function |
| ||
| I wrote a card game, where the cards were stored in an array as above, with a dimension to the array that represented the card location i.e. 1-4=player # 5=discard pile, 6=deck and 7=current 'top card' or whatever. |
| ||
Sorry about that po. Should have been:global kind$="" global name$="" global amount=0 global no_suits=4; set up number of suits global no_cards_suit=13; number of cards in each suit dim cards(no_suits,no_cards_suit); dim the array dim suit_name$(no_suits) ; set up the suits array, so you can easily pull names from it suit_name$(1)="Spades" suit_name$(2)="Clubs" suit_name$(3)="Hearts" suit_name$(4)="Diamonds" repeat suit=rand(1,4) ; generate a random suit card=rand(1,13) ; generate a random card number until cards(suit,card)=1 ; keep looping till you find a card that is 'there' cards(suit,card)=0 if card=1 then name$="Ace":kind$=suit_name$(suit):amount=11 elseif card=11 then name$="Jack":kind$=suit_name$(suit):amount=10 elseif card=12 then name$="Queen":kind$=suit_name$(suit):amount=10 elseif card=13 then name$="King":kind$=suit_name$(suit):amount=10 else name$=card:kind$=suit_name$(suit):amount=card end if |
| ||
| Here's a yugioh program me and my son are working on. Each player has their own deck but it illustrates using arrays in types to track which cards are where. When you have arrays pointing to types you can use the Null value to set that slot to empty, so to move a card from a player's hand into play- p\inplay[j]=c p\hand[i]=Null where p is the current player, i is the card from their hand they are playing and j is the playarea which in yugioh is an array of 5 cards in front of the player. The method of shuffle swaps two random cards in the deck multiple times. Also note the use of the command SeedRnd MilliSecs() to make sure you get a random deal every time you run the game.
; yugioh.bb
; by simon and harley
Type card
Field name$
Field attack
Field defence
Field effect$
Field stars
Field place
End Type
Type player
Field name$
Field decksize
Field deck.card[256]
Field hand.card[7]
Field inplay.card[5]
Field graveyard.card[256]
Field lifepoints
End Type
Function createplayer.player(name$)
; read in deck
p.player=New player
p\name=name
Read size
p\decksize=size
For i=1 To size
c.card=New card
Read c\name$
Read c\attack
Read c\defence
Read c\effect$
Read c\stars
p\deck[i]=c
Next
p\lifepoints=8000
Return p
End Function
Function ShuffleDeck(p.player)
For i=1 To 50
a=Rnd(p\decksize)
b=Rnd(p\decksize)
; swap 2 cards in the deck
c.card=p\deck[a]
p\deck[a]=p\deck[b]
p\deck[b]=c
Next
End Function
Function DealCards(p.player)
For i=1 To 5
p\hand[i]=p\deck[p\decksize]
p\decksize=p\decksize-1
Next
End Function
Function PlayTurn(p.player,q.player)
Print ""
Print p\name+"'s Turn"
; deal card
For i=1 To 7
If p\hand[i]=Null
p\hand[i]=p\deck[p\decksize]
p\decksize=p\decksize-1
Exit
EndIf
Next
summons=7
; command loop
While True
; print out commands
Print ""
For i=1 To summons
If p\hand[i]<>Null
Print " [S"+i+"] Summon "+p\hand[i]\name
EndIf
Next
attacks=0
For i=1 To 5
If p\inplay[i]<>Null
For j=1 To 5
If q\inplay[j]<>Null
Print " [A"+i+""+j+"] Attack "+q\inplay[j]\name+" with "+ p\inplay[i]\name
attacks=attacks+1
EndIf
Next
EndIf
Next
If (summons+attacks=0) Return
Print ""
; input command
a$=Input("("+p\lifepoints+") >")
Print ""
; finish turn
If a$="" Then Return
; quit game?
If a$="q" Then End
; summon monster ?
If (summons>0 And Left$(a$,1))="S" Or (Left$(a$,1))="s"
i=Mid$(a$,2)
c.card=p\hand[i]
If c<>Null
Print p\name+" summons "+c\name
For j=1 To 5
If p\inplay[j]=Null
p\inplay[j]=c
p\hand[i]=Null
Exit
EndIf
Next
EndIf
EndIf
; attack monster ?
If (Left$(a$,1))="A" Or (Left$(a$,1))="a"
i=Mid$(a$,2,1)
j=Mid$(a$,3,1)
If (i<6 And j<6)
c.card=p\inplay[i]
cc.card=q\inplay[j]
If c<>Null And cc<>Null
If (c\attack>cc\defence)
pts=c\attack-cc\defence
Print c\name+" wins! "+cc\name+" dies, "+q\name+" looses "+pts+" lifepoints."
q\lifepoints=q\lifepoints-pts
q\inplay[j]=Null
Else
pts=cc\defence-c\attack
Print c\name+" dies "+p\name+" looses, "+pts+" lifepoints," ;destroy monster
p\lifepoints=p\lifepoints-pts
p\inplay[i]=Null
EndIf
EndIf
EndIf
EndIf
summons=0
Wend
End Function
; main program
; to have different deck for each player change the Restore points
SeedRnd MilliSecs()
a$=Input("Player 1 name-")
Restore HarleyDeck
p1.player=CreatePlayer(a$)
a$=Input("Player 2 name-")
Restore HarleyDeck
p2.player=CreatePlayer(a$)
ShuffleDeck(p1)
ShuffleDeck(p2)
DealCards(p1)
DealCards(p2)
.gameloop
PlayTurn(p1,p2)
PlayTurn(p2,p1)
Goto gameloop
;PlayTurn(deck1)
; Print c\name+" "+Left$("*************",c\stars)
;MouseWait
Print "Game Over Dudes"
Input "Hit Return To Quit"
End
.HarleyDeck
Data 21
Data "LordOfD",1200,1100,"No Dragon Effects",4
Data "LordOfD",1200,1100,"No Dragon Effects",4
Data "LordOfD",1200,1100,"No Dragon Effects",4
Data "Blue-Eyes",3000,2500,"No Effect",8
Data "Blue-Eyes",3000,2500,"No Effect",8
Data "Blue-Eyes",3000,2500,"No Effect",8
Data "Rude Kaiser",1800,1600,"No Effect",5
Data "Swordstalker",2000,1600,"No Effect",6
Data "Battle Ox",1700,1000,"No Effect",5
Data "Battle Ox",1700,1000,"No Effect",5
Data "Hane-Hane",450,500,"FLIP:1 monster back to owners hand",2
Data "Dark Assailant",1200,1200,"No Effect",4
Data "Skull Red Bird",1550,1200,"No Effect",4
Data "La Ginn The Mgical Genie Of The Lamp",1800,1000,"No Effect",4
Data "Master & Expert",1200,1000,"No Effect",4
Data "Orge Of The Black Shadow",1200,1400,"No Effect",4
Data "Ryu-Kishin",1000,500,"No Effect",3
Data "Hitotsu-Me Giant",1200,1000,"No Effect",4
Data "Trap Master",500,1100,"No Effect",3
Data "Rouge Doll",1600,1000,"No Effect",4
Data "Ray & Temprature",1000,1000,"No Effect",3
|
| ||
| The way to do it is certainly by shuffling the cards, because your calculating is done up front. This method ensures that each card's position is swapped at least once: ----------------------------------------------------------- dim deck(51) function shuffle() for x=0 to 51 deck(x)=x next for x=0 to 51 temp=rand(0,51) ;get a random pointer into the array deckstore=deck(x) ;store the current value of the array deck(x)=deck(temp) ;swap with the random array element deck(temp)=deckstore ;restore the previous value next end function ----------------------------------------------------------- Of course, you can call this function as many times as you like to do multiple shuffles. Also, don't forget previous advice in this thread about seeding the random number generator. |
| ||
for a different approach, i use a "ripple" shuffle to simulate the way a person would shuffle a deck by hand (uses a Type def to store the card info and Deck array of idnums for the actual gameplay). Here's my basic cardgame template:
Const MAXCARDS = 52
Const MAXSHUFFLE = 7
Local i
Type tCard
Field idnum
Field suit$
Field value
End Type
Global CardDeck.tCard
Dim Deck(MAXCARDS) ;holds the idnum of cards...used in actual gameplay
Dim LeftHalf(MAXCARDS) ;holds the cards for shuffling from the "left hand"
Dim RightHalf(MAXCARDS) ;holds the cards for shuffling from the "right hand"
SeedRnd MilliSecs()
LoadCardDeck() ;load card info into the Type def
ResetDeck() ;reset Deck() to initial order
CheckDeck("unshuffled.txt") ;output unshuffled deck to check cards
ShuffleDeck(MAXCARDS) ;shuffle all cards
CheckDeck("shuffled.txt") ;output shuffled deck to check cards
Notify "Done"
End
Function ShuffleDeck(shufflecnt)
;shuffle deck routine
Local curcard, leftcnt, rightcnt, incleft, incright, cutcnt
leftcnt = Int(shufflecnt / 2) + Rand(-5,5) ;get half +/- 5 cards for left hand
rightcnt = Int(shufflecnt - leftcnt) ;remainder goes into right hand
Dim LeftHalf(leftcnt) ;re-dim just in case
Dim RightHalf(rightcnt)
;actual shuffle loop
For x = 1 To MAXSHUFFLE
For i = 1 To leftcnt ;load lefthalf from Deck()
LeftHalf(i) = Deck(i)
Next
For i = 1 To rightcnt ;load righthalf from Deck()
RightHalf(i) = Deck(leftcnt + i)
Next
;shuffle lefthalf & righthalf back into Deck() (overwrites whats already in Deck())
curcard = 0
incleft = 0
incright = 0
Repeat
If x Mod 2 = 0 ;even iteration, start with lefthalf
For y = 1 To Rand(3) ;pull up to 3 cards from lefthalf
incleft = incleft + 1
If incleft > leftcnt Then Exit ;exit if ran out of lefthalf
curcard = curcard + 1
Deck(curcard) = LeftHalf(incleft) ;overwrite Deck() with cards pulled back
Next
For y = 1 To Rand(3) ;now pull up to 3 cards from righthalf
incright = incright + 1
If incright > rightcnt Then Exit ;exit if ran out of righthalf
curcard = curcard + 1
Deck(curcard) = RightHalf(incright) ;overwrite Deck() with cards pulled back
Next
Else ;odd iteration, start with righthalf...
For y = 1 To Rand(3) ;...do as above...
incright = incright + 1
If incright > rightcnt Then Exit
curcard = curcard + 1
Deck(curcard) = RightHalf(incright)
Next
For y = 1 To Rand(3)
incleft = incleft + 1
If incleft > leftcnt Then Exit
curcard = curcard + 1
Deck(curcard) = LeftHalf(incleft)
Next
EndIf
Until curcard >= shufflecnt
Next
End Function
Function LoadCardDeck()
;currently creates a normal deck of 52 cards (less jokers)
Local i
For i = 1 To MAXCARDS
CardDeck = New tCard
CardDeck\idnum = i
Select True
Case i >= 1 And i <= 13
CardDeck\suit$ = "Spades"
CardDeck\value = i
Case i >= 14 And i <= 26
CardDeck\suit$ = "Hearts"
CardDeck\value = i-13
Case i >= 27 And i <= 39
CardDeck\suit$ = "Clubs"
CardDeck\value = i-26
Case i >= 40 And i <= 52
CardDeck\suit$ = "Diamonds"
CardDeck\value = i-39
End Select
Next
End Function
Function ResetDeck()
;reset the deck array into it's original order
Local i
For i = 1 To MAXCARDS ;Deck() is full and in original order
Deck(i) = i
Next
End Function
Function GetCard.tCard(cardnum)
;go to cardnum (for pulling card info)
For theCard.tCard = Each tCard
If theCard\idnum = cardnum Then Return theCard
Next
Return Null
End Function
Function CheckDeck(outputfilename$)
;output deck just for debug purposes
FileOut = WriteFile(outputfilename$)
For i = 1 To MAXCARDS
CardDeck.tCard = GetCard(Deck(i))
WriteLine(FileOut,CardDeck\idnum + ":" + CardDeck\suit$ + "-" + CardDeck\value)
Next
CloseFile FileOut
End Function
(appologies if this comes out in a wierd format...it's my first post!) |