Skip to main content
 首页 » 编程设计

python之二十一点返还错误的荷官百分比

2025年05月04日12jpfss

所以,我一直在研究 John Zelle 的 Python Programming 中的一个问题。问题是设计一个基本的 Blackjack 程序,该程序演示 21 点发牌人爆牌的概率是多少,规则是他必须打到 17 点以上。该程序旨在显示每张初始牌的可能性百分比,因为庄家经常亮出他的第一张牌。

我遇到的问题是,当我将 A 和 10 之外的每个值与 21 点表交叉引用时,该程序似乎为我提供了很好的百分比。

from random import randrange 
 
def main(): 
    printIntro() 
    n = getInput() 
    busts = simBlackjack(n) 
    printSummary(n, busts) 
 
def printIntro(): 
    print "Hello, and welcome to Blackjack.py." 
    print "This program simulates the likelihood" 
    print "for a dealer to bust." 
 
def getInput(): 
    n = input("How many games do you wish to simulate: ") 
    return n 
 
def simBlackjack(n): 
    busts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
    for b in range(10): 
        for i in range(n): 
            x = b + 1 
            if b == 0: 
                handAce = True 
            else: handAce = False 
            while x < 17: 
                add = randrange(1,14) 
                if add == 11: 
                    add = 10 
                elif add == 12: 
                    add = 10 
                elif add == 13: 
                    add = 10 
                elif add == 1: 
                    handAce = True 
                x = x + add 
                if handAce: 
                    if x + 10 >= 17 and x + 10 <= 21: 
                        x = x + 10 
 
            if x > 21: 
                busts[b] = busts[b] + 1 
 
    return busts 
 
def printSummary(n, busts): 
    for b in range(10): 
        if b == 0: 
            print "When the initial card was Ace, the dealer busted %d times in %d games. (%0.1f%%)" % (busts[0], n, (busts[0]) / float(n) * 100) 
        else: 
            print "When the initial value was %d, the dealer busted %d times in %d games. (%0.1f%%)" % ((b + 1), busts[b], n, (busts[b]) / float(n) * 100) 
 
if __name__ == "__main__": main() 

如果 n = 1,000,000,我分别得到 ~ 11.5% 和 21.2%,这与在线表格保持的 17% 和 23% 有很大不同。谁能告诉我问题出在哪里?

请您参考如下方法:

我看到的大问题是评分逻辑将循环结束时的 A 计算为硬值“x”,并且它仍然存在。一旦你有一张 A,“if handAce”行每次都会运行。

它看起来也建立在您可以有一个且只有一个案例的想法之上。但是理论上你可以——但不太可能——如果鞋子有 4 副牌,就会得到 24 个 A。我多次拿到多张 A,每一张都给了你不同的得分方式。

我认为不处理一定数量的牌组中的一组牌(即,消耗牌)很好。

无论如何,我可能会用更多的 oop 风格重做这个来解决 ace 问题:

class BlackjackHand(object): 
    cards= None 
 
    def __init__(self): 
        self.cards = [] 
 
    def autoplay(self,initial_card=None): 
        if initial_card: 
            self.cards.append(initial_card) 
        return self.calculate() 
 
    def calculate(self): 
        total = 0 
        for card in self.cards: 
            ## compute! 
        return total 

我也可能会自己处理面孔,只是为了让事情看起来干净:

faces = [ str(i) for i in (1,2,3,4,5,6,7,8,9,10,'j','q','k','a') ] 
def facevalue(face): 
    if face.isdigit(): 
        return ( int(face) , 0 ) 
    if face in ('j','q','k'): 
        return ( 10 , 0 ) 
    if face == 'a': 
        return ( 1 , 1 ) 

这样你就可以...

def simBlackjack(n): 
    for face in faces: 
        for i in range(n): 
            hand = BlackjackHand() 
            score = hand.autoplay(initial_card=face) 

并用类似...的方式计算

( hand , aces ) = facevalue( face ) 
while True: 
    new_card  = random.choice( faces ) 
    ( new_card_value , new_card_is_ace ) = facevalue( new_card ) 
    hand += new_card_value 
    aces += new_card_is_ace 
    # calculate the multiple different scoring possibilities  
    # if all of them bust, then break 

那里可能还有其他问题,但对我来说最明显的问题是您的代码不能很好地支持 Aces。