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!) |