前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >自娱自乐之用python写一个21点游戏

自娱自乐之用python写一个21点游戏

作者头像
IT运维技术圈
发布2025-01-02 18:14:11
发布2025-01-02 18:14:11
670
举报
文章被收录于专栏:IT运维技术圈

大家好,波哥又来给大家推荐好东西啦!

如果大家有需要帮忙推荐的工具、框架、应用、脚本可以在文章下方留言,留言中被点赞、推荐回复较多的,波哥就会帮各位提前安排哦!

游戏介绍

21点(Blackjack)是赌场中极为流行的纸牌游戏,玩家的目标是尽量使手牌的点数总和接近21点,但不能超过。Ace(A牌)可以根据需求计为1或11,K、Q、J均为10点,其余牌面按点数计算。游戏分为玩家和庄家两个角色,玩家可以选择“要牌”或“停牌”,而庄家则必须在点数不足17时继续“要牌”。

核心代码逻辑分析

面向对象设计: 本代码通过类的设计,将游戏中的各个实体(如牌、手牌、筹码等)进行了模块化封装,增强了代码的可读性和复用性。

Card类:表示扑克牌,定义了牌的花色和点数,并通过__str__方法实现直观的显示效果。

Deck类:表示一副完整的扑克牌,实现了生成牌堆、洗牌以及发牌的功能。

Hand类:表示玩家或庄家的手牌,支持添加新牌和调整Ace的点数。

Chips类:记录玩家的筹码信息,支持筹码增减的操作。

逻辑控制和交互:

玩家通过命令行与程序互动,如输入下注金额、选择是否继续要牌等。

使用全局变量playing控制游戏的进行状态,使代码逻辑清晰。

函数封装与复用:

功能性函数如take_bet(处理玩家下注)、hit_or_stand(控制玩家操作)等,封装了具体的逻辑,避免代码冗余。

显示牌面的函数show_some和show_all,分别在游戏不同阶段展示必要信息。

游戏主循环:

主函数blackjack_game负责完整的游戏流程,包括初始化、玩家操作、庄家操作、结算结果以及筹码更新。

外层循环允许玩家在余额未耗尽时选择继续游戏或退出。

代码书写技巧解析

简洁性与可读性:

通过类和函数封装,将复杂逻辑分解为小模块,提升了代码可维护性。

使用清晰的变量命名和注释,使代码含义一目了然。

用户输入校验:

在take_bet函数中,检查用户输入是否合法,确保下注金额不超过余额且为有效整数。

处理玩家选择时,要求输入有效选项,防止程序因错误输入而中断。

随机性处理:

通过random.shuffle实现洗牌功能,模拟真实扑克牌的随机性。

异常处理:

利用try-except块捕获无效输入,防止程序崩溃,并提示用户重新输入。

灵活性与扩展性:

Ace的点数调整逻辑,使游戏能够正确处理特殊情况。

筹码的动态管理,为游戏增加了策略性。

代码

代码语言:javascript
复制
import random

# 定义扑克牌的花色、点数和点数对应的值
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
values = {'Two': 2, 'Three': 3, 'Four': 4, 'Five': 5, 'Six': 6, 'Seven': 7, 'Eight': 8,
          'Nine': 9, 'Ten': 10, 'Jack': 10, 'Queen': 10, 'King': 10, 'Ace': 11}

playing = True  # 控制游戏状态

class Card:
    """
    定义牌类,表示扑克牌的基本结构
    包括花色(suit)和点数(rank)
    """
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return f"{self.rank} of {self.suit}"


class Deck:
    """
    定义牌堆类,生成一副完整的扑克牌并支持洗牌和发牌
    """
    def __init__(self):
        self.deck = [Card(suit, rank) for suit in suits for rank in ranks]

    def shuffle(self):
        """洗牌"""
        random.shuffle(self.deck)

    def deal(self):
        """发一张牌"""
        return self.deck.pop()


class Hand:
    """
    定义手牌类,包含玩家或庄家的牌以及相关的点数逻辑
    """
    def __init__(self):
        self.cards = []  # 当前手中的牌
        self.value = 0   # 当前点数总和
        self.aces = 0    # Ace 的数量,用于特殊点数调整

    def add_card(self, card):
        self.cards.append(card)
        self.value += values[card.rank]
        if card.rank == 'Ace':
            self.aces += 1

    def adjust_for_ace(self):
        """
        如果点数超过21且有Ace,将Ace的点数从11调整为1
        """
        while self.value > 21 and self.aces:
            self.value -= 10
            self.aces -= 1


class Chips:
    """
    定义筹码类,记录玩家当前余额和下注金额
    """
    def __init__(self, total=100):
        self.total = total  # 玩家初始筹码数量
        self.bet = 0        # 当前下注金额

    def win_bet(self):
        self.total += self.bet

    def lose_bet(self):
        self.total -= self.bet


