Python 实现简单的单机版 21 点游戏

Python 实现简单的单机版 21 点游戏

1. 21 点游戏规则简介

21 点游戏规则:
点数计算:每张牌都有点数。2 到 10 的牌的点数就是其牌面的数字,J、Q、K的点数是 10.
A有两种算法: 1 或者 11, 如果 A 算为 11 时总和大于 21,则 A 算为 1. 例如 (A, 8)是 19 点, (A,7,J)则为 18 点
爆牌:玩家手中牌的总点数超过 21 点
停牌:玩家不再要牌, 等待其他玩家操作
要牌:玩家根据自己手上的点数决定是否要牌, 如果要牌, 则系统再发一张牌给玩家. 如果要牌后总点数超过 21, 则算爆牌,玩家输掉本轮游戏;若要牌后点数为 21点, 则不能再要。如果要牌后总点数不到 21 点, 则玩家可以继续 “要牌” “停牌”“
庄家持牌总点数少于 17,则必须要牌,直到超过 16,如果庄家的总点数等于或多于 17 点,则必须停牌
如果庄家手中有 A,且 A 作 11 点时大于 16点,作 1 点时小于或等于 16 点, 则由庄家自己选择是否要牌
注意:游戏开始后,玩家和庄家各发两张牌,庄家的第二张牌对外不可见。

2. 实现代码

基于以上的规则,使用 Python 实现一个简单的 21 点游戏,该游戏只有玩家和电脑两个玩家,玩家通过命令行的方式输入命令,决定是否要牌或停牌,电脑玩家要牌或停牌由程序自动控制。代码如下:

import random  # 导入随机包

# 模拟要牌, 从卡牌列表中随机选择一张卡牌
import time

def my_random_choose():
    card = random.choice(cards)   # 从卡牌列表中随机选取一张牌
    flag = card[0]     # flag 存放卡牌的标记
    value = card[-1]   # value 存放卡牌的字符串类型的值
    if value == 'A':   # 如果卡牌为 A
        return flag, value, 1   # 暂时给它的值赋为 1
    elif value == '0':
        return flag, '10', 10     # 卡牌为 10
    elif value == 'J' or value == 'Q' or value == 'K':
        return flag, value, 10    # 卡牌为 J, Q, K 的当作 10
    else:
        return flag, value, int(value)  # 其他卡牌, 按照卡牌上的数字计算即可

# 询问玩家是否继续要牌, 获取玩家选择
def get_Input():
    Input = input('是否继续要牌(Y|N):')
    while Input != 'Y' and Input != 'N':  # 强制要求只能输入 Y 或者 N, 其他输入一律重新输入
        Input = input('是否继续要牌(Y|N):')
    return Input
    
# 玩家要牌
def player_hit():
    # 开始游戏,随机发给玩家两张卡牌
    flag1, value1, num1 = my_random_choose()
    flag2, value2, num2 = my_random_choose()
    player_cards = []                # 玩家卡牌列表,存放玩家要的所有牌, 存放的是 flag 和 value
    # 如果第一张卡牌为 A, 则赋值为 11
    if num1 == 1:
        num1 = 11  # 卡牌数值为 11
    elif num1 != 1 and num2 == 1: # 如果第一张卡牌不为 A, 但是第二张卡牌为 A
        num2 = 11  # 卡牌数值为 11

    player_total = num1 + num2  # 计算当前玩家手中卡牌总点数

    # 将初始发的两张卡牌放到玩家卡牌列表中, 存放的是字符串, 所以不参与计算, 只是用于输出卡牌拥有情况
    player_cards.append([flag1, value1])
    player_cards.append([flag2, value2])

    print('玩家手中的牌是:', [flag1, value1], [flag2, value2])

    if player_total == 21:   # 玩家当前点数为 21 点
        # 玩家赢了
        return player_total   # 返回玩家点数
    else:  # 玩家当前点数不为 21 点
        Input = get_Input()  # 询问玩家是否要继续要牌
        while Input == 'Y' or Input == 'N':
            if Input == 'Y':  # 玩家继续要牌
                flag, value, num = my_random_choose()  # 随机抽一张卡牌给玩家
                if num == 1 and (player_total + 11 <= 21):  # 如果抽到了 A, 将 A 看成 11, 看一下此时手中卡牌总点数是否大于 21
                    num = 11     # 如果不大于 21, 可以将当前 A 赋值为 11
                player_cards.append([flag, value])   # 将抽到的卡牌放到玩家卡牌列表中
                print('玩家手中的牌是:', player_cards)    # 输出当前拥有的卡牌
                player_total += num            # 计算玩家当前拥有的卡牌的总点数
                if player_total > 21:                  # 如果玩家当前拥有的卡牌总点数大于 21
                    return player_total                # 玩家爆牌, 返回 玩家卡牌总点数, 结束函数执行
            elif Input == 'N':     # 玩家不要牌
                return player_total  # 返回玩家当前卡牌总点数, 结束函数执行, 让庄家要牌

            Input = get_Input()   # 玩家之前要了牌, 但是牌的总点数小于 21, 询问玩家是否继续要牌
            
