我正在尝试构造类以玩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/