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 Posts: 117

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

• Mod
Posts: 6,872

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.

• Posts: 117

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

• Mod
Posts: 6,872

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

• Mod
Posts: 6,872

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

• Mod
Posts: 6,872

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
``````
• Posts: 117

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
``````
• Mod
Posts: 6,872

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: 414

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
``````
• Mod
Posts: 6,872

@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
``````
• Mod
Posts: 6,872

@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: 414

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

• Mod
Posts: 6,872

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

• Mod
Posts: 6,872

@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: 414

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

• Mod
Posts: 6,872

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

• Mod
edited February 25 Posts: 6,872

@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: 414

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

• Mod
Posts: 6,872

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

• Mod
Posts: 3,277

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
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
fontSize(60)
fill(255, 255, 255, 255)
text(str, WIDTH/2,HEIGHT-60)

-- Card count, this is being constantly updated
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
``````
• Mod
edited March 5 Posts: 6,872

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: 414

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

• Mod
Posts: 3,277

@LoopSpace thanks for this analysis.

• Mod
Posts: 6,872

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.