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>

总结

炸金花的牌型多,用程序来直接比较大比较困难。但如果使用过多的条件判断语句,这会是个灾难,所以需要尽量去避免这个问题。