今天我们用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')
最后为喜欢玩狼人杀的小伙伴们送上一则位置学攻略吧——