Python实现带图形界面的炸金花游戏
作者:Hann?Yang 发布时间:2021-06-21 15:41:56
炸金花
题目很简单:就是自己写一个程序,实现诈金花游戏的发牌、判断输赢。
规则:
一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁赢。
牌型:
豹子:三张一样的牌,如3张6.
顺金:又称同花顺,即3张同样花色的顺子, 如红桃 5、6、7
顺子:又称拖拉机,花色不同,但是顺子,如红桃5、方片6、黑桃7,组成的顺子
对子:2张牌一样
单张:单张最大的是A
版型大小顺序: 豹子>顺金>顺子>对子>单张
从网上百科到的诈金花各种牌型的出现概率,一起放进代码中增加一点趣味小知识。你可能不知道豹子出现的概率比同花顺大,实际打牌时同花顺反而比豹子小;顺子出现的概率比金花小,实际打牌时顺子反而比金花小;最大牌为5、6、7的单张牌型出现的概率都要比金花和顺子小,所以有的地方额外规定同一局中拿到“235”三张牌要比同局的豹子大。
回到正题,直接上代码,主要2个函数:一个计分、一个比大小
from random import shuffle as DealCards
Players = 5 #人数
pkPacks = 1 #扑克副数
W = "单张","对子","顺子","金花","顺金","豹子"
X = 74.38, 16.94, 3.26, 4.96, 0.22, 0.24 #出现概率
Y = 0.54, 1.36, 2.44, 3.8, 5.43, 7.33, 9.5, 11.95, 14.66, 17.38 #单张概率
V = *(str(i) for i in range(2,10)),*'TJQKA' #T代表10
F = '♠', '♥', '♣', '♦'
P = [f+v for f in F for v in V]*pkPacks
def Scores(pokers):
f,p = [],[]
for poker in pokers:
f.append(F.index(poker[0])+1)
p.append(V.index(poker[1])+2)
t = sorted(p)
if len(set(t))==1:
return 500_0000+t[0] #豹子
elif len(set(t))==2: #对子
if t[0]==t[1]: #对子一样大比较剩下的单张
return (100+t[1])*10000+t[2]
else:
return (100+t[1])*10000+t[0]
else:
if t[0]+1==t[1]==t[2]-1:
if len(set(f))==1:
return 400_0000+t[2] #顺金(同花顺)
else:
return 200_0000+t[2] #顺子
else:
if len(set(f))==1:
return ((300+t[2])*100+t[1])*100+t[0] #金花
else:
return (t[2]*100+t[1])*100+t[0] #单张
def WhoWins(P):
Pokers,Winner = [],[]
for i in range(0,3*Players,3):
Pokers.append(P[i:i+3])
for i,p in enumerate(Pokers,1):
win = Scores(p)
idx = win//100_0000
print(f"Player{i}: {*p,} - {W[idx]}")
Winner.append(win)
win = max(Winner) #没有判断“一样大”,如是则谁在前谁为大
idx = Winner.index(win)
big = win//10000
win = big//100
per = X[win] if win else Y[big-5]
pok = W[win] if win else '单'+V[big-2]
print(f"【Player{idx+1} win!】--> {*Pokers[idx],} {pok}({per}%)\n")
return P[3*Players:] #去掉每一局已发的牌
if __name__ == '__main__':
DealCards(P) #以随机洗牌来模拟发牌
#Players = int(input('请输入参加的人数?'))
PlayersMax = 52*pkPacks//3+1
if not 0<Players<PlayersMax:
print(f'请注意:参与人数的范围 0 < Players < {PlayersMax} !')
else:
count = 1
while len(P)>=3*Players: #所有牌(52*PokerPairs)发不够一局为止
print(f'第{count}局:')
count += 1
P = WhoWins(P)
运行结果:
第1局:
Player1: ('♥Q', '♣2', '♣8') - 单张
Player2: ('♦T', '♥7', '♠6') - 单张
Player3: ('♣4', '♠4', '♦2') - 对子
Player4: ('♠5', '♠9', '♥6') - 单张
Player5: ('♠7', '♠3', '♣5') - 单张
【Player3 win!】--> ('♣4', '♠4', '♦2') 对子(16.94%)
第2局:
Player1: ('♥2', '♥8', '♦4') - 单张
Player2: ('♦9', '♦3', '♥A') - 单张
Player3: ('♠J', '♣A', '♦K') - 单张
Player4: ('♠8', '♥9', '♥T') - 顺子
Player5: ('♣7', '♣9', '♣T') - 金花
【Player5 win!】--> ('♣7', '♣9', '♣T') 金花(4.96%)
第3局:
Player1: ('♦7', '♦J', '♠2') - 单张
Player2: ('♥J', '♦A', '♥K') - 单张
Player3: ('♥4', '♥5', '♦6') - 顺子
Player4: ('♣Q', '♣J', '♠T') - 顺子
Player5: ('♣K', '♦8', '♦5') - 单张
【Player4 win!】--> ('♣Q', '♣J', '♠T') 顺子(3.26%)
扩展
学习要举一反三,做完题目想到把这个程序的界面图形化。无非就是把牌型对应列表下标从下图中索引取出相应的图片来对应到Image控件上;想要输出的文字对应到text控件上;再整2个button控件绑定对应的事件动作。(代码中有第3个button是我测试用的)
牌型图: Pokers.png
初始界面:
发牌界面:
开牌界面:
PokersV1.py 完整源代码:
import tkinter as tk
from PIL import Image,ImageTk
from time import sleep
from random import shuffle as DealCards
Players = 4 #人数
pkPacks = 1 #扑克副数
isReady = True
W = "单张","对子","顺子","金花","顺金","豹子"
X = 74.38, 16.94, 3.26, 4.96, 0.22, 0.24 #出现概率
Y = 0.54, 1.36, 2.44, 3.8, 5.43, 7.33, 9.5, 11.95, 14.66, 17.38 #单张概率
V = *(str(i) for i in range(2,10)),*'TJQKA' #T代表10
F = '♠', '♥', '♣', '♦'
def loadCards():
infile = Image.open("pokers.png")
Images = []
for j in range(4):
image = []
for i in range(15):
box = infile.crop((i*100,j*150,i*100+100,j*150+150))
img = ImageTk.PhotoImage(image=box)
image.append(img)
Images.append(image)
infile.close()
return Images
def dealCards():
global cv,cards,isReady,P,Pokers
if not isReady:
return
cv.itemconfig(txt1, text="")
cv.itemconfig(txt2, text="")
if len(Pokers):
for j in range(3):
for i in range(4):
cv.itemconfig(cards[i][j], image=Cards[0][0])
cv.update()
sleep(0.5)
for j in range(3):
for i in range(4):
cv.itemconfig(cards[i][j], image=Cards[1][0])
cv.update()
sleep(0.3)
if len(P)==0 or len(P)<12:
P = [f+v for f in F for v in V]*pkPacks
DealCards(P)
isReady = False
def playCards():
global cv,isReady,P,Pokers,cards,Cards
if isReady:
return
P = WhoWins(P)
for i,pok in enumerate(Pokers):
for j,p in enumerate(pok):
x = F.index(p[0])
y = V.index(p[1])
#print(x,y,'-',i,j)
cv.itemconfig(cards[i][j], image=Cards[x][y+2])
cv.update()
isReady = True
def Scores(pokers):
f,p = [],[]
for poker in pokers:
f.append(F.index(poker[0])+1)
p.append(V.index(poker[1])+2)
t = sorted(p)
if len(set(t))==1:
return 500_0000+t[0] #豹子
elif len(set(t))==2: #对子
if t[0]==t[1]: #对子一样大比较剩下的单张
return (100+t[1])*10000+t[2]
else:
return (100+t[1])*10000+t[0]
else:
if t[0]+1==t[1]==t[2]-1:
if len(set(f))==1:
return 400_0000+t[2] #顺金(同花顺)
else:
return 200_0000+t[2] #顺子
else:
if len(set(f))==1:
return ((300+t[2])*100+t[1])*100+t[0] #金花
else:
return (t[2]*100+t[1])*100+t[0] #单张
def WhoWins(P):
global cv,txt1,txt2,Pokers
Pokers,Winner = [],[]
for i in range(0,3*Players,3):
Pokers.append(P[i:i+3])
for i,p in enumerate(Pokers,1):
win = Scores(p)
idx = win//100_0000
print(f"Player{i}: {*p,} - {W[idx]}")
Winner.append(win)
win = max(Winner) #没有判断“一样大”,如是则谁在前谁为大
idx = Winner.index(win)
big = win//10000
win = big//100
per = X[win] if win else Y[big-5]
pok = W[win] if win else '单'+V[big-2]
text1 = f"【Player{idx+1} win!】"
text2 = f"{pok}{*Pokers[idx],} {per}%\n"
print(text1,'--> ',text2)
cv.itemconfig(txt1, text=text1)
cv.itemconfig(txt2, text=text2)
return P[3*Players:] #去掉每一局已发的牌
def test():
global Pokers
print("测试:",Pokers)
if __name__ == '__main__':
root = tk.Tk()
root.geometry('1024x768')
root.title('诈金花')
cv = tk.Canvas(root, width=1024, height=680, bg='darkgreen')
cv.pack()
Pokers = []
Cards = loadCards()
cards = [[None]*3 for _ in range(4)]
P = [f+v for f in F for v in V]*pkPacks
DealCards(P)
x1, x2, x3 = 400, 80, 730
y1, y2, y3 = 100, 550, 320
dx1,dx2,dy = 105, 105, 0
imgxy = [[(x1,y1),(x1+dx1,y1),(x1+2*dx1,y1)],[(x3,y3),(x3+dx2,y3+dy),(x3+2*dx2,y3+dy*2)],
[(x1,y2),(x1+dx1,y2),(x1+2*dx1,y2)],[(x2,y3),(x2+dx2,y3+dy),(x2+2*dx2,y3+dy*2)]]
for x,lst in enumerate(imgxy):
for y,coord in enumerate(lst):
cards[x][y] = cv.create_image(coord, image=Cards[0][0])
cv.create_rectangle(coord[0]-50,coord[1]-75,coord[0]+50,coord[1]+75)
tx,ty = coord[0]-100,coord[1]+92
cv.create_text(tx,ty, text=f'Player{x+1}', fill='white')
btn = [None]*3
btn[0] = tk.Button(root,text='发牌',command=dealCards,width=10)
btn[1] = tk.Button(root,text='开牌',command=playCards,width=10)
btn[2] = tk.Button(root,text='测试',command=test,width=10)
for i in range(3):
btn[i].place(y=710, x=350+i*110)
txt1 = cv.create_text(510,300, fill='red', font=("宋体", 16))
txt2 = cv.create_text(510,360, fill='red', font=("宋体", 10))
root.mainloop()
【编译程序】
Windows的Cmd窗口中执行如下命令,Mac系统自行百度:
pyinstaller -F exam.py --noconsole
注意:记得把上面的牌型图保存为Pokers.png和代码放一起运行。
来源:https://blog.csdn.net/boysoft2002/article/details/128146513


