经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
Python实现带图形界面的炸金花游戏
来源:jb51  时间:2022/12/5 8:48:25  对本文有异议

炸金花

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

规则:

一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁赢。

牌型:

豹子:三张一样的牌,如3张6.

顺金:又称同花顺,即3张同样花色的顺子, 如红桃 5、6、7

顺子:又称拖拉机,花色不同,但是顺子,如红桃5、方片6、黑桃7,组成的顺子

对子:2张牌一样

单张:单张最大的是A

版型大小顺序: 豹子>顺金>顺子>对子>单张

从网上百科到的诈金花各种牌型的出现概率,一起放进代码中增加一点趣味小知识。你可能不知道豹子出现的概率比同花顺大,实际打牌时同花顺反而比豹子小;顺子出现的概率比金花小,实际打牌时顺子反而比金花小;最大牌为5、6、7的单张牌型出现的概率都要比金花和顺子小,所以有的地方额外规定同一局中拿到“235”三张牌要比同局的豹子大。

回到正题,直接上代码,主要2个函数:一个计分、一个比大小

  1. from random import shuffle as DealCards
  2. Players = 5 #人数
  3. pkPacks = 1 #扑克副数
  4. W = "单张","对子","顺子","金花","顺金","豹子"
  5. X = 74.38, 16.94, 3.26, 4.96, 0.22, 0.24 #出现概率
  6. Y = 0.54, 1.36, 2.44, 3.8, 5.43, 7.33, 9.5, 11.95, 14.66, 17.38 #单张概率
  7. V = *(str(i) for i in range(2,10)),*'TJQKA' #T代表10
  8. F = '?', '?', '?', '?'
  9. P = [f+v for f in F for v in V]*pkPacks
  10. def Scores(pokers):
  11. f,p = [],[]
  12. for poker in pokers:
  13. f.append(F.index(poker[0])+1)
  14. p.append(V.index(poker[1])+2)
  15. t = sorted(p)
  16. if len(set(t))==1:
  17. return 500_0000+t[0] #豹子
  18. elif len(set(t))==2: #对子
  19. if t[0]==t[1]: #对子一样大比较剩下的单张
  20. return (100+t[1])*10000+t[2]
  21. else:
  22. return (100+t[1])*10000+t[0]
  23. else:
  24. if t[0]+1==t[1]==t[2]-1:
  25. if len(set(f))==1:
  26. return 400_0000+t[2] #顺金(同花顺)
  27. else:
  28. return 200_0000+t[2] #顺子
  29. else:
  30. if len(set(f))==1:
  31. return ((300+t[2])*100+t[1])*100+t[0] #金花
  32. else:
  33. return (t[2]*100+t[1])*100+t[0] #单张
  34. def WhoWins(P):
  35. Pokers,Winner = [],[]
  36. for i in range(0,3*Players,3):
  37. Pokers.append(P[i:i+3])
  38. for i,p in enumerate(Pokers,1):
  39. win = Scores(p)
  40. idx = win//100_0000
  41. print(f"Player{i}: {*p,} - {W[idx]}")
  42. Winner.append(win)
  43. win = max(Winner) #没有判断“一样大”,如是则谁在前谁为大
  44. idx = Winner.index(win)
  45. big = win//10000
  46. win = big//100
  47. per = X[win] if win else Y[big-5]
  48. pok = W[win] if win else '单'+V[big-2]
  49. print(f"【Player{idx+1} win!】--> {*Pokers[idx],} {pok}({per}%)\n")
  50. return P[3*Players:] #去掉每一局已发的牌
  51. if __name__ == '__main__':
  52. DealCards(P) #以随机洗牌来模拟发牌
  53. #Players = int(input('请输入参加的人数?'))
  54. PlayersMax = 52*pkPacks//3+1
  55. if not 0<Players<PlayersMax:
  56. print(f'请注意:参与人数的范围 0 < Players < {PlayersMax} !')
  57. else:
  58. count = 1
  59. while len(P)>=3*Players: #所有牌(52*PokerPairs)发不够一局为止
  60. print(f'第{count}局:')
  61. count += 1
  62. 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 完整源代码:

  1. import tkinter as tk
  2. from PIL import Image,ImageTk
  3. from time import sleep
  4. from random import shuffle as DealCards
  5. Players = 4 #人数
  6. pkPacks = 1 #扑克副数
  7. isReady = True
  8. W = "单张","对子","顺子","金花","顺金","豹子"
  9. X = 74.38, 16.94, 3.26, 4.96, 0.22, 0.24 #出现概率
  10. Y = 0.54, 1.36, 2.44, 3.8, 5.43, 7.33, 9.5, 11.95, 14.66, 17.38 #单张概率
  11. V = *(str(i) for i in range(2,10)),*'TJQKA' #T代表10
  12. F = '?', '?', '?', '?'
  13. def loadCards():
  14. infile = Image.open("pokers.png")
  15. Images = []
  16. for j in range(4):
  17. image = []
  18. for i in range(15):
  19. box = infile.crop((i*100,j*150,i*100+100,j*150+150))
  20. img = ImageTk.PhotoImage(image=box)
  21. image.append(img)
  22. Images.append(image)
  23. infile.close()
  24. return Images
  25. def dealCards():
  26. global cv,cards,isReady,P,Pokers
  27. if not isReady:
  28. return
  29. cv.itemconfig(txt1, text="")
  30. cv.itemconfig(txt2, text="")
  31. if len(Pokers):
  32. for j in range(3):
  33. for i in range(4):
  34. cv.itemconfig(cards[i][j], image=Cards[0][0])
  35. cv.update()
  36. sleep(0.5)
  37. for j in range(3):
  38. for i in range(4):
  39. cv.itemconfig(cards[i][j], image=Cards[1][0])
  40. cv.update()
  41. sleep(0.3)
  42. if len(P)==0 or len(P)<12:
  43. P = [f+v for f in F for v in V]*pkPacks
  44. DealCards(P)
  45. isReady = False
  46. def playCards():
  47. global cv,isReady,P,Pokers,cards,Cards
  48. if isReady:
  49. return
  50. P = WhoWins(P)
  51. for i,pok in enumerate(Pokers):
  52. for j,p in enumerate(pok):
  53. x = F.index(p[0])
  54. y = V.index(p[1])
  55. #print(x,y,'-',i,j)
  56. cv.itemconfig(cards[i][j], image=Cards[x][y+2])
  57. cv.update()
  58. isReady = True
  59. def Scores(pokers):
  60. f,p = [],[]
  61. for poker in pokers:
  62. f.append(F.index(poker[0])+1)
  63. p.append(V.index(poker[1])+2)
  64. t = sorted(p)
  65. if len(set(t))==1:
  66. return 500_0000+t[0] #豹子
  67. elif len(set(t))==2: #对子
  68. if t[0]==t[1]: #对子一样大比较剩下的单张
  69. return (100+t[1])*10000+t[2]
  70. else:
  71. return (100+t[1])*10000+t[0]
  72. else:
  73. if t[0]+1==t[1]==t[2]-1:
  74. if len(set(f))==1:
  75. return 400_0000+t[2] #顺金(同花顺)
  76. else:
  77. return 200_0000+t[2] #顺子
  78. else:
  79. if len(set(f))==1:
  80. return ((300+t[2])*100+t[1])*100+t[0] #金花
  81. else:
  82. return (t[2]*100+t[1])*100+t[0] #单张
  83. def WhoWins(P):
  84. global cv,txt1,txt2,Pokers
  85. Pokers,Winner = [],[]
  86. for i in range(0,3*Players,3):
  87. Pokers.append(P[i:i+3])
  88. for i,p in enumerate(Pokers,1):
  89. win = Scores(p)
  90. idx = win//100_0000
  91. print(f"Player{i}: {*p,} - {W[idx]}")
  92. Winner.append(win)
  93. win = max(Winner) #没有判断“一样大”,如是则谁在前谁为大
  94. idx = Winner.index(win)
  95. big = win//10000
  96. win = big//100
  97. per = X[win] if win else Y[big-5]
  98. pok = W[win] if win else '单'+V[big-2]
  99. text1 = f"【Player{idx+1} win!】"
  100. text2 = f"{pok}{*Pokers[idx],} {per}%\n"
  101. print(text1,'--> ',text2)
  102. cv.itemconfig(txt1, text=text1)
  103. cv.itemconfig(txt2, text=text2)
  104. return P[3*Players:] #去掉每一局已发的牌
  105. def test():
  106. global Pokers
  107. print("测试:",Pokers)
  108. if __name__ == '__main__':
  109. root = tk.Tk()
  110. root.geometry('1024x768')
  111. root.title('诈金花')
  112. cv = tk.Canvas(root, width=1024, height=680, bg='darkgreen')
  113. cv.pack()
  114. Pokers = []
  115. Cards = loadCards()
  116. cards = [[None]*3 for _ in range(4)]
  117. P = [f+v for f in F for v in V]*pkPacks
  118. DealCards(P)
  119. x1, x2, x3 = 400, 80, 730
  120. y1, y2, y3 = 100, 550, 320
  121. dx1,dx2,dy = 105, 105, 0
  122. imgxy = [[(x1,y1),(x1+dx1,y1),(x1+2*dx1,y1)],[(x3,y3),(x3+dx2,y3+dy),(x3+2*dx2,y3+dy*2)],
  123. [(x1,y2),(x1+dx1,y2),(x1+2*dx1,y2)],[(x2,y3),(x2+dx2,y3+dy),(x2+2*dx2,y3+dy*2)]]
  124. for x,lst in enumerate(imgxy):
  125. for y,coord in enumerate(lst):
  126. cards[x][y] = cv.create_image(coord, image=Cards[0][0])
  127. cv.create_rectangle(coord[0]-50,coord[1]-75,coord[0]+50,coord[1]+75)
  128. tx,ty = coord[0]-100,coord[1]+92
  129. cv.create_text(tx,ty, text=f'Player{x+1}', fill='white')
  130. btn = [None]*3
  131. btn[0] = tk.Button(root,text='发牌',command=dealCards,width=10)
  132. btn[1] = tk.Button(root,text='开牌',command=playCards,width=10)
  133. btn[2] = tk.Button(root,text='测试',command=test,width=10)
  134. for i in range(3):
  135. btn[i].place(y=710, x=350+i*110)
  136. txt1 = cv.create_text(510,300, fill='red', font=("宋体", 16))
  137. txt2 = cv.create_text(510,360, fill='red', font=("宋体", 10))
  138. root.mainloop()

【编译程序】

Windows的Cmd窗口中执行如下命令,Mac系统自行百度:

pyinstaller -F exam.py --noconsole

注意:记得把上面的牌型图保存为Pokers.png和代码放一起运行。

到此这篇关于Python实现带图形界面的炸金花游戏的文章就介绍到这了,更多相关Python炸金花游戏内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号