一、Python面向对象实战之扑克游戏
我们的扑克只有52张牌(没有大小王),游戏需要将 52 张牌发到 4 个玩家的手上,
每个玩家手上有 13 张牌,按照黑桃、红心、草花、方块的顺序和点数从小到大排列,
以下实现:21点游戏(Black Jack)。
python
import random
from enum import Enum
class Suite(Enum):
"""花色(枚举)"""
SPADE, HEART, CLUB, DIAMOND = range(4)
class Card:
"""牌"""
def __init__(self, suite, face):
self.suite = suite
self.face = face
def __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 Suite
for face in range(1, 14)] # 52张牌构成的列表
self.current = 0 # 记录发牌位置的属性
def shuffle(self):
"""洗牌"""
self.current = 0
random.shuffle(self.cards) # 通过random模块的shuffle函数实现随机乱序
def deal(self):
"""发牌"""
card = self.cards[self.current]
self.current += 1
return card
@property
def has_next(self):
"""还有没有牌可以发"""
return self.current < len(self.cards)
class Player:
"""玩家"""
def __init__(self, name):
self.name = name
self.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 = 0
aces = 0 # 记录A的数量
for card in self.cards:
if card.suite == 1: # A
score += 11
aces += 1
elif 2 <= card.face <= 10: # 2-10
score += card.face
else: # J/Q/K
score += 10
# 如果总分超过21分,且手上有A,将A视为1分
while score > 21 and aces > 0:
score -= 10
aces -= 1
return score
class 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!')
break
elif choice == 'S':
break
else:
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('庄家爆牌!')
break
def 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
-
你爆牌了,庄家赢!