Python 制作一副扑克牌,有趣的案例!

简介: 之前在 《流畅的 Python 》中看到一个例子比较有趣,所以整理一下通过本文分享给大家, 该案例是通过 Python 类属性创建一幅除去 大王、小王之后的 52 张扑克牌,并实现随机抽牌、排序、洗牌等功能;

之前在 《流畅的 Python 》中看到一个例子比较有趣,所以整理一下通过本文分享给大家, 该案例是通过 Python 类属性创建一幅除去 大王、小王之后的 52 张扑克牌,并实现随机抽牌、排序、洗牌等功能;


创建一个纸牌类

一副扑克除去大王小王之外,剩下的 52 张纸牌以花色为基准(梅花、方块、黑桃、红心)可分为 4 组,每组有 13 张牌组成;因此可创建两个列表一个来存储花色,一个存储 13 个字符;通过两个列表之间的随机组合来生成 52 张纸牌,


代码如下

import collections
Card = collections.namedtuple("Card",['rank','suit'])
class FrenchDeck:
    ranks = [str(n) for n in range(2,11) ] + list("JQKA")
    suits = 'spades diamonds clubs hearts'.split()
    def __init__(self):
        self._cards = [Card(rank,suit) for suit in self.suits 
                       for rank in self.ranks]
    def __len__(self):
        return len(self._cards)
    def __getitem__(self, position):
        return self._cards[position]

代码中通过 collections.namedtuple 模块创建一个类来表示一幅纸牌,[’rank','suit'] 分别表示纸牌中的字符(2-10,J-A)和花色;


FranchDeck 类来建 52 张纸牌,其中有两个特殊方法,len() 返回纸牌数量,__getitem__() 获取 position(索引) 下的指定纸牌

# 用 Card 创建一张纸牌
beer_card = Card('7','diamonds')
print(beer_card) # 打印输出
deck = FrenchDeck()
print('len is -----')
print(len(deck))
# 返回首张 纸牌
print(deck[0])
# 返回最后一张纸牌
print(deck[-1])
# Output
Card(rank='7', suit='diamonds')
len is -----
52
Card(rank='2', suit='spades')
Card(rank='A', suit='hearts')


随机抽取一张牌

这里借助 random 模块实现 随机 抽牌的功能

from random import choice
# 利用 random.choice 随机抽取一张纸牌
print("random choice -----------")
print(choice(deck))
print(choice(deck))
print(choice(deck))
# Output
random choice -----------
Card(rank='8', suit='clubs')
Card(rank='5', suit='hearts')
Card(rank='5', suit='spades')

列表迭代、切片

因为 __getitem__ 方法 把 [] 操作交给 self._cards 列表 ,除了上面提到的 index 定位之外,FranckDeck() 类还可实现切片、迭代操作;

# 切片操作
print('\nslice is --')
print(deck[:3])
print(deck[8:10])
print('\n迭代操作')
for card in deck[:3]:
    print(card)
print('\n 反迭代操作')
for card in reversed(deck[:3]):
    print(card)
# Output
slice is --
[Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), Card(rank='4', suit='spades')]
[Card(rank='10', suit='spades'), Card(rank='J', suit='spades')]
迭代操作
Card(rank='2', suit='spades')
Card(rank='3', suit='spades')
Card(rank='4', suit='spades')
 反迭代操作
Card(rank='4', suit='spades')
Card(rank='3', suit='spades')
Card(rank='2', suit='spades')

排序操作

常规来说,依据点数来判断扑克牌的大小的话,2最小,A最大。实现点数排序是比较简单的,在创建点数列表时是以上面提到顺序进行创建,排序时只需按照 点数所在 index 作为基准 进行排序即可,


除了 点数之外还有一个 花色也需要考虑,对于花色的话,需要建立一个映射基准(也可以称之为权重),不同花色赋予不同值;Python 的字典类型可以很方面地满足我们的需要

# 创建一个字典映射
suit_values = dict(
    spades = 3,
    hearts = 2,
    diamonds = 1,
    clubs = 0
)
def spades_high(card):
    rank_value = FrenchDeck.ranks.index(card.rank) # 索引查询
    return rank_value*len(suit_values) + suit_values[card.suit] # index* 4 + suit.value
print('\nSorted ------------------')
# 利用 key = lambda 机制对列表进行排序
for card in sorted(deck,key = spades_high,reverse= True):
    print(card)
