<pre><code>Dealer = CardPack
</code></pre>
<p>此行不创建<code>CardPack</code>类型的实例,它只是复制对它的引用。因此,当您调用<code>Dealer.deal()</code>时,实际上是在执行<code>CardPack.deal()</code>,它无权访问实例属性。在</p>
<p>相反,您应该创建一个实例,然后对该实例调用方法:</p>
^{pr2}$
<p>在这种情况下,还需要注意的是,要调用一个方法,<strong>不是</strong>为<code>self</code>传递一个值。当您在实例上调用方法时,<code>self</code>是隐式设置的。因此,当您执行<code>dealer.deal()</code>操作时,<code>self</code>会自动设置为dealer实例。如果您要调用<code>dealer.deal(dealer)</code>,您将传递一个该方法没有的<em>第二个</em>参数,因此您将得到一个错误。这也是您在<code>deal</code>中的<code>getRandomCards</code>调用的问题:<code>self.getRandomCards(self)</code>将<code>self</code>设置为<em>第二个</em>参数,给您一个错误。做<code>self.getRandomCards()</code>就是你想做的。在</p>
<p>尽管如此,请注意您的<code>deal</code>方法将有一个无限循环,因为只要<code>cards</code>不是3就继续迭代,但是您永远不会更改<code>cards</code>的值。所以您可能想增加循环中的值。但即使这样,访问空列表上的<code>cardsDealt[cards]</code>也会导致索引错误,所以您也需要修复它。您可以先重置列表,然后再向其添加<code>append</code>张新卡片,但更好的方法是一次只创建一个新列表,其中包含3张卡片。您可以使用列表理解来简化:</p>
<pre><code>def deal(self):
self.cardsDealt = [self.getRandomCards() for card in range(3)]
return self.cardsDealt
</code></pre>
<hr/>
<p>最后,您的<code>getRandomCards</code>可能并没有完全按照您的预期操作。通常,你会期望每张牌都有相同的机会。然而,你要做到的是俱乐部卡有1/4的几率,黑桃卡有3/16的几率,红桃卡有9/64的几率,钻石卡有27/256的几率。这样就有81/256的几率获得<em>无牌</em>。这显然是不对的。在</p>
<p>发生这种情况的原因是你对每个测试都做了随机选择。所以为了测试你是否得到俱乐部卡,你要做一个选择(1/4的机会)。如果你没有得到一张黑桃牌(3/4的机会),你会做出另一个选择来获得黑桃牌(1/4的机会;所以总共是3/4*1/4)等等。相反,你应该只做一次选择<em>,然后将结果重新用于子类别:</p>
<pre><code>def getRandomCards(self):
# only make *one* random choice for the suit
suit = random.choice(self.suits)
if suit == "C":
return random.choice(self.cardsClubs)
elif suit == "S":
return random.choice(self.cardsSpades)
elif suit == "H":
return random.choice(self.cardsHearts)
elif suit == "D":
return random.choice(self.cardsDiamonds)
</code></pre>
<p>这也使得你不可能不从这个方法中随机得到一张牌,因为你总是得到四套西装中的一套。在</p>
<hr/>
<p>最后2点,正如gboffi在评论中提到的,你没有任何保护措施来阻止你得到多张相同的卡。从<code>getRandomCards()</code>得到三张同一张牌是可能的(不太可能,但仍然有可能),这在大多数游戏中是不可能的。在</p>
<p>为了防止这种情况,您可以在所有卡片的列表中使用<a href="https://docs.python.org/3/library/random.html#random.sample" rel="nofollow">^{<cd21>}</a>。这将给你三张(或任何数字)绝对不同的卡片。它还允许你有一个真正的“牌堆”,你从中抽牌,然后离开牌堆,直到你重新开始游戏。在</p>
<p>通过设置,您可以制作如下新牌组:</p>
<pre><code>self.deck = self.cardsClubs + self.cardsSpades + self.cardsHearts + self.cardsDiamonds
</code></pre>
<p>这实际上只是将所有四个卡片列表组合在一起,创建一个新的卡片列表,然后可以从中提取。要从它们中提取三个,可以使用<code>random.sample</code>,如下所示:</p>
<pre><code>drawnCards = random.sample(self.deck, 3)
</code></pre>
<p>然后你可以从牌堆中取出这些牌:</p>
<pre><code>for card in drawnCards:
self.deck.remove(card)
</code></pre>
<p>另一种方法是更接近真实的方式。你可以先洗牌,然后从最上面抽牌,而不是从牌堆中随机抽牌。要洗牌列表,可以使用<a href="https://docs.python.org/3/library/random.html#random.shuffle" rel="nofollow">^{<cd23>}</a>,要从列表中提取和移除卡片,可以使用<code>list.pop</code>:</p>
<pre><code># create the deck
self.deck = self.cardsClubs + self.cardsSpades + self.cardsHearts + self.cardsDiamonds
# shuffle the deck
random.shuffle(self.deck)
# and then draw three cards from it
drawnCards = [self.deck.pop() for i in range(3)]
</code></pre>