详细的Python炸金花游戏代码

**

详细的Python炸金花游戏代码

**
觉得有用请点个赞吧

#!/usr/bin/env python
# -*- coding: utf-8 -*- 
'''
# @Time: 2022/07/15 00:21 
# @Author: lzl 
# @File: 7-15炸金花棋牌游戏-思路版.py
'''
'''
编写炸金花游戏程序自己写一个程序,实现发牌,比大小判断输嬴.
游戏规则:
一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁嬴.
有以下几种牌:
1、豹子:三张一样的牌,如3张6.
2、顺金:又称同花顺,即3张同样花色的顺子,如红桃5,6,7
3、顺子:又称拖拉机,花色不同,但是顺子,如红桃5,方片6,黑桃7,组成的顺子
4、金花:三张同样花色的牌, 如红心2、红心5、红心8;
5、对子:两张点数一样的牌,如红心2、黑桃2、方片9;
6、单张:单张最大的是A
这几种牌的大小顺序为,豹子>顺金>同花>顺子>对子>单张
需程序实现的点:
1.先生成一付完整的扑克牌
2.给5个玩家随机发牌
3.统一开牌,比大小,输出赢家是谁
'''

# 思考:
# 1、单牌之间如何比大小
'''# 思考 A玩家:红桃8,红桃J, 黑桃K--(8+11+13)   <  B玩家:黑桃9,方片10,梅花A--(9+10+14)
# 只是单独数值相加不可行比如牌型(8 J K)<(2 3 A),但是其数值8+11+13 > 2+3+14
# 所以也得考虑权重,越大的牌权重越大,先排序-然后 大牌*100+中牌*10+小牌'''

# 2、不同牌型之问如何比大小【考虑不同权重--最大的单牌(J K A)至少比最小的对子小(2 2 3)】
# 3、如何判断玩家是什么牌 (高内聚,低耦合)(不同牌型封装成一个函数)
'''val = [2, 2, 3]
if len(set(val)) == 2:
    print('对子')
elif len(set(val)) == 1:
    print('豹子')'''

import random


# 一、生成牌
def creat_pk():
    flower_color = ['♠', '♥', '♣', '♦']     #花色类型
    pk_num = [f'{i}' for i in range(2, 11)] + ['J', 'Q', 'K', 'A']      # 牌面类型
    pk_list = []        # 用于记录所有牌
    for i in flower_color:
        count = 2
        for j in pk_num:
            pk_list.append([f'{i}{j}', count])
            # count用于记录牌面大小,方便后续计分[['♣A', 14], ['♦K', 13], ['♠Q', 12],['♣J', 11], ['♦9', 9], ['♠6', 6]...]
            count += 1
    return pk_list

pk_list = creat_pk()
plays = ['lzl', '赵', '钱', '孙', '李']


# 二、发牌
def deal_cards(plays, pk_list):
    pl_cards_dict = {}
    for pl in plays:
        random_cards = random.sample(pk_list, 3)
        pl_cards_dict[pl] = random_cards
        print(f'已为玩家{pl}发牌成功')
        for card in random_cards:
            pk_list.remove(card)  
            # 已发出的牌,从牌列表中删除
    return pl_cards_dict

pl_cards_dict = deal_cards(plays, pk_list)
for i in pl_cards_dict:
#查看各玩家手中的牌
    print(f'玩家{i}的牌是: {pl_cards_dict[i]}')


# 三、写好每种牌型的判断规则函数
# 1、排序:
def sort_list(lis):
    # 冒泡排序, 将形如lis=[['♣K', 13], ['♦9', 9], ['♠6', 6]]例表排序
    l = len(lis)
    for i in range(l):
        for j in range(l-i-1):
            if lis[j][1] > lis[j+1][1]:     
            # 如果前者大于后者
                lis[j],lis[j+1] = lis[j+1],lis[j]   
                # 则前者与后者调换位置
    return lis

# 2、单牌计分
'''
# 【都有A牌时,K开头的最小牌(A K 2) 要大于 Q开头的最大牌(A Q J)】
设置设置最大数权重为x,第二大的数权重为y,则14x+13y+2>14x+12y+11--->y>9,所以可取值y=10
【A开头的最小牌(A 2 3) 要大于 K开头最大牌(K Q 10)的分值】
设置最大数权重为x,第二大的数权重为y,则14x+3y+2>13x+12y+10--->x-9y-8>0,所以可取值 y=10,则x=100'''
def calculate_single(pl_cards,score):       
# 形如pl_cards = [['♣K', 13], ['♦9', 9], ['♠6', 6]]
    pl_cards = sort_list(pl_cards)       # 先对单牌进行排序
    weight_vals = [1, 10, 100]      
    # 权重单独拿出,方便后续更改权重值,比如【10,100,1000】
    count = 0
    for card in pl_cards:
        score += card[1] * weight_vals[count]
        count += 1
    print(f'计算单牌分数', pl_cards, score)
    return score

