Python3编写炸金花游戏--超详细的讲解!!

自己写一个程序,实现发牌、比大小判断输赢。

#### 游戏规则

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

有以下几种牌:

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

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

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

对子:2张牌一样

单张:单张最大的是A

这几种牌的大小顺序为, **豹子>顺金>顺子>对子>单张**

#### 需程序实现的点

1. 先生成一付完整的扑克牌

2. 给5个玩家随机发牌

3. 统一开牌,比大小,输出赢家是谁

目录

 讲解思路:

步骤一:初始化牌组列表及玩家列表

步骤二:模拟发牌

效果展示(运行过程中会有停顿感以模拟真实发牌):

步骤三:判断输赢

类Player补充的函数:

完整代码:

效果展示:


 讲解思路:

首先,需要实现两个类:扑克牌Card和玩家Player,然后确定它们的基本属性。

# 定义一个Card类,由牌面和花色初始化
class Card:
    def __init__(self, face="", color=""):
        self.face = face                # 牌面,字符串类型
        self.color = color              # 花色,字符串类型
        self.name = color + face        # 牌的完整名称
        self.prior1 = PRIORITY[face]     # 牌面对应的优先级
        self.prior2 = PRIORITY[color]     # 牌花色对应的优先级

对于扑克牌Card类:牌面、花色、完整名称属性应该很好理解, prior1和prior2主要是对应牌面和花色的优先级,这2个属性是方便比较牌Card对象的大小。所有优先级对应如下: 

# PRIORITY数组用于比较牌面值,花色,牌型的优先级
# A>K>Q>...>2
# 黑桃>红心>方块>梅花
# 豹子>顺金>顺子>对子>单张
PRIORITY = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8,
            '9': 9, '10': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14,
            '梅花♣': 1, '方块♦': 2, '红心♥': 3, '黑桃♠': 4,
            '单张': 1, '对子': 2, '顺子': 3, '顺金': 4, '豹子': 5
            }
# 定义一个Player类,由玩家姓名初始化
class Player:
    def __init__(self, name=""):
        self.card = list()      # 玩家拥有的牌存储在card里面,元素类型为Card
        self.name = name        # 玩家姓名
        self.type = ''          # 牌型
        self.winner = False     # 标志,记录该玩家是否是最后的赢家
        self.pair = 0           # 记录第一张对子牌的索引,默认为0

 对于玩家Player类:玩家姓名name、牌组card属性应该很好理解, 牌型type指定玩家牌属于顺子,豹子等等,winner属性记录玩家是否是赢家,pair记录对子牌的索引。

这个游戏过程我们分为三个步骤,第一步是初始化;第二步是模拟发牌;第三步是判断输赢。

步骤一:初始化牌组列表及玩家列表

此处定义多个全局变量:(牌面有13种情况,花色有4种情况,牌型有5种情况,玩家有5位)

# 分别定义全局变量:牌面值,花色,牌型,玩家姓名
FACES = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
COLORS = ['黑桃♠', '红心♥', '方块♦', '梅花♣']
TYPE = ['豹子', '顺金', '顺子', '对子', '单张']
NAMES = ['#Player1', '#Player2', '#Player3', '#Player4', '#Player5']

 我们需要两个列表来存储52张牌以及5位玩家,列表元素分别是Card对象和Player对象

# 牌组列表初始化为空,玩家组列表初始化为空
CARD_GROUP = list()
PLAYERS = list()

准备工作做好了,接下来填充列表:

# 输入:无
# 输出:无
# 功能:初始化52张的扑克牌列表,即生成一副完整的牌,然后初始化玩家列表
def init():
    CARD_GROUP.clear()  # 清空牌组列表
    for f in FACES:  # 遍历牌面值
        for c in COLORS:  # 遍历花色
            CARD_GROUP.append(Card(f, c))  # 添加扑克牌
    for name in NAMES:  # 初始化玩家列表
        PLAYERS.append(Player(name))  # 添加玩家

步骤二:模拟发牌

直接说思路:每次从列表CARD_GROUP随机抽取一张牌发给玩家,此牌再从牌组中移除。

