python每日一练[2]
不知道干什么好、又是无所事事的一天
炸金花
自己写一个程序,实现发牌、比大小、判断输赢。
<br>
游戏规则:
一付扑克牌,去掉大小王,给每个玩家发3张牌,最后比大小,看谁赢。 牌的大小顺序为:豹子>同花顺>同花>顺子>对子>单张 <br> 豹子: 三张一样的牌,如3张6。 同花顺: 即3张同样花色的顺子,如红桃 5、6、7。 顺子: 又称拖拉机,花色不同,但是顺子,如红桃5、方片6、黑桃7,组成的顺子。 对子: 两张牌一样。 单张: 最大的是A。
需程序实现的点:
1.需生成一付扑克牌 2.给5个玩家随机发牌 3.比大小,输出赢家是谁 <br><br>
代码实现:
'''
判断赢家可以通过设置分值来比较来牌面的大小
先看每人三张的花色、没有相同的就不会有同花顺
再看每人的大小,三个数均值等于中间数字就有豹子和顺子,A K Q J分别视为14 13 12 11
再看有没有对子
最后看单张大小
'''
import random
# 生成除去大小王的52张牌
suits = ['红桃', '方片', '黑桃', '梅花']
ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
value_map = {'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}
deck = [(suit, rank) for suit in suits for rank in ranks]#列表推导式遍历 suits 和 ranks 中的所有组合,生成一个包含所有可能扑克牌的元组列表
# 用于比较牌面大小的函数
def get_card_values(cards):
return [value_map[card[1]] for card in cards]
# 判断是否为豹子
def is_straight_flush(cards):
values = get_card_values(cards)
return len(set(values)) == 1
# 判断是否为同花顺
def is_flush(cards):
suits = [card[0] for card in cards]
values = get_card_values(cards)
return len(set(suits)) == 1 and len(set(values)) == len(values) and max(values) - min(values) == len(values) - 1
# 判断是否为顺子
def is_straight(cards):
values = get_card_values(cards)
return len(set(values)) == len(values) and max(values) - min(values) == len(values) - 1
# 判断是否为对子
def is_pair(cards):
values = get_card_values(cards)
return len(values) != len(set(values))
# 发牌并判断赢家
print('炸金花,开始发牌:')
# 设置变量存储本轮所发的牌
playerDeck = []
for i in range(5):
shoupai = sorted(random.sample(deck, 3), key=lambda x: (value_map[x[1]], x[0])) # 按牌面值排序手牌,方便后续比较
print(f'玩家{i+1}的手牌:{shoupai}')
playerDeck.append(shoupai)
# print(playerDeck)
# 初始化赢家变量
winner = None
max_score = (-1, []) # (牌型分数, 玩家手牌),分数越高越好,初始化为一个不可能的值
# 定义牌型分数,越高代表牌型越强
SCORE_STRAIGHT_FLUSH = 5 # 豹子
SCORE_FLUSH = 4 # 同花顺
SCORE_STRAIGHT = 3 # 顺子
SCORE_PAIR = 2 # 对子
SCORE_SINGLE = 1 # 单张
for index, hand in enumerate(playerDeck):
if is_straight_flush(hand):
score = (SCORE_STRAIGHT_FLUSH, get_card_values(hand))
elif is_flush(hand):
score = (SCORE_FLUSH, get_card_values(hand))
elif is_straight(hand):
score = (SCORE_STRAIGHT, get_card_values(hand))
elif is_pair(hand):
score = (SCORE_PAIR, get_card_values(hand))
else:
score = (SCORE_SINGLE, get_card_values(hand))
# 比较分数确定赢家,如果分数相同则比较最大的一张牌
if score > max_score or (score == max_score and score[1][-1] > max_score[1][-1]):
max_score = score
winner = index + 1
print(f"赢家是玩家{winner}")
<br><br>
运行结果
运行后,控制台输出:
炸金花,开始发牌:
玩家1的手牌:[('方片', '2'), ('黑桃', '7'), ('方片', 'K')]
玩家2的手牌:[('红桃', '2'), ('方片', '4'), ('梅花', '6')]
玩家3的手牌:[('黑桃', '2'), ('梅花', '7'), ('黑桃', 'J')]
玩家4的手牌:[('红桃', '3'), ('方片', '6'), ('梅花', 'Q')]
玩家5的手牌:[('方片', '4'), ('红桃', '4'), ('黑桃', 'K')]
赢家是玩家5
<br><br>
总结
炸金花的牌型多,用程序来直接比较大比较困难。但如果使用过多的条件判断语句,这会是个灾难,所以需要尽量去避免这个问题。