在21点(Python)中操纵Ace的值

2024-04-20 09:01:55 发布

您现在位置:Python中文网/ 问答频道 /正文

有人能看看我的代码,让我知道为什么当玩家的手小于21时,Ace值没有变为11?我很难在defcheckvalue(self)下的FOR循环中实现IF循环。这是最好的办法还是有更好的办法?在

谢谢

import random

rank = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace']
suit = ['Diamonds', 'Clubs', 'Hearts', 'Spade']

card_val = {'2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, '10':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':1}

class Card(object):

    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit

    def __str__(self):
        return str(self.rank) + ' of ' + str(self.suit)

    def grab_suit(self):
        return self.suit

    def grab_rank(self):
        return self.rank

    def draw(self):
        print(self.suit + self.rank)

class Deck(object):

    def __init__(self):
        self.cards = []    
        for i in rank:
            for j in suit:
                self.cards.append(Card(i,j))

    def __str__(self):
        return str([str(card) for card in self.cards])

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self):
        single_card = self.cards.pop()
        return single_card

deck = Deck()

class Hand(object):

    def __init__(self):
        self.value = []

    def hit(self):
        self.value.append(deck.deal())
        return self.value

    def __str__(self):
        return str([str(card) for card in self.value])

    def checkvalue(self):
        handvalue = 0
        for card in self.value:  
            handvalue += card_val[card.grab_rank()]
        if card.grab_rank() in self.value == 'Ace' and handvalue <= 11:
            handvalue = handvalue + 10
        return handvalue


playerhand = Hand()

Tags: inselfforreturnvaluedefcardclass
3条回答

if card.grab_rank() in self.value == 'Ace'是胡言乱语。或者更确切地说,它被解释为

if (card.grab_rank() in self.value) == 'Ace'

这里的card是指手中的最后一张牌(因为它在上面的for循环之外),而不是手上的任何一张牌。即使是这样,你也必须删除in self.value检查。在

使代码正常工作的最小更改是:

^{pr2}$

分别地,get_rank和{}是愚蠢的。不要在Python中实现getter,只需使用属性访问(card.rank,和card.value)。在


注意,这里有很多事情需要清理一下。一方面,卡片应该知道自己的价值,而不是必须在全局表中查找。在

class Card(object):
    valuetable = {'Jack': 10, 'Queen': 10, 'King': 10, 'Ace': 1}
    valuetable.update({str(i): i for i in range(2, 10)})
    # maybe write that out for clarity.

    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit
        self.value = self.valuetable[self.rank]  # look up once and save

然后您的checkvalue函数变成

def checkvalue(self):
    handvalue = sum(c.value for c in self.value)
    if any(c.rank == 'Ace' for c in self.value) and handvalue <= 11:
        handvalue += 10
    return handvalue

如果重构到继承模型并将checkvalue转换为属性,这将变得更加简单。在

class Hand(list):
    # in other languages, I might literally define this as a type alias of `[]Card`
    # in Python, inheriting from list is fine.

    @property
    def value(self):
        total = [c.value for c in self]
        if any(c.rank == 'Ace' for c in self) and total <= 11:
            total += 10
        return total

现在您调用hand.value,而不是hand.value(),这样做更有意义。value在现实世界中不是一个动作,它是一个名词而不是一个动词。将其视为属性(或属性,这是@property装饰器所做的)。在

请注意,我在这里没有定义__init__,因为这是从^{继承时处理的,我没有定义__str__,因为它或多或少是由它自己来处理的(如果你print一个列表,它会对它的所有成员调用str),而且我也没有定义{},因为手实际上不应该打击自己。从封装的角度来看,它都没有意义(它现在依赖于一个名为deck的对象,它有一个方法deal),而且“命中”是手的责任也没有意义。也许考虑…在

class Player(object):
    # has a self.hand attribute and a `self.game.deck` attribute
    def hit(self):
        self.hand.append(self.game.deck.deal(1))

玩家击球,手不击球

当你计算一个玩家的手牌的值时,你只比较最后一个遍历self.valuecard,看它是否是Ace。在

def checkvalue(self):
    handvalue = 0
    for card in self.value:  
        handvalue += card_val[card.grab_rank()]

    # Because of how Python scoping works, the card you use here
    # is the last card that `for card in self.value` iterated on
    # You're not actually comparing every card in `self.value` to 'Ace'
    # This conditional is also odd - you probably meant it to be an iteration
    # over self.value to see if any card was an Ace
    if card.grab_rank() in self.value == 'Ace' and handvalue <= 11:
        handvalue = handvalue + 10
    return handvalue

因此,基本上,你需要计算手的值,同时还要确定是否有一张牌是Ace。在

^{pr2}$

你希望if在for循环中,否则你只检查一张卡(手上的最后一张卡)。我们也只关心他们是否至少有一张王牌,因为使用超过一张的11张会破产。在

尝试:

def checkvalue(self):
    handvalue = 0
    has_ace = False
    for card in self.value:
        if card.grab_rank() == 'Ace':
            has_ace = True
        handvalue += card_val[card.grab_rank()]
    if has_ace and handvalue <= 11:
        handvalue += 10
    return handvalue

关于其余代码的小注释:

你的if检查if自我价值等于'Ace'(False),然后如果卡。抢。排名()为False,这将出错。在

Don't use getters in Python

在弹出之前,您可能需要检查deal函数中的deck是否为空,否则它将出错。在

相关问题 更多 >