Cards in general

@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.)

@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.

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?

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\
 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

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

Thanks…

It worked…

@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.)

@LoopSpace thanks for this analysis.

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.

when i touch the display to shuffle, the shuffled cards appear then i hear the shuffled sounds, i need to delay the screen until after i hear the shuffled sounds.
Take a peek, I tried to put an elapsed time in, but I might have put it in the wrong place

displayMode(FULLSCREEN)

function setup()
t=ElapsedTime
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(10, 26, 223)
fontSize(30)
fill(255, 255, 255)
text("Tap screen \
to shuffle",WIDTH/2-250,HEIGHT-120)
for z=0,51 do
text(deck[z+1],WIDTH/2-120+(z//13)*80,30+(z%13)*30)
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 ElapsedTime>t+.5 then
-- end
if t.state==BEGAN then
sound(asset.documents.Shuffle_2)
shuffle()
end
end

Try this. I don’t have access to your shuffle sound, so I just picked a standard Codea sound. Replace my sound with yours and adjust the delay value (3) in tween delay to what you want.

PS. When you post code, put three tildes ~~~ on a line before and after your code so it shows OK. I’m not sure why I can’t format your above code.

displayMode(FULLSCREEN)

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(10, 26, 223)
    fontSize(30)
    fill(255, 255, 255)
    text("Tap screen \
to shuffle",WIDTH/2-250,HEIGHT-120)
    for z=0,51 do
        text(deck[z+1],WIDTH/2-120+(z//13)*80,30+(z%13)*30)
    end
end

function touched(t)
    if t.state==BEGAN then
        sound(asset.downloaded.Game_Sounds_One.Pac_Death_2)
        tween.delay(3,shuffle)
    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

@kendog400 Here’s another version. I don’t have your card shuffle sound, so when you add it, adjust the value (.4) in draw to match the length of the shuffle sound.

displayMode(FULLSCREEN)

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
    shuffle()
end

function draw()
    background(10, 26, 223)
    fontSize(30)
    fill(255, 255, 255)
    text("Tap screen \
to shuffle",WIDTH/2-250,HEIGHT-120)
    for z=0,dk do
        text(deck[z+1],WIDTH/2-120+(z//13)*80,30+(z%13)*30)
    end
    if dk<51 then
        dk=dk+.4
    end
end

function touched(t)
    if t.state==BEGAN then
        shuffle()
    end
end

function shuffle()
    sound(asset.downloaded.Game_Sounds_One.Pac_Death_2)
    for q=1,100 do
        a,b=math.random(52),math.random(52)
        deck[a],deck[b]=deck[b],deck[a]
    end
    dk=0
end

Thanks !

I have here a PGM that deals 4 cards to 4 players, I’m trying to figure out a way to get the 2nd text under the 1st 1…right now the text prints 1 on top of the other and looks sloppy…

~~ Shuffle

displayMode(FULLSCREEN)

function setup()
suit={“??”,“??”,“??”,“??”}
value={“2”,“3”,“4”,“5”,“6”,“7”,“8”,“9”,“10”,“J”,“Q”,“K”,“A”}
Shuffled=shuffleCards(5)
n=50
end

function draw()
background(32, 95, 43)
font(“Copperplate-Bold”)
fontSize(30)
card=0
fill(255)
text(“Player 1”,WIDTH/2,HEIGHT-30) – Player 1 Location
text(“Player 2”,WIDTH/2+250,HEIGHT-170) – Player 2 Location
text(“Player 3”,WIDTH/2,HEIGHT-250) – Player 3 Location
text(“Player 4”,WIDTH/2-250,HEIGHT-170) – Player 4 Location
font(“AmericanTypewriter-Bold”) – Change the font
fontSize(30) – Size of card font

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 r>1 then
n=n+2
–end
–==================================
end
if player==1 then
text(str,WIDTH/2+5,HEIGHT/2+(n+85)*round)
end
if player==2 then
text(str,WIDTH/2+250,HEIGHT/2+(n-56)*round)
end
if player==3 then
text(str,WIDTH/2+10,HEIGHT/2+(n-138)*round)
end
if player==4 then
text(str,WIDTH/2-240,HEIGHT/2+(n-58)*round)
end
end
end
fill(0) – this fills the bottom rect with Blk
rect(0,0,WIDTH,42) – this is the red highliteer

– This is the Shuffle button
fill(255, 255, 255, 255)
stroke(255, 0, 8, 255)
strokeWidth(4)
ellipse(565,275,100)
fill(0, 0, 0, 255)
font(“Copperplate-Bold”)
fontSize(40)
text(“Shuffle”,WIDTH/2+230,HEIGHT-30)

  -- This is the Deal button
fill(255, 255, 255, 255)
stroke(255, 0, 8, 255)
strokeWidth(4)
ellipse(80,275,100)
fill(0, 0, 0, 255)
font("Copperplate-Bold")
fontSize(50)
text("Deal",WIDTH/2-250,HEIGHT-30)             

end

function touched(t)
if t.state==BEGAN then
if t.x>40 and t.x<140 and t.y>275 and t.y<375 then
sound(asset.documents.Card_Deal,.5)
r=r+1
if r>5 then
r=5
end
elseif t.x>465 and t.x<665 and t.y>275 and t.y<375 then
sound(asset.documents.Card_Shuffle,.5)
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 ~~

If you tick the deal button twice you will see what I mean, I tried to put in a variable that would increase, but all I see is the card float up or down.

Your touched function is missing part of the code and your if statements are missing the = or other character for the compare. Plus there’s other functions missing.

Next I wud like to deal two cards and keep a score, which ever player has the highest score wins… This wud help me get my roll on…

Could you give me a hint on how I could fix this ?..

Fix what. How to post all the code or how to fix what you want. We can’t fix code when all of it isn’t there to run or see.