使用 类 和函数在 python 上创建纸牌游戏 - 编辑

Creating a card game on python by using Classes and Functions - EDIT

我正在学习 Python 编程,并且正在尝试制作一款流行的纸牌游戏。

我从骨架开始,所以我写了一些代码来创建牌组、发牌和洗牌。 现在我想创建 2 个 "have" 手牌的玩家,他们最多可以保留 3 张牌,并且可以 "draw" 牌。 我想到了一个玩家 class,其中定义了每个不同玩家的名称和手牌属性,但是当我尝试用玩家 1 抽牌时,它也会将牌添加到玩家 2 的手上。我怎样才能改变它以便将卡片添加到玩家并且只添加到他,然后将它们从牌组中移除?我的解决方案有什么问题?

输出:

['10 di Denari', '1 di Coppe']
['10 di Denari', '1 di Coppe', '6 di Denari', '5 di Denari']

你能帮我理解如何让它工作吗?

编辑:是的,我粘贴了错误的代码,这是我需要帮助的代码:

import random
semi = ['Bastoni','Spade','Coppe','Denari']
numeri = [1,2,3,4,5,6,7,8,9,10]
mazzo = []

for element in numeri:
    for seme in semi:
        carta = str(element) + ' di ' + seme
        mazzo.append(carta)
Rimanenti = len(mazzo)
def mischia():
    random.shuffle(mazzo)
class Giocatore:
    nome = None
    mano = []
    tola = []
    def __init__(self,nome):
        self.nome=nome

    def draw(q):
        for n in range(0, q):
            pesco = random.choice(mazzo)
             Giocatore.mano.append(pesco)
            mazzo.remove(pesco)

    def turno():
        Giocatore.draw('Toni',1)
        Giocatore.draw('Piero',1)
    def inizio():
        Giocatore.draw('Toni', 3)
        Giocatore.draw('Piero', 3)


class Piero(Giocatore):
    nome = 'Piero'

class Toni(Giocatore):
    nome = 'Toni'


Toni.draw(2)
print(Toni.mano)
Piero.draw(2)
print(Piero.mano)

另一个编辑:

谢谢大家的回答!现在我对整个事情有了更好的理解,我正在以不同的方式重写它!

您使用的 class 不正确。制作玩家 class 就像定义玩家身份,这是成为纸牌游戏玩家的想法。您不能仅凭玩家的 想法 来玩纸牌游戏;您需要能够体现玩家身份的真实玩家。在编程术语中,玩家将 实例化 玩家 class。

您正在尝试使用 class 本身玩游戏,而不是 class 的实例。您需要实例化 Giocatore 两次(每个玩家一次)并使用实例进行游戏。要实例化你需要做这样的事情:

player1 = Giocatore('Pietro')
player2 = Giocatore('Toni')

在底部,您已经使用以玩家命名的新 class 子classed Giocatore。除非每个玩家都有不同的能力(即属性 and/or 方法),否则这是不必要的。它与实例化 Giocatore.

不是一回事

when i tried to draw cards with player1 it also added the cards to player2's hand.... How can i change it so it adds the cards to a a player and only to him, removing them from the deck? What is wrong with my solution?

有两个原因。首先,正如我上面所描述的,您正在玩​​ class 本身。但即使你没有这样做,还有一个额外的问题,那就是你已经将手 mano 设为 class 属性而不是 实例 属性。这意味着所有实例都将共享该属性;因此所有玩家将分享完全相同的手牌。在 draw 方法中,应该是 self.mano.append(pesco) 而不是 Giocatore.mano.append(pesco)。这样您就可以将新卡仅放在该玩家的手上,而不是所有玩家共同分享的手上。

要使手成为实例属性,您应该在 __init__ 中定义它。该方法应如下所示:

def __init__(self, nome):
    self.nome = nome
    self.mano = []

此处self指实例

至于从牌组中移除卡片,如果您在开始时已经使用 random.shuffle 将它们随机化,则无需在抽取新卡片时使用 random.choice。我建议只从列表中弹出一个,如下所示:

def draw(self, n):
    for _ in range(n):
        self.mano.append(mazzo.pop())

我认为主要问题是您误解了 class 变量和实例变量之间的区别。我将使用一个简单的例子:

class Player():
    hand = [] # hand is a class variable, as it is not tied to an instance

p1 = Player() # p1 is an instance of Player
p2 = Player() # p2 is a separate instance of Player()

现在,如果我在 p1 的手上加点东西:

p1.hand.append(1)

p2.hand
# [1]

这是因为我在class级别定义了hand,所以p1.handp2.hand都是真的Player.hand。要更改此设置,您需要使用 self.hand__init__ dunder 方法将 hand 附加到一个实例,该方法的作用类似于 class 个实例的构造函数。

class Player():
    def __init__(self): # self is always passed as the first argument
        self.hand = []

p1 = Player() 
p2 = Player()

现在,p1.hand 是一个与 p2.hand 完全不同的对象,因为它们是通过每次调用 __init__ 创建的。现在,如果我向 p1.hand 添加内容:

p1.hand.append(1)
p1.hand
# [1]
p2.hand
# []

它们都没有被修改。现在,谈谈 class 功能。默认情况下,classes 中的函数是实例级别的,这意味着 self 或 class 实例 将作为第一个隐式传递争论。如果你没有 self 的占位符,你会得到错误:

class A():
    def a():
        print("did something")

inst = A()
a.a()
# TypeError: a() takes 0 positional arguments but 1 was given

# To fix this
class A():
    def a(self):
        print("did something")

inst = A()
a.a()
# did something

计划

幸运的是,您已经确定了此程序正常运行所需的条件、两名玩家、一副牌和轮流机制。因为您正在使用 random.choice 来挑选卡片,所以我认为您实际上不需要一个函数来洗牌。您可以像之前一样通过随机选择一张卡片来获得卡片:

semi = ['Bastoni','Spade','Coppe','Denari']
numeri = [1,2,3,4,5,6,7,8,9,10]
mazzo = ['%d di %s' % (element, seme) for seme in semi for element in numeri]

要抽一张牌,您可以使用以下方法:

# Use random.choice as you've done before
idx = random.coice(mazzo)
mazzo.remove(drawn_card)

class 方法 remove 将从列表中删除一个值。搭配您的 class.hand 方法:

Toni = Player()

Toni.hand.append(drawn_card)

或者,作为 Player class 中的方法:

class Player():
    def __init__(self):
        self.hand = []

    def draw(self):
        # Need to convert set to list to choose
        drawn_card = random.choice(mazzo)
        mazzo.remove(drawn_card)
        self.hand.append(drawn_card)
        print(self.hand) # If you want to see the hand

toni = Player()

toni.draw()
# ['8 di Spade']

尽管您可能认为这有点冗长。如果你想保留你的洗牌方法,那么你可以每次洗牌并使用 pop 随机抓取一张牌,正如@ibonyun 建议的那样