# 庄家要牌
def dealer_hit(num1, dealer_cards):
    
    DEALER_MIN_SCORE = 17  # 庄家手中的牌的总点数的最小值为 17, 如果小于 17, 庄家必须要牌
    
    flag2, value2, num2 = my_random_choose()  # 为庄家随机选择一张卡牌
    if num1 != 11 and num2 == 1:  # 庄家的第一张牌不是 A, 但是第二张卡牌是 A
        num2 = 11    # 给第二张卡牌赋值为 11
    dealer_cards.append([flag2, value2])   # 将庄家的第二张卡牌放到庄家卡牌列表中, 用于之后输出拥有卡牌情况
    dealer_total = num1 + num2

    # 当庄家手中牌的总点数小于 17, 必须要牌,
    while dealer_total < DEALER_MIN_SCORE:
        flag, value, num = my_random_choose()
        if num == 1 and (dealer_total + 11 <= 21):
            num = 11
        dealer_cards.append([flag, value])
        print('庄家得到一张牌, 庄家手中的牌是: ', dealer_cards)
        dealer_total += num
    # 庄家手中的牌的总点数大于等于17, 必须停牌, 即返回总点数
    return dealer_total

# 决定赢家
def vs(player_total, dealer_total):

    if player_total > 21:   # 如果玩家爆牌
        # 玩家输
        print('庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 庄家赢了!')
        return 1, 0  # 分别返回庄家和玩家的比分
    else:
        if dealer_total > 21:  # 庄家爆牌

            print(' 庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 玩家赢了!')
            return 0, 1
        else:
            if player_total == dealer_total:  # 平局

                print(' 庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 平局!')
                return 1, 1
            elif player_total > dealer_total:  # 都没有爆牌,但是玩家的卡牌总点数大于庄家卡牌总点数
                # 玩家赢
                print(' 庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 玩家赢了!')
                return 0, 1
            else:
                # 庄家赢
                print(' 庄家点数为 ', dealer_total, ', 玩家点数为 ', player_total, ', 庄家赢了!')
                return 1, 0

def start_21_game():
    player_score = 0      # 玩家得分
    dealer_score = 0      # 庄家得分
    Input = 'Y'
    round_count = 0       # 比赛的轮数
    while Input == 'Y':
        round_count += 1
        print(f'第{round_count}轮比赛开始:')
        flag1, value1, num1 = my_random_choose()   # 从卡牌列表中随机选择一个卡牌
        if num1 == 1:    # 卡牌为 A
            num1 = 11    # 因为只有一个卡牌,所以不会爆牌,赋值为 11
        dealer_cards = []      # 庄家拥有的卡牌列表
        dealer_cards.append([flag1, value1])    # 将抽到的卡牌放到庄家卡牌列表中
        print('庄家手中的牌是: ', [flag1, value1], '?')
        player_total = player_hit()   # 调用玩家要牌函数, 返回值是玩家此时的卡牌总点数
        dealer_total = dealer_hit(num1, dealer_cards)   # 调用庄家要牌函数, 返回值是庄家此时的卡牌总点数
        dealer_point, player_point = vs(player_total, dealer_total)   # 根据玩家和庄家的卡牌总点数判断赢家是谁, 返回值分别是庄家和赢家当局的比分
        print('------------------------------')
        player_score += player_point  # 将玩家当局的得分加到玩家总得分上
        dealer_score += dealer_point  # 将庄家当局的得分加到庄家总得分上

        Input = input('是否进行下一局 [Y|N]:')
        while Input != 'Y' and Input != 'N':
            print('请输入 Y or N.', end='')
            Input = input('请重新输入 [Y|N]:')
    return player_score, dealer_score

if __name__ == '__main__':

    # 定义一个存放卡牌的列表
    cards = ['♠A', '♠2', '♠3', '♠4', '♠5', '♠6', '♠7', '♠8', '♠9', '♠10', '♠J', '♠Q', '♠K',
             '♣A', '♣2', '♣3', '♣4', '♣5', '♣6', '♣7', '♣8', '♣9', '♣10', '♣J', '♣Q', '♣K',
             '♦A', '♦2', '♦3', '♦4', '♦5', '♦6', '♦7', '♦8', '♦9', '♦10', '♦J', '♦Q', '♦K']

    # play_score 记录玩家的得分, dealer_score 记录庄家的得分
    player_score, dealer_score = start_21_game()

    print(f'玩家, 庄家总比分为:{player_score}:{dealer_score}')
    if player_score > dealer_score:
        print('玩家胜出')
    elif player_score < dealer_score:
        print('庄家胜出')
    else:
        print('平局')
    print('游戏结束')
    print('10秒后自动关闭窗口')
    time.sleep(10)

3. 运行效果

上面的代码可以直接运行,为了更加直观地展示运行效果。我将使用 pyinstaller 将文件打包成可执行文件,然后在命令行窗口进行展示。在 Pycharm 集成开发工具的终端 terminal 输入 pyinstaller 打包的命令, 命令如下:

pyinstaller -F 21点游戏.py

如果未安装 pyinstaller, 则使用如下 pip 命令进行安装:

pip install pyinstaller -i https://mirrors.aliyun.com/pypi/simple

打包完成之后,运行生成的可执行文件,运行效果截图如下所示:
在这里插入图片描述

4. 总结

以上就是使用 Python 实现简单的单机版 21 点游戏,上述代码编写并没有体现使用面向对象的编程思想,大家可以在此基础上,用对象进行封装,从而对代码有更深的体会!
如果觉得有用的话,记得点赞、收藏加关注哦!

  • 10
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReadThroughLife

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值