# 3、对子计分,(谁重要谁加权重)
'''
# 思考一:【最小的对子 > 最大单牌【即(2 2 3)大于(A K J)】,将对子的分值再加权重】
在单牌计分基础上再加权重 2+2*10+3*100=322,14*100+13*10+11=1541【322x > 1541---> x>=5】
思考二:存在bug ,理论上【最小对子+最大单牌(2 2 A)】 <  【第二小对子+次小单牌(3 3 4)】;【(但是按上述分值2+2*10+14*100=1422 > 3+3*10+4*100=433)】
对对子所在位置进行增加权重 【最小的对子 > 最大单牌【即(2 2 3)大于 (A K J)=A*100+K*10+J=1541;假设对子2的权重x: (2+2)x+3>1541--->可令x=400】
'''
def calculate_pair(pl_cards,score):     
# 形如pl_cards = [['♣A', 14], ['♦10', 10], ['♠3', 3]]
    pl_cards = sort_list(pl_cards)
    card_values = [i[1] for i in pl_cards]  # 将映射的值取出来
    if len(set(card_values)) == 2:      
    #set() 取集合,相同的元素会去除,当长度为2:说明有一个重复
        if card_values[0] ==card_values[1]:     
        # 对子排序在前,比如 3 3 9
            score = (card_values[0] + card_values[1]) * 400 +card_values[2]
        else:       # 对子排序在后,比如 5 9 9
            score = (card_values[2] + card_values[1]) * 400 +card_values[0]
    print(f'对子计分', pl_cards, score)
    return score


# 4、顺子计分
'''
最大的对子【A A K--得分(14+14)*400+13=11213】 < 最小顺子【2 3 4---得分2+3*10+4*100=432】
从上可知,假设顺子权重x,则432x > 11213 ; 可令 x=30
'''
def calculate_straight(pl_cards,score):
    pl_cards = sort_list(pl_cards)
    card_values = [i[1] for i in pl_cards]  # 将映射的值取出来
    if card_values[2]-card_values[1] == card_values[1]-card_values[0]==1:
        score *= 30
    print(f'顺子计分', pl_cards, score)
    return score


# 5、同花计分
'''
# 考虑最小同花(♥2 ♥3 ♥5)[2+3*10+5*100=532] > 最大顺子(♥Q ♣K ♦A)[(12+13*10+14*100)*30=46260],所以配个权重100,532*100=53200>46260
'''
def calculate_same_color(pl_cards,score):    
# 形如pl_cards = [['♣A', 14], ['♦10', 10], ['♠3', 3]]
    color_type = {i[0][0] for i in pl_cards}
    # 将花色提取出来, 用{}表示集合,会自动去重【i=pl_cards[0]=['♣A', 14], i[0]=['♣A'],  i[0][0]='♣'】
    if len(color_type) == 1:
        score *= 100
    print(f'同花计分', pl_cards, score)
    return score

# 6、同花顺计分,
'''
--同花顺会匹配上面的 顺子计分 和 同花计分, 即已经做过两次计分了,在此就不用对分值在加权重了
所以考虑最大同花顺,最小同花顺此时计分多少,好计算给豹子配多少权重
最大同花顺(Q K A)[(12+13*10+14*100)*30*100=4626000],最小同花顺(2 3 4)[(2+3*10+4*100)*30*100=1296000]
'''
def calculate_same_color_straight(pl_cards,score):
    pl_cards = sort_list(pl_cards)
    card_values = [i[1] for i in pl_cards]  # 将映射的值取出来
    if card_values[2] - card_values[1] == card_values[1] - card_values[0] == 1:
        color_type = {i[0][0] for i in pl_cards}
        # 将花色提取出来, 用{}表示集合,会自动去重【i=pl_cards[0]=['♣A', 14], i[0]=['♣A'],  i[0][0]='♣'】
        if len(color_type) == 1:
            score
            print(f'同花顺计分', pl_cards, score)
    return score


