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: ('♥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和代码放一起运行。

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

(0)

相关推荐

  • Python实现炸金花游戏的示例代码

    今天的第二个作品,哈哈哈哈,搞起来感觉还挺有意思的,不过代码里纸牌J,Q,K,A几个数字被我替换成了11,12,13,14......主要是没有想到简单的办法让其比较,索性都用数字了,我太菜了,希望有大佬指点一下. 代码如下: import random   #导入随机数函数 def puke():     """     生成一副52张的扑克牌(除去大小王)     :return:     """     list1 = ['黑桃', '红桃

  • 基于Python制作炸金花游戏的过程详解

    目录 前言 一.思路 二.解决方案 三.总结 前言 <诈金花>又叫三张牌,是在全国广泛流传的一种民间多人纸牌游戏.比如JJ比赛中的诈金花(赢三张),具有独特的比牌规则.游戏过程中需要考验玩家的胆略和智慧.--<百度百科> 前几天在交流群里边,有个叫[^-^]的粉丝分享了一道扑克牌诈金花的题目,要求用Python实现,题目如下: 自己写一个程序,实现发牌.比大小判断输赢. 游戏规则: 一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁赢. 有以下几种牌: 豹子:三张一样的牌,

  • python编写扎金花小程序的实例代码

    游戏规则: 一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁赢. 有以下几种牌: 豹子:三张一样的牌,如3张6. 顺金:又称同花顺,即3张同样花色的顺子, 如红桃 5.6.7 顺子:又称拖拉机,花色不同,但是顺子,如红桃5.方片6.黑桃7,组成的顺子 对子:2张牌一样 单张:单张最大的是A 这几种牌的大小顺序为, 豹子>顺金>顺子>对子>单张 程序需要实现的点: 先生成一付完整的扑克牌 给5个玩家随机发牌 统一开牌,比大小,输出赢家是谁 主要思路: 把各种牌用积分来计算,

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

    炸金花 题目很简单:就是自己写一个程序,实现诈金花游戏的发牌.判断输赢. 规则: 一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁赢. 牌型: 豹子:三张一样的牌,如3张6. 顺金:又称同花顺,即3张同样花色的顺子, 如红桃 5.6.7 顺子:又称拖拉机,花色不同,但是顺子,如红桃5.方片6.黑桃7,组成的顺子 对子:2张牌一样 单张:单张最大的是A 版型大小顺序: 豹子>顺金>顺子>对子>单张 从网上百科到的诈金花各种牌型的出现概率,一起放进代码中增加一点趣味小知识.你

  • python GUI库图形界面开发之PyQt5信号与槽机制、自定义信号基础介绍

    信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解.信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方. 在linux.windows等 GUI 工具包中,GUI组件都会注册回调函数用于处理组件所触发的动作,通常是注册对应的函数的函数指针.在之前关于Button的文章中提到了信号与槽的机制的使用,通过该机制可以很好的将组件的信号(如button的clocked.toggled.pressed等)和处理该信号的槽关

  • python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例

    在下面这3篇文章中我们给出了手工输入代码的信号与槽的使用方法,因为采用这种方法介绍时,会简单一些,如果使用Qt Designer来介绍这些功能,那么任何一个简单的功能都会使用xxxx.ui xxxx.py call_xxxx.py三个文件 来实现,这样内容会显得很乱 python GUI库图形界面开发之PyQt5信号与槽基础使用方法与实例 python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧(自定义信号与槽)详解与实例 python GUI库图形界面开发之PyQt5信号与槽的高级

  • python GUI库图形界面开发之PyQt5拖放控件实例详解

    本篇,我们学习PyQt5界面中拖放(Drag 和Drop)控件. 拖放动作 在GUI中,拖放指的是点击一个对象,并将其拖动到另一个对象上的动作.比如百度云PC客户端支持的拖放文件以快速移动文件: 拖放动作能够很直观很方便的在GUI程序中完成一些很复杂或繁琐的操作. 在PyQt中实现拖放 在PyQt5中,我们也可以很轻松地使用拖放功能. 使用Qt设计师或者使用API都可以实现.我们先使用Qt设计师将GUI的图形设计出来,在之前的GUI的基础上,我们新建一个选项卡. 我们新建了一个选项卡,然后在里面

  • python GUI库图形界面开发之PyQt5开发环境配置与基础使用

    PyQt5安装 在cmd下输入 pip install PyQt5 完成PyQt5安装,再安装qt designer,可以使用pip安装 pip install PyQt5-tools 安装完成后,在python安装目录下可以看到 配置PyCharm 配置PyCharm是为了在Pycharm里面实现打开qt designer,然后生成qt文件,然后将qt文件转换成python语言的软件文件. 打开Pycharm,按下图操作 打开Extrernal Tools之后,点击上如绿色的+,添加Tools

  • python GUI库图形界面开发之PyQt5信号与槽基本操作

    信号与槽基本操作 进入Qt Designer,加入控件,本文以按钮为例. 按F4开始后,选择需要加入信号与槽的按钮,如下图所示该按钮会变红,按住鼠标拉出一条红线,若该按钮需控制旁边的label,则红线连接到label上(图1),若对框体(MainWindow)进行操作,则链接到框体上,会出现一个像物理中"地线"似的符号(图2). 图1 图2 连接后,会弹出如下窗体(图3),左侧界面选择信号,如下图中选择"clicked()"代表点击按钮触发右侧对应槽的操作. 勾选下

  • python GUI库图形界面开发之PyQt5窗口类QMainWindow详细使用方法

    QMainWindow QMainWindow类中比较重要的方法 方法 描述 addToolBar() 添加工具栏 centralWidge() 返回窗口中心的一个控件,未设置时返回NULL menuBar() 返回主窗口的菜单栏 setCentralWidget() 设置窗口中心的控件 setStatusBar() 设置状态栏 statusBar() 获得状态栏对象后,调用状态栏对象的showMessage(message,int timeout=0)方法 显示状态栏信息,其中第一个参数是要显

  • python GUI库图形界面开发之PyQt5中QMainWindow, QWidget以及QDialog的区别和选择

    PyQt中MainWindow, QWidget以及Dialog的区别和选择 1. Qt界面分类 在Qt Designer设计界面时,首先需要选择界面模板,主要分为三个类: Main Window Widget Dialog 2. 三种模板的区别(官方文档介绍) MainWindow QMainWindow类提供一个有菜单条.锚接窗口(例如工具条)和一个状态条的主应用程序窗口. 主窗口通常用在提供一个大的中央窗口部件(例如文本编辑或者绘制画布)以及周围菜单.工具条和一个状态条.QMainWind

  • python 实现一个图形界面的汇率计算器

    调用的api接口: https://api.exchangerate-api.com/v4/latest/USD 完整代码 import requests from tkinter import * import tkinter as tk from tkinter import ttk class RealTimeCurrencyConverter(): def __init__(self,url): self.data = requests.get(url).json() self.curr

  • Python实现带GUI界面的手写数字识别

    目录 1.效果图 2.数据集 3.关于模型 4.关于GUI设计 5.缺点 6.遗留问题 1.效果图 有点low,轻喷 点击选择图片会优先从当前目录查找 2.数据集 这部分我是对MNIST数据集进行处理保存 对应代码: import tensorflow as tf import matplotlib.pyplot as plt import cv2 from PIL import Image import numpy as np from scipy import misc (x_train_a

随机推荐