为比标准牌组中更复杂的扑克牌类型制作课程的好方法?

tee*_*eee 9 python oop class instance object-oriented-analysis

我对面向对象编程非常陌生,并且正在尝试通过制作一个简单的纸牌游戏(似乎是传统的!)来开始学习 Python。我已经完成了以下工作正常的示例,并教我如何PlayingCard()创建类的多个实例以创建类的实例Deck()

class PlayingCard(object):
    def __init__(self, suit, val):
        self.suit = suit
        self.value = val

    def print_card(self):
        print("{} of {}".format(self.value, self.suit))

class Deck(object):
    def __init__(self):
        self.playingcards = []
        self.build()

    def build(self):
        for s in ["Spades", "Clubs", "Diamonds", "Hearts"]:
            for v in range(1,14):
                self.playingcards.append(PlayingCard(s,v))

deck = Deck()
Run Code Online (Sandbox Code Playgroud)



我现在想用更复杂的卡片制作一些东西,而不仅仅是标准的 52 副牌(它有很好的递增值)。我想到的牌组是大富翁纸牌游戏:

在此处输入图片说明

卡片有 3 种基本类型 - 行动卡片、财产卡片和金钱卡片。动作卡执行不同的动作,属性卡属于不同的颜色组,钱卡可以有不同的值。此外,属性卡可以是“通配符”,并且可以用作两组之一的一部分。最后,每张卡还具有等值的货币价值(在每张卡的顶角标明)。在租金行动卡中,该卡只能适用于卡上标明的颜色属性。

我的问题通常是如何处理这样的情况,以及将这些不同的卡片包含在基于类的 Python 程序中的好方法是什么?我应该保留我的单一PlayingCard()课程,并且只有很多输入,例如PlayingCard(type="PROPERTY", value="3M"). 还是会更好地创建单独的类,如ActionPlayingCard()PropertyPlayingCard()等?或者,还有更好的方法?正如我所说,我刚刚开始在这里学习,以及如何根据更高级别的设计来组织这些类型的情况。

非常感谢。

Cod*_*ice 7

这些就是我们所说的“设计决策”。通常“正确”的方式是见仁见智的。作为初学者,我认为尝试两种实现以了解它们是如何工作的会很有启发性。无论你选择哪一个,都会有取舍。您必须决定哪些权衡是最重要的。随着您获得更多经验,您将做出此类决定。


ale*_*lex 3

当您使用OOP解决问题时,您通常希望以可重用的方式对行为和属性进行建模,即您应该考虑抽象并基于抽象来组织您的类层次结构。

我会写如下内容:

class Card:
    def __init__(self, money_value=0):
        self.money_value = money_value

class ActionCard(Card):
    def __init__(self, action, money_value=0):
        super().__init__(money_value=money_value)

        self.action = action

class RentActionCard(ActionCard):
    def __init__(self, action, color, money_value=0):
        super().__init__(action, money_value=money_value)

        self.color = color

    def apply(self, property_card):
        if property_card.color != self.color:
            # Don't apply
        # Apply

class PropertyCard(Card):
    def __init__(self, color, money_value=0):
        super().__init__(money_value=money_value)

        self.color = color

class WildcardPropertyCard(PropertyCard):
    def __init__(self, color, money_value=0):
        super().__init__(color, money_value=money_value)

class MoneyCard(Card):
    def __init__(self, money_value=0):
        super().__init__(money_value=money_value)


Run Code Online (Sandbox Code Playgroud)

由于Python是一种动态类型语言,在我看来, OOP有点难以证明其合理性,因为我们只能依赖鸭子类型动态绑定,组织层次结构的方式并不那么重要。

例如,如果我要在C#中对这个问题进行建模,我毫无疑问会使用上面显示的层次结构,因为我可以依靠多态性来表示不同的类型,并根据正在分析的卡片类型来指导我的逻辑流程。

最后几句话:

  1. Python具有非常强大的内置类型,但大多数时候使用基于它们构建的新自定义类型会让您的生活更轻松。
  2. 您不必继承自,object因为Python 3中的类型(这是迄今为止唯一维护的类型)object默认继承自。

但是,归根结底,没有完美的答案,最好的方法是尝试这两种方法,看看哪种方法更适合您。