# 7、豹子计分:
'''
最小豹子(2 2 2)按单牌计分为2+2*10+2*100=222
最大同花顺(Q K A)[(12+13*10+14*100)*30*100=4626000]
所以豹子的权重为4626000/222=20838,取权重21000
'''
def calculate_leopard(pl_cards,score):
    card_values = [i[1] for i in pl_cards]  # 将映射的值取出来
    if len(set(card_values)) == 1:
        score *= 21000
    print(f'豹子计分', pl_cards, score)
    return score



# 4、 对比
calculate_funcs = [       # calculate--计算
    calculate_single,       # 单排 single--单一的,单个的
    calculate_pair,         # 对子 pair--对子,一双,一对
    calculate_straight,     # 顺子 straight--直的,顺的	
    calculate_same_color,   # 同花 same--同样的
    calculate_same_color_straight,      #同花顺
    calculate_leopard       # 豹子
]

performance = []

for p_name, p_cards in pl_cards_dict.items():
    print(f'开始计算玩家{p_name}的牌')
    score = 0
    for calc_func in calculate_funcs:
        score = calc_func(p_cards, score)
    performance.append([p_name, score])

winner = sort_list(performance)[-1]     
# 排序后最后一位就是最大分数

for i in performance:       
	# 如果谁的分数和最大的分数一样,谁就是赢家,两人一样就两位赢家
    if int(i[1]) == int(winner[1]):
        print(f'赢家是{i}')

运行后得到输出结过:

已为玩家lzl发牌成功
已为玩家赵发牌成功
已为玩家钱发牌成功
已为玩家孙发牌成功
已为玩家李发牌成功
玩家lzl的牌是: [['♥4', 4], ['♦5', 5], ['♥6', 6]]
玩家赵的牌是: [['♠3', 3], ['♠5', 5], ['♦K', 13]]
玩家钱的牌是: [['♦A', 14], ['♣3', 3], ['♥10', 10]]
玩家孙的牌是: [['♦J', 11], ['♣J', 11], ['♦2', 2]]
玩家李的牌是: [['♠K', 13], ['♣Q', 12], ['♠9', 9]]
开始计算玩家lzl的牌
计算单牌分数 [['♥4', 4], ['♦5', 5], ['♥6', 6]] 654
对子计分 [['♥4', 4], ['♦5', 5], ['♥6', 6]] 654
顺子计分 [['♥4', 4], ['♦5', 5], ['♥6', 6]] 19620
同花计分 [['♥4', 4], ['♦5', 5], ['♥6', 6]] 19620
豹子计分 [['♥4', 4], ['♦5', 5], ['♥6', 6]] 19620
开始计算玩家赵的牌
计算单牌分数 [['♠3', 3], ['♠5', 5], ['♦K', 13]] 1353
对子计分 [['♠3', 3], ['♠5', 5], ['♦K', 13]] 1353
顺子计分 [['♠3', 3], ['♠5', 5], ['♦K', 13]] 1353
同花计分 [['♠3', 3], ['♠5', 5], ['♦K', 13]] 1353
豹子计分 [['♠3', 3], ['♠5', 5], ['♦K', 13]] 1353
开始计算玩家钱的牌
计算单牌分数 [['♣3', 3], ['♥10', 10], ['♦A', 14]] 1503
对子计分 [['♣3', 3], ['♥10', 10], ['♦A', 14]] 1503
顺子计分 [['♣3', 3], ['♥10', 10], ['♦A', 14]] 1503
同花计分 [['♣3', 3], ['♥10', 10], ['♦A', 14]] 1503
豹子计分 [['♣3', 3], ['♥10', 10], ['♦A', 14]] 1503
开始计算玩家孙的牌
计算单牌分数 [['♦2', 2], ['♦J', 11], ['♣J', 11]] 1212
对子计分 [['♦2', 2], ['♦J', 11], ['♣J', 11]] 8802
顺子计分 [['♦2', 2], ['♦J', 11], ['♣J', 11]] 8802
同花计分 [['♦2', 2], ['♦J', 11], ['♣J', 11]] 8802
豹子计分 [['♦2', 2], ['♦J', 11], ['♣J', 11]] 8802
开始计算玩家李的牌
计算单牌分数 [['♠9', 9], ['♣Q', 12], ['♠K', 13]] 1429
对子计分 [['♠9', 9], ['♣Q', 12], ['♠K', 13]] 1429
顺子计分 [['♠9', 9], ['♣Q', 12], ['♠K', 13]] 1429
同花计分 [['♠9', 9], ['♣Q', 12], ['♠K', 13]] 1429
豹子计分 [['♠9', 9], ['♣Q', 12], ['♠K', 13]] 1429
赢家是['lzl', 19620]

觉得有用请留个赞吧

  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值