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 点游戏,上述代码编写并没有体现使用面向对象的编程思想,大家可以在此基础上,用对象进行封装,从而对代码有更深的体会!
如果觉得有用的话,记得点赞、收藏加关注哦!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/157069.html