今天我们用tkinter的canvas画布实现扑克牌的随机发牌:将54张牌随机发给四位牌手,在屏幕上显示每位牌手的牌,利用Canvas将发牌结果显示出来。
需要准备的是54张扑克牌的图片(gif或者png,jpg的话要经过额外的转换),为了保证最终的牌序是按照由小到大排列的,图片编号要按照AAAA、2222……KKKK、大小王来排列(也许A和2应该更大,但是请忽略这一点)。
下面是完整代码:
from tkinter import *
import random
n=54
(player1,player2,player3,player4)=([],[],[],[])
(p1,p2,p3,p4)=([],[],[],[])
pocker=[i for i in range(n)]
imgs=[]
root=Tk()
cv=Canvas(root,bg="White",width=700,height=600)
#洗牌(用随机交换打乱牌序)
def gen_pocker(n):
x=100
while(x>0):
x=x-1
p1=random.randint(0,n-1)
p2=random.randint(0,n-1)
t=pocker[p1]
pocker[p1]=pocker[p2]
pocker[p2]=t
return pocker
pocker=gen_pocker(n) #打乱后的牌组编号
#将图片放入imgs列表
for i in range(1,55):
imgs.insert(i,PhotoImage(file="imgs/"+str(i)+".gif"))
#发牌,
for m in range(0,54,4):
try:
p1.append(pocker[m])
p2.append(pocker[m+1])
p3.append(pocker[m+2])
p4.append(pocker[m+3])
except:
break
#由小到大排序
p1.sort()
p2.sort()
p3.sort()
p4.sort()
#逐一显示图片,其中1号和2号会发到14张牌
for x in range(0,14):
try:
img=imgs[p1[x]]
player1.append(cv.create_image((230+20*x,80),image=img)) #参数控制图片的位置和间隔
img=imgs[p2[x]]
player2.append(cv.create_image((100,150+25*x), image=img))
img = imgs[p3[x]]
player3.append(cv.create_image((230+20*x,500), image=img))
img = imgs[p4[x]]
player4.append(cv.create_image((600,150+25*x), image=img))
except:
pass
cv.pack()
root.mainloop()
图片在百度网盘
链接: https://pan.baidu.com/s/1yHoQCTZ1sde-J3d3qnb4DQ?pwd=m28h 提取码: m28h
模拟结果如图:
稍微改一改也可以用来模拟斗地主:
再改一改也可以模拟狼人杀,逻辑比扑克牌简单多了,不需要排序,而且通常只有12张牌。成果如下:
还可以改变一下布局,既然用的是网易的图片,那就和网易狼人杀的位置一样吧:
如果想看发牌的动画效果,请参考下面的代码:
from tkinter import *
import random
from PIL import Image, ImageTk
import time
n=12
player2,player4=[],[],[],[]
p1,p2,p3,p4=[],[],[],[]
pocker=[i for i in range(n)]
imgs=[]
root=Tk()
cv=Canvas(root,bg="White",width=400,height=600)
for i in range(1,13):
imgs.insert(i,ImageTk.PhotoImage(file="img/"+str(i)+".gif"))
#洗牌(用随机交换打乱牌序)
def gen_pocker(n):
x=10
while(x>0):
x=x-1
p1=random.randint(0,n-1)
p2=random.randint(0,n-1)
t=pocker[p1]
pocker[p1]=pocker[p2]
pocker[p2]=t
return pocker
#发牌
def mm():
global p2,p4 #list本身虽然是全局变量,但如果不用global仅能修改元素,不能重新定义列表
cv.deldete('all')
p2,p4=[],[]
pocker=gen_pocker(n) #打乱后的牌组编号
for m in range(0,12,2):
try:
p2.append(pocker[m])
p4.append(pocker[m+1])
except:
break
#先更新左边一列
def ks(x):
if x==0:
mm()
img=imgs[p2[x]]
player2.append(cv.create_image((100,50+100*x), image=img))
x+=1
#从第七张开始更新右边一列
if x==6:
x2=0
root.after(500,ks2,x2)
return
root.after(500,ks,x)
#更新右侧一列
def ks2(x2):
img = imgs[p4[x2]]
player4.append(cv.create_image((320,50+100*x2), image=img))
x2+=1
#最后一张之后结束
if x2==6:
return
root.after(500,ks2,x2)
button = Button(root, text ="发牌", width=10,height=1,command = lambda:ks(0))
button.place(x=170, y=260)
cv.pack()
root.mainloop()
这样就能实现动态发牌的效果了:
什么?边角位真的总有狼?
有了这个程序,手上没牌也能模拟发牌、研究位置学了。
删除canvas创建的组件方法:在定义时加一个tags属性,然后用delete删除,例如:
cv.create_image((100,100), image=img,tags='o')
cv.delete('o')
最后为喜欢玩狼人杀的小伙伴们送上一则位置学攻略吧——