一、Python面向对象实战之扑克游戏
我们的扑克只有52张牌(没有大小王),游戏需要将 52 张牌发到 4 个玩家的手上,
每个玩家手上有 13 张牌,按照黑桃、红心、草花、方块的顺序和点数从小到大排列,
以下实现:21点游戏(Black Jack)。
import random
from enum import Enumclass Suite(Enum):"""花色(枚举)"""SPADE, HEART, CLUB, DIAMOND = range(4)class Card:"""牌"""def __init__(self, suite, face):self.suite = suiteself.face = facedef __repr__(self):suites = '♠♥♣♦'faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']return f'{suites[self.suite.value]}{faces[self.face]}' # 返回牌的花色和点数def __lt__(self, other):if self.suite == other.suite:return self.face < other.face # 花色相同比较点数的大小return self.suite.value < other.suite.value # 花色不同比较花色对应的值class Poker:"""扑克"""def __init__(self):self.cards = [Card(suite, face)for suite in Suitefor face in range(1, 14)] # 52张牌构成的列表self.current = 0 # 记录发牌位置的属性def shuffle(self):"""洗牌"""self.current = 0random.shuffle(self.cards) # 通过random模块的shuffle函数实现随机乱序def deal(self):"""发牌"""card = self.cards[self.current]self.current += 1return card@propertydef has_next(self):"""还有没有牌可以发"""return self.current < len(self.cards)class Player:"""玩家"""def __init__(self, name):self.name = nameself.cards = [] # 玩家手上的牌def get_one(self, card):"""摸牌"""self.cards.append(card)def arrange(self):"""整理手上的牌"""self.cards.sort()def calculate_score(self):"""计算手牌点数(A可计为1或11,J/Q/K计为10)"""score = 0aces = 0 # 记录A的数量for card in self.cards:if card.suite == 1: # Ascore += 11aces += 1elif 2 <= card.face <= 10: # 2-10score += card.faceelse: # J/Q/Kscore += 10# 如果总分超过21分,且手上有A,将A视为1分while score > 21 and aces > 0:score -= 10aces -= 1return scoreclass BlackJack:"""21点"""def __init__(self):self.poker = Poker()self.player = Player('玩家')self.dealer = Player('庄家')def start_game(self):"""开始游戏"""print("===== 21点游戏开始 =====")self.poker.shuffle()# 初始发牌,每人两张for _ in range(2):self.player.get_one(self.poker.deal())self.dealer.get_one(self.poker.deal())# 显示初始牌面self.show_hands(show_dealer_first_card=False)# 玩家回合self.player_turn()# 庄家回合(如果玩家未爆牌)if self.player.calculate_score() <= 21:self.dealer_turn()# 结算self.settle()def player_turn(self):"""玩家回合"""while True:choice = input('要牌(Hit)或停牌(Stand)?[H/S]').strip().upper()if choice == 'H':self.player.get_one(self.poker.deal())self.show_hands(show_dealer_first_card=False)if self.player.calculate_score() > 21:print('爆牌!你的点数超过21!')breakelif choice == 'S':breakelse:print('输错了,傻屌!')def dealer_turn(self):"""庄家回合(规则:点数<17必须要牌)"""print("\n庄家回合。。。")self.show_hands(show_dealer_first_card=True)while self.dealer.calculate_score() < 17:self.dealer.get_one(self.poker.deal())print(f'庄家要牌:{self.dealer.cards[-1]}')if self.dealer.calculate_score() > 21:print('庄家爆牌!')breakdef show_hands(self, show_dealer_first_card=False):"""显示当前手牌"""print("\n=== 当前牌面 ===")print(f"玩家手牌:{self.player.cards} 点数:{self.player.calculate_score()}")if show_dealer_first_card:print(f'庄家手牌:{self.dealer.cards} 点数:{self.dealer.calculate_score()}')else:# 隐藏庄家第二张牌print(f'庄家手牌:[{self.dealer.cards[0]},?]')def settle(self):"""结算"""player_score = self.player.calculate_score()dealer_score = self.dealer.calculate_score()print('\n=== 游戏结果 ===')print(f'玩家点数:{player_score}')print(f'庄家点数:{dealer_score}')if player_score > 21:print('你爆牌了,庄家赢!')elif dealer_score > 21:print('庄家爆牌,你赢!')elif player_score > dealer_score:print('你赢!')elif player_score < dealer_score:print('庄家赢!')else:print('平了!')
if __name__ == '__main__':game = BlackJack()game.start_game()
-
===== 21点游戏开始 =====
-
=== 当前牌面 ===
-
玩家手牌:[♠Q, ♠4] 点数:14
-
庄家手牌:[♥6,?]
-
要牌(Hit)或停牌(Stand)?[H/S]h
-
=== 当前牌面 ===
-
玩家手牌:[♠Q, ♠4, ♦J] 点数:24
-
庄家手牌:[♥6,?]
-
爆牌!你的点数超过21!
-
=== 游戏结果 ===
-
玩家点数:24
-
庄家点数:14
-
你爆牌了,庄家赢!