# 输入:无
# 输出:无
# 功能:实现发牌
def deal():
    # 因为每人需要发三张牌,所以用三次循环实现
    # 模拟随机发牌过程:每次随机抽取一张牌,然后从列表移除
    circle = 3
    for i in range(circle):
        print('第{0}轮发牌:'.format((i + 1)), end='\t')
        for p in PLAYERS:
            temp = random.choice(CARD_GROUP)        # 随机抽牌
            CARD_GROUP.remove(temp)                 # 从牌组移除这张牌
            p.card.append(temp)                     # 将牌加入玩家的card列表里面
            time.sleep(0.7)                         # 体现发牌停顿感,暂停0.7s
            print(temp.name, end='\t\t')            # 打印牌名称
        print()
    print()

效果展示(运行过程中会有停顿感以模拟真实发牌):

步骤三:判断输赢

这个过程中,我们要分两个小过程,首先是判断玩家手中的牌型,把他们分类;然后比较同种牌型下的牌组大小。

1. 判断牌型,这个函数作为Player类的成员函数实现:

    def judge_type(self):                   # 判断牌型,这个过程中,若出现对子类型的牌,则更新属性self.pair
        self.card.sort(reverse=True)        # 对玩家的牌按照优先级从大到小排序
        cards = self.card
        if cards[0].prior1 == cards[1].prior1 and cards[0].prior1 == cards[2].prior1:
            self.type = '豹子'
        elif cards[0].prior1-cards[1].prior1 == 1 and cards[1].prior1-cards[2].prior1 == 1:
            if cards[0].prior2 == cards[1].prior2 and cards[0].prior2 == cards[2].prior2:
                self.type = '顺金'
            else:
                self.type = '顺子'
        elif cards[0].prior1 == cards[1].prior1:
            self.type = '对子'
        elif cards[1].prior1 == cards[2].prior1:        # 排序过后,若出现对子牌,那么它们必定连在一起,所以其实索引0和2不用比较
            self.type = '对子'
            self.pair = 1
        else:
            self.type = '单张'

2. 接下来是“重头戏”:怎么比较玩家手中牌的大小呢?

首先,我们知道有个库函数sort(),用于对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。语法如下:

list.sort( key=None, reverse=False)

仔细分析炸金花游戏的比较过程:首先对于玩家比如说张三手中的牌,需要对这三张牌进行比较,这是第一个排序;然后对于同种牌型的玩家,比如两个人都是对子牌,需要对玩家进行比较,这是第二个排序。像这种对《类对象数组的排序》,有基础的童鞋应该有思路了:实现一个内置函数cmp,然后调用库函数sort就可以了。一开始我以为是重写类的__cmp__()函数,查了半天发现是重写__lt__()函数,其实就是重写<号。这个游戏需要重写两个类的__lt__函数,如下:

    def __lt__(self, other):            # 此处重写Card类的'<'符号,先比较牌面,再比较花色,当调用sort函数时,其会自动采用该内置函数比较
        if self.prior1 == other.prior1:
            return self.prior2 <= other.prior2
        else:
            return self.prior1 < other.prior1

    def __lt__(self, other):    # 此处重写Player类的'<'符号,先比较牌型,再比较每张牌,当调用sort函数时,其会自动采用该内置函数比较
        n = len(self.card)
        if PRIORITY[self.type] == PRIORITY[other.type]:     # 若牌型相同,则比较牌大小。注意:对子牌型需要先比对,再比单。
            for i in range(n):
                index = (self.pair + i) % n                     # 0,1,2或者是1,2,0比较
                if self.card[index] != other.card[index]:
                    return self.card[index] < other.card[index]
            # 循环外这种情况是,玩家所有牌全部一样,也返回True。
            # 当然,看花色的情况下,第一张牌就可以比较出玩家输赢
            return True
        else:
            return PRIORITY[self.type] < PRIORITY[other.type]

类Player补充的函数:

info函数:用于输出玩家的姓名,牌信息,是否是赢家

    def info(self):
        print(self.name, end='\t')          # 输出玩家姓名
        for c in self.card:                 # 输出牌面
            print(c.name, end='\t')
        if not self.winner:                 # 若不是赢家,则只用输出牌型
            print(self.type)
        else:                               # 若是赢家,则还要加上庆祝语
            print(self.type, '\tWinner! 🎉🎉🎉')

完整代码:

当然具体流程的主函数此处没有展示,完整代码文件可见我的Github:GitHub - yhmain/CSDN

或者在CSDN上面下载:Python3-card.py

(大家觉得可以的话,可以给个👍嘛~~~)

效果展示:

  • 19
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值