Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Cards in general

edited December 2017 in Questions Posts: 117

Cards in General, this is just a study along with a Lua book

Comments

  • dave1707dave1707 Mod
    Posts: 7,200

    Do a search for Ignatz tutorials. I don't know it he did anything for card games. Do a forum search for what you want, you'll find some info there.

  • This prints to a compiler just fine, but how can I get these cards randomized ? I think I could put a table.insert and a math.random somewhere.....
    ~~~
    suit={"♠️","♣️","♥️","♦️"}
    val={"2","3","4","5","6","7","8","9","10","J","Q","K","A"}
    cards={}
    for x=1,4 do
    for y=1,13 do
    str=string.format(" %s\n%s",val[y],suit[x])
    table.insert(cards,str)
    print(val[y],suit[x])
    end
    end
    ~~~

    P.S. : This is just a study along with a Lua book....

  • dave1707dave1707 Mod
    Posts: 7,200

    @kendog400 There are a lot of card programs already written in this forum. Try doing a search for them and you’ll find code to randomize a deck of cards.

  • dave1707dave1707 Mod
    Posts: 7,200

    @kendog400 I don’t know what you’re doing, but in one of your other card game programs that you posted, you have a very nice shuffle function that shuffles a deck of cards.

  • dave1707dave1707 Mod
    Posts: 7,200

    Here’s something I came up with that you can look thru.

    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    
    function setup()
        s={" ♥️"," ♠️"," ♦️"," ♣️"}
        v={" 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10"," J"," Q"," K"," A"}
        deck={}
        for z=0,51 do
            table.insert(deck,v[z%13+1]..s[z//13+1])
        end
    end
    
    function draw()
        background(151, 223, 223, 255)
        fontSize(40)
        fill(255)
        text("Tap screen to shuffle",WIDTH/2,HEIGHT-50)
        for z=0,51 do
            text(deck[z+1],275+(z//13)*150,50+(z%13)*50)
        end
    end
    
    function shuffle()
        for q=1,100 do
            a,b=math.random(52),math.random(52)
            deck[a],deck[b]=deck[b],deck[a]
        end
    end
    
    function touched(t)
        if t.state==BEGAN then
            shuffle()
        end
    end
    
  • Thanks !...I'm just reading a book on Lua and trying to get a good comprehension...If I can understand whats going on I can tackle it !..

  • edited February 25 Posts: 117

    I would like to know why when i touch the screen the PGM deals cards, when it should only deal when i touch the Deal button...Can someone help ?

    -- Shuffle
    
    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    
    function setup()
       suit={"♠️","♣️","♥️","♦️"}
       value={"2","3","4","5","6","7","8","9","10","J","Q","K","A"}
       Shuffled=shuffleCards(5)
       r=0
    end
    
    function draw()
       background(230, 228, 219, 255)
       fill(45, 127, 37, 255)
       font("Copperplate-Bold")
       fontSize(50)
       card=0
       fill(0, 5, 255, 255)
       text("Player 1",WIDTH/2,HEIGHT-40)
       text("Player 2",WIDTH-150,500)
       text("Player 3",WIDTH/2,280)
       text("Player 4",130,500)
       font("AmericanTypewriter-Bold")
       fontSize(50)
       for round=1,r do
           for player=1,4 do
               card=card+1
               s=math.ceil(Shuffled[card]/13)   -- get suit value
               v=Shuffled[card]%13+1                -- get card value
               str=value[v].." of "..suit[s]            -- print card
               fill(0)
               if s>2 then
                   fill(255,0,0)
               end
               if player==1 then
                   text(str,WIDTH/2,HEIGHT-30-60*round)
               end  
               if player==2 then
                   text(str,WIDTH-150,480-55*round)
               end  
               if player==3 then
                   text(str,WIDTH/2,275-50*round)
               end  
               if player==4 then
                   text(str,120,490-50*round)
               end            
           end      
       end
       fill(0)
       rect(0,0,WIDTH,50)
    
       -- This is the Reset button
        fill(255, 255, 255, 255)
        stroke(255, 0, 8, 255)
        strokeWidth(4)
        ellipse(865, 650,150)
        fill(0, 0, 0, 255)
        font("Copperplate-Bold")
        fontSize(40)
        text("Reset",WIDTH/2+350,HEIGHT-120) 
    
          -- This is the Deal button
        fill(255, 255, 255, 255)
        stroke(255, 0, 8, 255)
        strokeWidth(4)
        ellipse(150, 650,150)
        fill(0, 0, 0, 255)
        font("Copperplate-Bold")
        fontSize(50)
        text("Deal",WIDTH/2-365,HEIGHT-120)             
    end 
    
    
    function touched(t)
       if t.state==BEGAN then
          if t.x>765 and t.x<915 and t.y>550 and t.y<700 then
             sound("Game Sounds One:1-2 Go")
               Shuffled=shuffleCards(5)
               r=0
               return
           end
           r=r+1
           if r>5 then
               r=5
           end
       end
    
        if t.state==BEGAN then
          if t.x>50 and t.x<200 and t.y>550 and t.y<700 then
             sound("Game Sounds One:Bell 2")
                 draw()
          end
        end
    end
    
    function shuffleCards(x)
       local d1, d2, s, y, z = {}, {}
       for z=1,52 do
           d2[z]=z                             -- fill table with numbers 1 to 52
       end      
       for y=1,x do                           -- shuffle x number of times
           d1,d2=d2,{}
           for z=1,52 do
               s=math.random(1,#d1)    -- get a random number from table d1
               table.insert(d2,d1[s])           -- insert it in table d2
               table.remove(d1,s)    -- remove it from table d1
           end
       end
       return d2                               -- return shuffled deck
    end
    
  • dave1707dave1707 Mod
    Posts: 7,200

    In the touched() function your adding 1 to r when you don’t touch a button. In the draw() function you’re displaying more cards because r was increased.

  • Posts: 117

    I tried a few steps, but i’m baffled as to what to do ?

  • Posts: 117

    In the draw function i changed the
    for round=1,r do to for found=1,4 and it automatically spits out 4 cards a player...

  • Posts: 422

    Just by-the-by, the standard algorithm for shuffling a table is the Fisher-Yates-Knuth algorithm. In lua, it looks like this:

    function Shuffle(n)
        local l
        local p = {}
        for k = 1,n do
            p[k] = k
        end
        for k = 1,n-1 do
            l = math.random(k,n)
            if l ~= k then
                p[k],p[l] = p[l],p[k]
            end
        end
        return p
    end
    

    This creates a table with 1,...,n in a shuffled order, which can then be used as indices to another table to extract them in the given order. Eg:

    cards = { ... }
    order = Shuffle(52)
    for i=1,52 do
        print (cards[order[i]])
    end
    
  • dave1707dave1707 Mod
    Posts: 7,200

    @kendog400 Press the shuffle button to shuffle the cards. Press the deal button to deal a card. Make whatever changes you need.

    -- Shuffle
    
    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    
    function setup()
       suit={"♠️","♣️","♥️","♦️"}
       value={"2","3","4","5","6","7","8","9","10","J","Q","K","A"}
       Shuffled=shuffleCards(5)
    end
    
    function draw()
       background(230, 228, 219, 255)
       fill(45, 127, 37, 255)
       font("Copperplate-Bold")
       fontSize(50)
       card=0
       fill(0, 5, 255, 255)
       text("Player 1",WIDTH/2,HEIGHT-40)
       text("Player 2",WIDTH-150,500)
       text("Player 3",WIDTH/2,350)
       text("Player 4",130,500)
       font("AmericanTypewriter-Bold")
       fontSize(50)
       for round=1,r do
           for player=1,4 do
               card=card+1
               s=math.ceil(Shuffled[card]/13)   -- get suit value
               v=Shuffled[card]%13+1                -- get card value
               str=value[v].." of "..suit[s]            -- print card
               fill(0)
               if s>2 then
                   fill(255,0,0)
               end
               if player==1 then
                   text(str,WIDTH/2,HEIGHT-30-60*round)
               end  
               if player==2 then
                   text(str,WIDTH-150,480-55*round)
               end  
               if player==3 then
                   text(str,WIDTH/2,350-50*round)
               end  
               if player==4 then
                   text(str,120,490-50*round)
               end            
           end      
       end
       fill(0)
       rect(0,0,WIDTH,50)
    
       -- This is the Shuffle button
        fill(255, 255, 255, 255)
        stroke(255, 0, 8, 255)
        strokeWidth(4)
        ellipse(865, 650,150)
        fill(0, 0, 0, 255)
        font("Copperplate-Bold")
        fontSize(40)
        text("Shuffle",WIDTH/2+350,HEIGHT-120) 
    
          -- This is the Deal button
        fill(255, 255, 255, 255)
        stroke(255, 0, 8, 255)
        strokeWidth(4)
        ellipse(150, 650,150)
        fill(0, 0, 0, 255)
        font("Copperplate-Bold")
        fontSize(50)
        text("Deal",WIDTH/2-365,HEIGHT-120)             
    end 
    
    function touched(t)
        if t.state==BEGAN then
            if t.x>75 and t.x<225 and t.y>575 and t.y<725 then
                sound("Game Sounds One:1-2 Go")
                r=r+1
                if r>5 then
                    r=5
                end
            elseif t.x>790 and t.x<940 and t.y>575 and t.y<725 then
                sound("Game Sounds One:Bell 2")
                Shuffled=shuffleCards(5)
                r=0
            end
        end
    end
    
    function shuffleCards(x)
        r=0
        local d1, d2, s, y, z = {}, {}
        for z=1,52 do
            d2[z]=z                             -- fill table with numbers 1 to 52
        end      
        for y=1,x do                           -- shuffle x number of times
            d1,d2=d2,{}
            for z=1,52 do
                s=math.random(1,#d1)    -- get a random number from table d1
                table.insert(d2,d1[s])           -- insert it in table d2
                table.remove(d1,s)    -- remove it from table d1
            end
        end
        return d2                               -- return shuffled deck
    end
    
  • dave1707dave1707 Mod
    Posts: 7,200

    @LoopSpace Here’s a shuffle routine I wrote that seems to work OK. The deck is created 1 time and the shuffle routine will shuffle the previously shuffled deck. Tap the screen to shuffle and print deck sequence.

    function setup()
        -- create the deck 1 time
        deck={}
        for z=1,52 do
            table.insert(deck,z)
        end
    end
    
    function touched(t) -- touch screen to shuffle deck and display numbers
        if t.state==BEGAN then
            shuffle()
            print(table.concat(deck," "))
        end
    end
    
    function shuffle()  -- shuffle the shuffled deck
        for z=1,200 do  -- swap random positions 200 times
            r1,r2=math.random(52),math.random(52)   -- create 2 random positions
            deck[r1],deck[r2]=deck[r2],deck[r1] -- swap numbers at 2 positions
        end
    end
    
  • Posts: 422

    @dave1707 Not all algorithms are equal, see this post for a discussion of shuffling algorithms in particular.

  • dave1707dave1707 Mod
    Posts: 7,200

    @LoopSpace Thanks for the link, I was looking for something like that but never found one. I’m not saying that routine is perfect, but it gets the job done. Each shuffle will take the previously shuffled deck and shuffle it again. I don’t think you can say that one sequence of numbers is more random than any other. Every sequence of numbers has the same chance of occurring as any other sequence. Even if the same sequence occurs twice in a row doesn’t mean it’s not random. Now to get back to that link and read more.

  • dave1707dave1707 Mod
    Posts: 7,200

    @LoopSpace Looking at the explanation of a 3 card deck at the link you provided, they say the 6 combinations of sequences should be about equal. Random sequences don’t happen equally. If I flip a coin 1000 times, does that mean I should have 500 heads and 500 tails. 990 heads and 10 tails has the same chance of happening as any other combination, but that doesn’t mean it’s not random. So far I’m not agreeing to much with that link, but I’ll keep on reading.

  • Posts: 422

    @dave1707 Not time for a long reply, but you're wrong in what you say:

    If I flip a coin 1000 times, does that mean I should have 500 heads and 500 tails. 990 heads and 10 tails has the same chance of happening as any other combination

    If you prescribe the order of the 500 heads and tails, and of the 990 heads and tails then yes, each is as likely to occur as the other. However, when we say "500 heads and tails" then we (usually) mean without taking order into account. In that case, there are far, far more ways of getting 500 heads and tails than 990 heads and 10 tails.

    Extremes are helpful: there is precisely one way to get 1000 heads. But there are 1000 ways to get 999 heads and 1 tail. So 999 heads is 1000 times more likely that 1000 heads.

  • dave1707dave1707 Mod
    Posts: 7,200

    @LoopSpace I agree with you on the coin toss, that was a bad choice on my part. Right now I’m writing code to check my shuffle using a 3 card deck to see how the counts come up for the six different combinations.

  • dave1707dave1707 Mod
    edited February 25 Posts: 7,200

    @LoopSpace Here’s the results of a 3 card shuffle after 3 1,000,000 count runs. The top is using my shuffle and the bottom is using the shuffle from the link. I think my shuffle comes close to the results they want.

    Using my shuffle
        123      166620  166399  167344
        132      166754  166264  167280
        213      167025  166627  166550
        231      166755  166702  166236
        312      166739  167196  166064
        321      166107  166812  166526
    
    Using their shuffle
        123      148082  148162  148045
        132      185607  184335  185147
        213      184932  185002  185207
        231      184785  185815  184404
        312      148035  148325  148299
        321      148559  148361  148898
    

    Ps. I should have used 600,000 instead of 1,000,000 to match their results.

  • Posts: 422

    @dave1707 You're right, in a sense, but wrong in another. Your algorithm is different to the one that Jeff Attwood uses but I wasn't critiquing the specific algorithm but rather saying that shuffling algorithms are subtle.

    Your algorithm is a random walk on the graph of arrangements connected by transpositions. This converges to a uniform distribution, which is why you're seeing the roughly even distribution. However, your algorithm is expensive. You need to do a lot of transpositions relative to the number of objects to get it to be uniform. Your original code used 200 swaps and I don't think that would be enough for 52 cards. It is enough for 3 cards, as shown in your tests, but it is 100 more swaps than necessary. When shuffling 3 cards, only two swaps are necessary.

    (Though in actual fact, shuffling 52 cards reaches the limit of the pseudo-random generator - it won't reach all possible shuffles of 52 cards simply because there are too many of them. But that's a different aspect.)

  • dave1707dave1707 Mod
    Posts: 7,200

    @LoopSpace I was trying to find something that would say how well a random sequence was random, but didn’t find anything. But one thing I tried on my shuffle was to see how many numbers (1-52) when shuffled ended up in their numerical position, ie 5 in position 5, 25 in position 25, etc. When I kept shuffling and checking, a lot of times 1 number was in its numerical position. Sometimes I had 0 and sometimes I had 2. I didn’t have more than 2, but I didn’t check on the order of thousands of runs. I don’t know how well that checks anything, but for a shuffle for a simple card game, I think it works OK. I don’t know if there’s an optimal number of swaps, but I picked 200 for no reason.

  • Jmv38Jmv38 Mod
    Posts: 3,280

    to shuffle i like to use this

    -- shuffle
    function setup()
        deck = {}
        for i=1,10 do
            deck[i] = i
        end
        print(table.concat(deck,"-"))
        deck = shuffle(deck)
        print(table.concat(deck,"-"))
    end
    
    function shuffle(t)
        temp = {}
        for i,v in pairs(t) do
            temp[i] = {v, math.random()}
        end
        table.sort(temp, function(a,b) return a[2]<b[2] end)
        for i,v in pairs(temp) do
            t[i] = temp[i][1]
        end
        return t
    end
    

    I assume this method has no caveats?

  • edited March 4 Posts: 117

    On line 53, is there a way that the card value could be printed upside down like a real card ? Take a peek anyone...

    --- Random Card
    
    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    
    function setup()
       rectMode(CENTER)
       suit={{" ♥️",” ♦️"," ♠️"," ♣️ "}
       u={" 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10"," J"," Q"," K"," A"}
       deck={}                        -- Table for the cards
       createDeck()                   -- Goto createDeck
       getCard=true                   -- Show the first card
       cc = 52                        -- Keep count of the Cards
    end
    
    function draw()
       -- Background color
       background(31, 34, 97, 255)
       if getCard then                --if a card is showing
           getCard=false              --Dont get another until the button is touched
           randomCard()               --Goto the random card fx
           c=v%13+1                   --The card value
           s=math.ceil(v/13)
       end
    
       -- This is the white card background
       fill(255)
       rect(WIDTH/2,HEIGHT/2,350,500)      --This is the WHT rectangle, location & Size
    
       -- Font & font size of the suit & value
       font("AmericanTypewriter-Bold") 
       fontSize(160) --size of suit font
    
        --This is the card suit being printed to the screen
       text(suit[s],WIDTH/2,HEIGHT/2) 
    
        -- This is the different colors of the suits
       if s==1 then --hearts 
           fill(255,0,0)  
            elseif 
        s==2 then --dimonds
           fill(31, 0, 255, 255)  
            elseif 
        s==3 then --spades
           fill(0, 0, 0, 255)  
            elseif 
        s==4 then --clubs
           fill(31, 109, 53, 255)  
       end
    
       -- This is the card value
       text(u[c],WIDTH/2-90,HEIGHT/2+170)  
       text(u[c],WIDTH/2+80,HEIGHT/2-170)         -- This is line 53,,,,,,
    
        --End of deck suit
        font("Baskerville-BoldItalic")
        fontSize(60)
        fill(255, 255, 255, 255)
        text(str, WIDTH/2,HEIGHT-60)  
    
        -- Card count, this is being constantly updated
        font("Baskerville-BoldItalic")
        fontSize(50)
        fill(255, 255, 255, 255)
        text(cc, WIDTH-875,HEIGHT/2)  
    
        -- Plain text
        font("Copperplate-Bold")
        fontSize(50)
        fill(255, 255, 255, 255)
        text("Cards left\n in Deck :", WIDTH-855,HEIGHT/2+80)  
    
       -- This is the button
        fill(255, 255, 255, 255)
        stroke(255, 0, 8, 255)
        strokeWidth(4)
        ellipse(865, 420,150)
        fill(0, 0, 0, 255)
        font("Copperplate-Bold")
        fontSize(50)
        text("Next",WIDTH/2+350,HEIGHT-345)        
    end 
    --This is the touch area location
        -- The 'x', subtract 100 from 865 = 765
        -- The 'y', subtract 100 from 420 = 320
        -- Stretch this 150 pixels
    function touched(t)
        if t.state==BEGAN then
            if t.x>765 and t.x<915 and t.y>320 and t.y<470 then
                sound("Game Sounds One:Bell 2")
                 getCard=true
            end
        end
    end
    
    function createDeck()
      str = "Tap button for next card"
       for z=1,52 do
           deck[z]=z
       end
    end
    
    function randomCard()
    -- This plucks a random card then subtracts it from the Main deck
       if #deck>0 then     --if there are any cards left in the deck, then pluck
           d=math.random(#deck)     --pluck at random
           v=deck[d]
           table.remove(deck,d)      --after being plucked, remove it from the deck
       else
            str = "End of Deck"
       end
    -- This keeps track of the amount of cards left in the deck
        if cc <= 52 then   --cc means card-count
            cc = cc - 1
        end
    end
    
  • dave1707dave1707 Mod
    edited March 5 Posts: 7,200

    It can be done but it’s more work. Here's an example for 1 card. You use the translate and rotate commands.

    function setup()
    end
    
    function draw()
        background(40, 40, 50)
        stroke(255, 164, 0, 255)
        strokeWidth(5)
        fill(255)
        rect(200,300,130,200)
        fill(255,0,0)
        text("2",220,480)
        text("♥️",220,460)
        scale(2,2)
        text("♥️",133,220)
        scale(.5,.5)
    
        -- show things upside down
        translate(300,300)
        rotate(180)
        text("2",-10,-20)
        text("♥️",-10,-40)
        scale(2,2)
        text("♥️",18,-30)
        translate(-300,-300)
    end
    
  • Posts: 117

    Thanks...

  • Posts: 117

    It worked...

  • Posts: 422

    @Jmv38 Your sort does produce shuffles with the correct distribution, but it you do more steps than necessary. As you're using a sort (I can't recall which sort table.sort uses off the top of my head), you are typically doing n log(n) swaps, whereas the optimal algorithm uses n-1 swaps.

    So your algorithm is less efficient than the Knuth-Fisher-Yates one.

    (The actual multiplier is trickier since one measures complexity of algorithms in "big-O" notation, which ignores certain factors.)

  • Jmv38Jmv38 Mod
    Posts: 3,280

    @LoopSpace thanks for this analysis.

  • dave1707dave1707 Mod
    Posts: 7,200

    I would say as long as people arent winning or losing tens of thousands of dollars based on the above sort routines, then whichever one is used doesn’t really matter that much. As long as it appears to be random and doesn’t take a long time, then that’s good enough. But it’s still interesting to see all the different routines and comments about them.

Sign In or Register to comment.