# 功能函数
def take_bet(chips):
    """
    提示玩家下注,并校验输入的合法性
    """
    while True:
        try:
            chips.bet = int(input(f"您的余额是 {chips.total}。请输入您的下注金额: "))
            if 0 < chips.bet <= chips.total:
                break
            print(f"无效金额!下注金额应在 1 到 {chips.total} 之间。")
        except ValueError:
            print("无效输入!请输入一个整数。")


def hit(deck, hand):
    """玩家要牌"""
    hand.add_card(deck.deal())
    hand.adjust_for_ace()


def hit_or_stand(deck, hand):
    """
    提示玩家选择要牌或停牌
    """
    global playing

    while True:
        choice = input("是否要牌?输入 '1' 要牌,输入 '0' 停牌: ").strip()
        if choice == '1':
            hit(deck, hand)
            break
        elif choice == '0':
            print("您选择停牌。庄家操作中...")
            playing = False
            break
        else:
            print("无效输入,请重新输入。")


def show_some(player, dealer):
    """
    显示玩家和庄家的部分手牌
    """
    print("\n庄家的手牌:")
    print(" [隐藏的牌]", dealer.cards[1])
    print("\n您的手牌:", *player.cards, sep='\n ')


def show_all(player, dealer):
    """
    显示玩家和庄家的全部手牌
    """
    print("\n庄家的手牌:", *dealer.cards, sep='\n ')
    print("庄家的点数 =", dealer.value)
    print("\n您的手牌:", *player.cards, sep='\n ')
    print("您的点数 =", player.value)


def check_winner(player, dealer, chips):
    """
    判断游戏结果并处理筹码
    """
    if player.value > 21:
        print("您爆牌了!")
        chips.lose_bet()
    elif dealer.value > 21:
        print("庄家爆牌!")
        chips.win_bet()
    elif player.value > dealer.value:
        print("您赢了!")
        chips.win_bet()
    elif player.value < dealer.value:
        print("庄家获胜!")
        chips.lose_bet()
    else:
        print("平局!")


# 游戏主循环
def blackjack_game():
    """主游戏逻辑"""
    global playing

    print("\n欢迎来到 21 点游戏!\n")
    print("规则: 尽量接近 21 点,但不能超过。Ace 可以算作 1 或 11。\n")

    deck = Deck()
    deck.shuffle()

    player_hand = Hand()
    dealer_hand = Hand()

    player_hand.add_card(deck.deal())
    player_hand.add_card(deck.deal())
    dealer_hand.add_card(deck.deal())
    dealer_hand.add_card(deck.deal())

    player_chips = Chips()

    take_bet(player_chips)
    show_some(player_hand, dealer_hand)

    while playing:
        hit_or_stand(deck, player_hand)
        show_some(player_hand, dealer_hand)
        if player_hand.value > 21:
            break

    if player_hand.value <= 21:
        while dealer_hand.value < 17:
            hit(deck, dealer_hand)

        show_all(player_hand, dealer_hand)
        check_winner(player_hand, dealer_hand, player_chips)

    print("\n您的当前余额为:", player_chips.total)
    return player_chips.total


while True:
    final_balance = blackjack_game()
    if final_balance > 0:
        new_game = input("是否再来一局?输入 '1' 开始新游戏,输入 '0' 退出: ").strip()
        if new_game == '1':
            playing = True
            continue
    print("感谢参与游戏!祝您好运!")
    break

示例:

  1. 玩家开始游戏,初始余额为 100。
  2. 玩家下注 20。
  3. 玩家停牌,庄家操作后爆牌。
  4. 玩家获胜,余额增加到 120。
  5. 玩家选择退出游戏。

整个交互根据玩家输入和游戏逻辑动态变化,最终打印结果并退出游戏。

代码语言:javascript
复制
欢迎来到 21 点游戏!

规则: 尽量接近 21 点,但不能超过。Ace 可以算作 1 或 11。

您的余额是 100。请输入您的下注金额: 
> 20

庄家的手牌:
 [隐藏的牌]
 Seven of Hearts

您的手牌:
 Ace of Spades
 Nine of Diamonds

是否要牌?输入 '1' 要牌,输入 '0' 停牌: 
> 0
您选择停牌。庄家操作中...

庄家的手牌:
 Seven of Hearts
 Five of Clubs

庄家的点数 = 12

庄家的手牌:
 Seven of Hearts
 Five of Clubs
 Queen of Diamonds

庄家的点数 = 22

您的手牌:
 Ace of Spades
 Nine of Diamonds

您的点数 = 20

庄家爆牌!
您赢了!

您的当前余额为: 120
是否再来一局?输入 '1' 开始新游戏,输入 '0' 退出: 
> 0
感谢参与游戏!祝您好运!

总结

这份21点游戏代码通过面向对象的设计和功能性函数封装,实现了一个完整、交互性强的游戏系统。无论是从代码简洁性、逻辑清晰度还是用户体验角度,这份代码都具有良好的示范意义。通过进一步优化交互细节和逻辑结构,可以使代码更具扩展性和实用性。

觉得不错别忘了给波哥一键三连哦!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-01-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT运维技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 核心代码逻辑分析
  • 示例:
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档