我正在尝试构造类以玩MTG(纸牌游戏)游戏。我有三个相关的类:MTGGame(...),MTGCard(...)和AbilityList()。 MTGGame的对象具有有关玩家的几个属性(转身,法力,...,副牌)。

玩家必须拥有一副纸牌才能玩,因此我为作为纸牌的每个玩家创建了MTGCard对象的列表,并从各自的纸牌中为每个玩家创建了MTGGame对象。这些卡具有异能,并且在创建卡时,我会将异能作为功能/参数存储在每个MTGCard中。但是,我需要具有从MTGGame继承和访问方法/属性并更新它们的能力,但是如果使用super().__init__,那么在制作MTGCard时,我将需要调用我的牌组作为AbilityList的参数,而我没有然而。

能做到吗?如果不是,有什么建议可以改善我的OOP逻辑以完成此任务?

我知道我可以做这样的事情:

class MTGGame():

    def __init__(self, deck, turn = 0, mana = 0, lifeTotal = 20, cavalcadeCount = 0, hand = [], board = []):
        self.turn = turn
        self.mana = mana
        self.lifeTotal = lifeTotal
        ...
    def gainLife(self, lifeGained):
        self.lifeTotal = self.lifeTotal +lifeGained
    def combatPhase(self):
        for card in self.board:
            card.attackingAbility()

class MTGCard():

    def __init__(self, name, CMC, cardType, power, toughness, castedAbility, attackingAbility, activatedAbility, canAttack = False):
        ....
        self.attackingAbility = attackingAbility

Class abilityList():

    def healersHawkAbility(self, lifeAmt):
        MTGGame.gainLife(lifeAmt)



但这会影响MTGGame的所有实例,而不是会从中调用的特定MTGGame对象。我希望它只是更新有问题的特定对象。我想做这样的事情,但我不知道能力列表方法如何访问MTGGame属性/方法(“能力列表”对象没有属性“ gainLife”):

Class abilityList():

    def healersHawkAbility(self, lifeAmt):
        #How do I access methods/attributes in MTGGame from here? self?
        self.gainLife(lifeAmt)

aL = abilityList()
#One example card:
card1 = MTGCard("Healers Hawk",1,'Creature',1,1, aL.nullAbility(), aL.healersHawkAbility, aL.nullAbility())
whiteDeck = [list of constructed MTGCard() objects, card1, card2,...,cardLast]
player1 = MTGGame(whiteDeck)
...

#Call the ability in a method contained in MTGGame:
player1.combatPhase()
#Would call something like this inside
card.attackingAbility()

#Which may refer to card.healersHawkAbility() since we stored healersHawkAbility() as an attribute for that MTGCard,
#and would declare gainLife(), which refers to self.lifeTotal or player1.lifeTotal in this case.

最佳答案

这是一个很好的开始,显然您已经考虑了很多。但是,您还没有考虑过类之间的关系。

首先要注意的是:
MTGGame.gainLife(lifeAmt)是通过类而不是实例访问的方法调用。这意味着self参数实际上并未填写,即由于您的方法需要2个参数而只接收1个参数,因此会出现错误。
您可能打算做的事情如下:

class MTGGame:

    lifeTotal = 20 # Notice this is declared as a class variable

    def __init__(self, ...):
        ...

    @classmethod
    def healersHawkAbility(cls, lifeGained):
        cls.lifeTotal = cls.lifeTotal + lifeGained


但是,这需要类变量,这在这里使实例无法实现。

您在整个程序中的命名都应该表明您的课程有点差。
例如player1 = MTGGame()。玩家是游戏吗?不,当然不是。因此,实际上您可能希望将MTGGame类重命名为Player,以使其清楚地指向玩家,而不是游戏。可能需要创建一个单独的类MTGGame来管理玩家之间的互动,例如轮到谁了,在结算的同时拿着纸牌的堆叠。

您的问题的主要重点:如何处理访问游戏/玩家对象的卡牌。

卡牌应该能够访问玩家和游戏类别的实例,并且如果玩家具有is_playing属性,那么卡牌就不应具有此属性。继承的经验法则是“是”。由于纸牌“不是”玩家,因此不应继承它或MTGGame。取而代之的是,card应该像这样:

game = RevisedMTGGame()
player1 = Player()
player2 = Player()

class Card:
    def __init__(self, name, text, cost):
        self.name = name
        self.text = text
        self.cost = cost
        self.owner = None
        self.game = None

class Creature(Card):
    def __init__(self, name, text, cost, power, toughness):
        super().__init__(self, name, text, cost)
        self.power = power
        self.toughness = toughness
    def lifelink(self):
        self.owner.heal(self.power) # NOTE: this is NOT how I would implement lifelink, it is an example of how to access the owner

healersHawk = Creature("Healer's Hawk", "Flying, Lifelink", 1, 1, 1)
healersHawk.game = game
healersHawk.owner = player1


从这个不完整的示例中可以看到,即使使用复杂的机制,也可以轻松地设置卡,并且由于已经定义了基类,因此可以避免重新编写代码。例如,您可能想研究事件模型以实现生命链接机制。我希望你能继续游戏下去!

关于python - 继承类属性而不声明属性或更好的OOP,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59708346/

10-09 12:43