用python实现的21点游戏

几个月前,因为希望接触python这门目前比较火的编程语言,我采用《笨办法学python3》这本书来开始学习的过程。
在练习45中其给出了一个开放式的练习题:你来制作一款游戏。于是编了一个21点的脚本游戏,因为对于python其实还是相当生疏,所以其功能比较简单,中间的代码也有待优化。
当时,我将这篇日志放置在csdn的博客中,现在挪到简书中,作为在简述中的记录。

游戏规则

该游戏的规则与实际的玩法应该有点差异,因为我没有去细查21点的确切玩法,只是根据印象中进行了一系列的定义,具体如下:
1.玩家为人类玩家与电脑玩家,共2个玩家。电脑为庄家。
2.先给人类玩家与电脑玩家分别发两张牌作为底牌。
3.判断双方底牌是否为blackjack,如果一方为blackjack则直接判胜利,并在总分中记上一分。如果双方均为blackjack,则判双方平局,均不得分
4.如果没有出现blackjack的情况,人类玩家根据牌面决定是否要牌,若要牌则得到牌堆的一张牌,并再次判断。如果人类牌面的点数超过21点,则直接判负。
5.如果人类玩家停止要牌,且未因为超过21点而判负,则电脑要牌(电脑的要牌基于一个算法,后期如果更新,这个算法要基于对胜率的估算),电脑停止要牌后,判断与人类的输赢情况。赢者加一分。
6.人类玩家决定是否继续下一轮,如果继续,则从剩余牌堆中继续发牌开始上述过程。如果不继续,则计算总分,判断谁胜出。
7.如果牌堆的牌已经不够玩一轮的话,自动判断游戏结束。人类可以选择是否重新再玩。

程序功能

要实现上面游戏的规则,程序的功能进行划分如下,不同的功能用不同的函数来实现,以达到代码的复用。
1.牌堆:在发牌的过程中,牌堆中会去除已经发出的牌
2.发牌:要牌的时候,需要从牌堆随机抽取一张牌
3.计分:能对手中的牌的分数进行计算,其中需要考虑靠A的特殊性
4.胜负判断:当结束要牌的时候,能通过分数判断胜负
5.要牌与否:一个让你判断是否继续要牌的功能
6.游戏结束判断:让你决定是否提前结束游戏,如果不提前结束,则在牌堆中牌的数量比较少的时候,自动结束游戏
7.一局游戏的过程

代码

import random
import numpy as np
from sys import exit

poker_name = ['♦10', '♦2', '♦3', '♦4', '♦5', '♦6', '♦7', '♦8', '♦9', '♦A', '♦J', '♦K', '♦Q',
 '♣10', '♣2', '♣3', '♣4', '♣5', '♣6', '♣7', '♣8', '♣9', '♣A', '♣J', '♣K', '♣Q',
 '♥10', '♥2', '♥3', '♥4', '♥5', '♥6', '♥7', '♥8', '♥9', '♥A', '♥J', '♥K', '♥Q',
 '♠10', '♠2', '♠3', '♠4', '♠5', '♠6', '♠7', '♠8', '♠9', '♠A', '♠J', '♠K', '♠Q']
#牌堆用一个列表来表示

poker_value = {'♣A':1,'♥A':1,'♠A':1,'♦A':1,'♦10': 10, '♦2': 2, '♦3': 3, '♦4': 4, '♦5': 5, '♦6': 6, '♦7': 7, '♦8': 8, '♦9': 9,  '♦J': 10, '♦K': 10, '♦Q': 10,
 '♣10': 10, '♣2': 2, '♣3': 3, '♣4': 4, '♣5': 5, '♣6': 6, '♣7': 7, '♣8': 8, '♣9': 9,  '♣J': 10, '♣K': 10, '♣Q': 10,
 '♥10': 10, '♥2': 2, '♥3': 3, '♥4': 4, '♥5': 5, '♥6': 6, '♥7': 7, '♥8': 8, '♥9': 9,  '♥J': 10, '♥K': 10, '♥Q': 10,
 '♠10': 10, '♠2': 2, '♠3': 3, '♠4': 4, '♠5': 5, '♠6': 6, '♠7': 7, '♠8': 8, '♠9': 9,  '♠J': 10, '♠K': 10, '♠Q': 10}
 #根据牌堆里面的名称,设置每张牌对应的分值


def Dealing_Poker(poker_database):
    #发一张牌,并在牌堆中删除这张牌
    return poker_database.pop(random.randint(0,len(poker_database)-1))

def Score_Count(hand_poker):
    #计算牌的点数
    Score = 0
    Have_Ace = False
    for k in hand_poker:
        Score += poker_value[k]
    for i in hand_poker:
        if i in Ace:
            Have_Ace = True
            break
        else: continue
    if Have_Ace == True:
        if Score + 10 <= 21:
            Score = Score + 10
    return Score

