Python实现带图形界面的炸金花游戏

作者:Hann?Yang 时间:2021-06-21 15:41:56 

炸金花

Python实现带图形界面的炸金花游戏

题目很简单:就是自己写一个程序,实现诈金花游戏的发牌、判断输赢。

规则:

一付扑克牌,去掉大小王,每个玩家发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: ('&hearts;Q', '&clubs;2', '&clubs;8') - 单张
Player2: ('&diams;T', '&hearts;7', '&spades;6') - 单张
Player3: ('&clubs;4', '&spades;4', '&diams;2') - 对子
Player4: ('&spades;5', '&spades;9', '&hearts;6') - 单张
Player5: ('&spades;7', '&spades;3', '&clubs;5') - 单张
【Player3 win!】--> ('&clubs;4', '&spades;4', '&diams;2') 对子(16.94%)
第2局:
Player1: ('&hearts;2', '&hearts;8', '&diams;4') - 单张
Player2: ('&diams;9', '&diams;3', '&hearts;A') - 单张
Player3: ('&spades;J', '&clubs;A', '&diams;K') - 单张
Player4: ('&spades;8', '&hearts;9', '&hearts;T') - 顺子
Player5: ('&clubs;7', '&clubs;9', '&clubs;T') - 金花
【Player5 win!】--> ('&clubs;7', '&clubs;9', '&clubs;T') 金花(4.96%)
第3局:
Player1: ('&diams;7', '&diams;J', '&spades;2') - 单张
Player2: ('&hearts;J', '&diams;A', '&hearts;K') - 单张
Player3: ('&hearts;4', '&hearts;5', '&diams;6') - 顺子
Player4: ('&clubs;Q', '&clubs;J', '&spades;T') - 顺子
Player5: ('&clubs;K', '&diams;8', '&diams;5') - 单张
【Player4 win!】--> ('&clubs;Q', '&clubs;J', '&spades;T') 顺子(3.26%)

扩展

学习要举一反三,做完题目想到把这个程序的界面图形化。无非就是把牌型对应列表下标从下图中索引取出相应的图片来对应到Image控件上;想要输出的文字对应到text控件上;再整2个button控件绑定对应的事件动作。(代码中有第3个button是我测试用的)

牌型图: Pokers.png

Python实现带图形界面的炸金花游戏

初始界面:

Python实现带图形界面的炸金花游戏

发牌界面:

Python实现带图形界面的炸金花游戏

开牌界面:

Python实现带图形界面的炸金花游戏

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

标签:Python,炸金花,游戏
0
投稿

猜你喜欢

  • asp全面解析Server对象

    2008-10-19 17:24:00
  • ASP实现文件直接下载的代码

    2011-04-11 10:56:00
  • 何时将数据装载到Application 或 Session 对象中去?

    2009-12-03 20:17:00
  • Oracle备库宕机启动的完美解决方案

    2023-07-20 05:28:34
  • Microsoft SQL Server 2000安装问题集锦

    2008-12-10 14:26:00
  • python爬虫容易学吗

    2023-08-24 09:48:26
  • Python如何通过变量ID得到变量的值

    2023-01-22 22:35:56
  • Win7的IIS7中ASP获得的系统日期格式为斜杠的解决办法

    2012-12-04 19:57:33
  • Python异常处理如何才能写得优雅(retrying模块)

    2023-07-13 05:50:44
  • python调用matlab的m自定义函数方法

    2023-11-11 21:40:52
  • base href 使用方法详解

    2008-05-18 13:27:00
  • 适合所有表的添加、删除、修改的函数

    2008-04-15 15:29:00
  • php投票系统之增加与删除投票(管理员篇)

    2023-10-14 09:44:53
  • Python Pandas对缺失值的处理方法

    2021-03-18 19:38:55
  • Python图像处理之直线和曲线的拟合与绘制【curve_fit()应用】

    2021-01-28 10:30:49
  • 用javascript替换URL中的参数值示例代码

    2023-08-30 03:58:09
  • 编写兼容IE和FireFox的脚本

    2009-05-19 12:01:00
  • PHP htmlspecialchars()函数用法与实例讲解

    2023-06-02 16:48:38
  • 带进度条的ASP无组件断点续传大文件下载

    2010-06-25 18:27:00
  • 使用SQL Server 2008管理非结构化数据

    2009-01-08 15:28:00
  • asp之家 网络编程 m.aspxhome.com