# Output
Sorted ------------------
Card(rank='A', suit='spades')
Card(rank='A', suit='hearts')
Card(rank='A', suit='diamonds')
Card(rank='A', suit='clubs')
Card(rank='K', suit='spades')
Card(rank='K', suit='hearts')
Card(rank='K', suit='diamonds')
Card(rank='K', suit='clubs')
Card(rank='Q', suit='spades')
Card(rank='Q', suit='hearts')
Card(rank='Q', suit='diamonds')

代码解读:


1,代码中利用字典加入了一个映射机制,黑桃为3,红心为2,方块次之,随后梅花;

2,创建 spades_high 函数来计算 每张牌的权重总值;

3,利用 sorted() 函数 key= spades_high 来作为排序基准,来实现扑克牌排序

洗牌操作

洗牌简单来说就是对一副扑克牌重新进行无规则地排序;正常情况random.shuffle 可以很方面地实现这个功能,但前提需要保证对象 满足可变协议,这里 FranchDeck() 是不满足的,直接使用的话会报错:

from random import shuffle
print('-------------------\n'*3)
deck  =FrenchDeck()
shuffle(deck)
# Output
    x[i], x[j] = x[j], x[i]
TypeError: 'FrenchDeck' object does not support item assignment

对于上面问题,只需要要把 此类由 不变 变成 可变的 即可,创建一个函数赋值为 __setitem__ 属性

from random import shuffle
print('-------------------\n'*3)
def set_deck(deck,position,card):
    deck._cards[position] = card
deck1 = FrenchDeck()
print('打乱前\n')
print(deck1[:5])
FrenchDeck.__setitem__ = set_deck
shuffle(deck1)
# Output
打乱前
Card(rank='2', suit='spades')
Card(rank='3', suit='spades')
Card(rank='4', suit='spades')
Card(rank='5', suit='spades')
Card(rank='6', suit='spades')
打乱后:
Card(rank='6', suit='diamonds')
Card(rank='4', suit='hearts')
Card(rank='Q', suit='diamonds')
Card(rank='K', suit='clubs')
Card(rank='8', suit='spades')

这里抽取到打乱前后纸牌的前 5 个元素,已经实现 洗牌 的功能了!

根据以上的代码部分,可以进一步开发, 提前设计好 54 张扑克牌的可视化图片,


创建一个 key:value 映射关系,对扑克牌字符与可视化图片之间创建一个映射关系,如下图所示,把此关系集存储到指定数据库或文件中,后面使用后可直接调用


按照上面的进阶玩法就可以创建一个基于Python开发扑克牌小程序!

相关文章
|
1月前
|
iOS开发 MacOS Python
Python 编程案例:谁没交论文?输出并生成电子表格
Python 编程案例:谁没交论文?输出并生成电子表格
|
1月前
|
数据采集 前端开发 NoSQL
Python编程异步爬虫实战案例
Python编程异步爬虫实战案例
|
1月前
|
数据采集 自然语言处理 API
Python反爬案例——验证码的识别
Python反爬案例——验证码的识别
|
1月前
|
iOS开发 MacOS Python
Python编程小案例—利用flask查询本机IP归属并输出网页图片
Python编程小案例—利用flask查询本机IP归属并输出网页图片
|
1月前
|
存储 大数据 Python
案例学Python:filter()函数的用法,高级!
`filter()`函数是Python中处理序列数据的强大工具,它允许我们高效地根据条件过滤元素。通过结合匿名函数、常规函数或直接利用Python的内置逻辑,`filter()`提供了灵活且高效的过滤机制,尤其在大数据处理和内存敏感的应用中展现出其价值。掌握 `filter()`的使用,不仅能提升代码的可读性和效率,还能更好地适应Python的函数式编程风格。
33 2
|
1月前
|
IDE 开发工具 iOS开发
Python编程案例:查找指定文件大小的文件并输出路径
Python编程案例:查找指定文件大小的文件并输出路径
|
1月前
|
文件存储 iOS开发 MacOS
Python编程案例:文件查找并归类
Python编程案例:文件查找并归类
|
1月前
|
Python
Python编程案例:同一工作簿不同表单特定数据添加到工作簿的另一表单里
Python编程案例:同一工作簿不同表单特定数据添加到工作簿的另一表单里
|
1月前
|
iOS开发 MacOS Python
Python编程案例:根据姓名归档论文、报告
Python编程案例:根据姓名归档论文、报告
|
2月前
|
机器学习/深度学习 数据采集 数据可视化
跟着penguins案例学Seaborn之Pairplot
跟着penguins案例学Seaborn之Pairplot
74 1