def Judgement(your_score,pc_score):
    #结束要牌的时候,计算双方的点数,判断输赢
    if your_score > 21 and pc_score > 21:
        print('PUSH')
        return np.array([0,0])
    elif your_score > 21 and pc_score <= 21:
        print('YOU LOSE')
        return np.array([0,1])
    elif your_score <= 21 and pc_score > 21:
        print('YOU WIN')
        return np.array([1,0])
    elif your_score <= 21 and pc_score <= 21:
        if your_score < pc_score:
            print('YOU LOSE')
            return np.array([0,1])
        elif your_score > pc_score:
            print('YOU WIN')
            return np.array([1,0])
        else:
            print('PUSH')
            return np.array([0,0])


def Hit_or_Stand():
#玩家需要判断是否继续叫牌
    AskPoker = input('Would You Hit?(Y/N)>>:')
    if AskPoker.upper() == 'Y':
        return Dealing_Poker(poker_database)
    elif AskPoker.upper() == 'N':
        print('You stand')
        return False
    else:
        print('Wrong input, please input Y/y or N/n!>>')
        return Hit_or_Stand() 

def Continue_Or_Quit():
#在每一轮结束后,判断是否继续下一轮的游戏。当牌堆里面牌的数目不足的时候,自动停止游戏
    NextRound = input('Would you like start next round?(Y/N)>>')
    if NextRound.upper() == 'Y':
        if len(poker_database) <10:
            print('The left pokers is not enough')
            input('Game Over')
            exit(1)
        else:
            return True
    elif NextRound.upper() == 'N':
        input('Game Over')
        exit(1)
    else:
        print('Wrong Input, Please Try One More Time!')
        Continue_Or_Quit()

def Start_Dealing(poker_database):
#开局的时候,自动给玩家和电脑发两张牌
    return [poker_database.pop(random.randint(0,len(poker_database)-1)),poker_database.pop(random.randint(0,len(poker_database)-1))]

def One_Round(poker_database):
#一个回合的游戏
    you_get = Start_Dealing(poker_database)  
    pc_get = Start_Dealing(poker_database)
    print(f'Your hand poker:{you_get[0]} , {you_get[1]}')
    print(f'PC\'s hand poker:{pc_get[0]} , ?\n')
    your_hand_poker.extend(you_get)
    pc_hand_poker.extend(pc_get)
    score = np.array([Score_Count(your_hand_poker),Score_Count(pc_hand_poker)])
    if score[0] == 21 or score[1] == 21:
        print('BlackJack')
        return Judgement(score[0],score[1])
    else:
        while score[0] <= 21:
            Get_New_Poker = Hit_or_Stand()
            if Get_New_Poker != False:
                your_hand_poker.append(Get_New_Poker)
                print(f'You Hand Poker:{your_hand_poker}')
                score[0] = Score_Count(your_hand_poker)
                if score[0] > 21:
                    print('You Bust')
                    print(f'PC\'s Hand Poker:{pc_hand_poker}')
                    return Judgement(score[0],score[1])
                else:continue
            elif Get_New_Poker == False:
                while score[1] < score[0]:
                    PC_Ask_Poker = Dealing_Poker(poker_database)
                    pc_hand_poker.append(PC_Ask_Poker)
                    pc_score = Score_Count(pc_hand_poker)
                    score[1] = pc_score
                print(f'PC final hand poker:{pc_hand_poker}')
                return Judgement(score[0],score[1])
                break
            else:continue



Ace = {'♣A','♥A','♠A','♦A'} #用于判断手牌中是否有A,根据分数来选择A牌的分值是0还是1
poker_deck = 1 #一共是使用几副牌
poker_database = poker_name * poker_deck #最终生成的牌堆
total_score = np.array([0,0])    #总分的计分器                

Round = 1                                        
while len(poker_database) > 10:
    your_hand_poker = []
    pc_hand_poker = []
    input('Start Dealing, good luck...<>\n')
    print(f'Round {Round}:')
    print('.' * 60)
    score = One_Round(poker_database)
    total_score += score
    print(f'Total score is:{total_score[0]}:{total_score[1]}')
    Round += 1
    Continue_Or_Quit()

21点与凯利公式(期望和概率)

的是一位天才的数学教授在大学生中网罗了一批数学天才,关起门来训练他们玩21点。然后指挥他们转战各个赌场,通过相互间的配合,赢了很多钱,最终又成为各大赌场的黑名单中人与追杀对象,后来这本书被拍成电影《决胜21点》,推荐您看一下。 21点的游戏规则是,大家围桌

1张扑克的游戏

妈提起了“免蹲起券”,立马让我想到了《扑克游戏》。 《扑克游戏》是某次买书拼单时塞到购物车的。带给我的小窃喜,犹如抄同学的作业没被发现一样。 而在乌伯特.盛旦老师的班里,你根本不用担心抄作业被发现后,老师会如何雷霆大怒。 因为,你可以正大光明地拥有一张“可