猜你喜欢
- 一、Position1、语法:position:static/ absolute / fixed / relative2、参数:(1)sta
- 本文实例讲述了python简单实现旋转图片的方法。分享给大家供大家参考。具体实现方法如下:# rotate an image counter
- SQLPlus是进行Oracle操作的主要前台工具,用户名和密码分别为用户名和密码,连接ORACLE数据库可见,显示的比较混乱,可以通过以下
- 给静态网页加密的方法有很多,有的简单有的复杂。前两天看见有人问静态网页加密问题,就写了这个代码思路:加密时:先把用户的密钥A用md5加密为B
- 楔子上一篇文章我们探讨了 GIL 的原理,以及如何释放 GIL 实现并行,做法是将函数声明为 nogil,然后使用 with nogil 上
- 网络上有很多关于语言选择的问题,其中关于Python和Java的问题大抵如下:Python和Java该如何选择 ?将来Python(Java
- 关于 WARNING: Ignoring invalid distribution -pencv-python … 警
- Python 堆栈堆栈是一个后进先出(LIFO)的数据结构. 堆栈这个数据结构可以用于处理大部分具有后进先出的特性的程序流 . 在堆栈中,
- 前言:keras是一个十分便捷的开发框架,为了更好的追踪网络训练过程中的损失函数loss和准确率accuracy,我们有几种处理方式,第一种
- pygame绘制机制简介 屏幕控制 pygame.display• 用来控制Pygame游戏的屏幕• Pygame有且只有一个屏幕
- 在asp中获取当前的地址栏网址很简单,使用下面这句语句即能实现获取网站域名Request.ServerVariables("HTT
- 准备工作安装anaconda,官网下载安装,笔者安装在"D:\Anaconda3"安装好之后,查看环境变量path中是否
- 使用cv2.canny进行图像边缘检测CV2提供了提取图像边缘的函数canny。其算法思想如下:1.使用高斯模糊,去除噪音点(cv2.Gau
- Python Assert 为何不尽如人意?Python中的断言用起来非常简单,你可以在assert后面跟上任意判断条件,如果断言失败则会抛
- 假设我有一个DataFrame(df)如下:name age idmike 10 1tony 14 2lee 20 3现在我想把id 放到最
- 刚整理了一些关于javascript cookies操作的文章,发现这篇文章也不错,推荐大家一起参考,选择需要的,不足的地方主要是对路径的设
- 前言什么是OCR?光学字符识别(Optical Character Recognition, OCR),是指对文本资料的图像文件进行分析识别
- 前言最近有人对自动上传与发布很感兴趣,都私下找我说了好几次了。今天,必须把他安排,必须实力宠粉。“本篇依次介绍目前主流的
- text函数的功能是向数据点添加文本说明。语法text(x,y,txt)text(x,y,z,txt)text(___,Name,Value
- 按照 官方教程 ,下载安装包,点击安装后,如需在命令行启动,还需设置命令路径:在命令行中,打开配置文件 .bash_profile:vim