Хороший спосіб скласти заняття для складніших типів гральних карт, ніж ті, що знайдені в стандартній колоді?


9

Я надзвичайно новачок в об'єктно-орієнтованому програмуванні і намагаюся почати вчитися на 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()



Я хочу зробити щось зараз із більш складними картами, а не просто зі стандартною 52 колодою (яка має приємно зростаючі значення). Колода, яку я маю на увазі, - це картка Monopoly:

введіть тут опис зображення

Існує 3 основні типи карток - картки ДІЙ, карт ВЛАСНІСТЬ та картки ГРОШІ. Карти дій виконують різні дії, картки власності належать до різних кольорових наборів, а грошові картки можуть мати різні значення. Крім того, картки власності можуть бути "макетками" і можуть використовуватися як частина одного з двох наборів. Нарешті, кожна картка також має еквівалентну вартість грошей (вказана у верхньому куті кожної картки). У картках дій з прокату картка може застосовуватися лише до властивості кольору, зазначеної на картці.

Моє запитання полягає лише в тому, як вирішити подібну ситуацію, і що було б приємним способом включити ці різні картки в програму python на основі класу? Чи повинен я тримати свій єдиний PlayingCard()клас і просто мати багато входів, таких як PlayingCard(type="PROPERTY", value="3M"). Або було б краще , щоб створити роздільні класи , такі як ActionPlayingCard(), PropertyPlayingCard()і т.д.? Або є кращий спосіб? Як я кажу, я на початку свого навчання тут, і як організувати такі типи ситуацій з точки зору дизайну вищого рівня.

Дуже дякую.


Якщо ви виявите, що різні типи карт мають деякі функції, ви можете використовувати спадщину чи навіть клас "Анотація". Ви можете ознайомитись із фабричним
малюнком

@Tomerikoo Дякую, що вказали на це - я трохи прочитав про згаданий вами заводський зразок. Як я розумію, це найкорисніше, коли ви заздалегідь не знаєте, які класи об’єктів потрібно буде створити (можливо, знаючи лише під час виконання). Однак, оскільки в цьому випадку я знаю, як повинна виглядати вся колода (скільки кожного типу карт, що вони роблять і т. Д.), Чи застосовується тут заводський зразок?
teeeeee

Відповіді:


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)

Зважаючи на те, що Python є динамічно набраною мовою, OOP трохи складніше виправдати, на мій погляд, оскільки ми можемо просто покладатися на введення качок та динамічне зв’язування , спосіб організації вашої ієрархії є менш важливим.

Якби я, наприклад, моделював цю проблему в C # , я б без сумніву використовував ієрархію, показану вище, тому що я міг би покластися на поліморфізм для представлення різних типів та керування потоком моєї логіки на основі того, який тип карти аналізується.

Кілька заключних зауважень:

  1. У Python є дуже потужні вбудовані типи, але більшість часу, використовуючи нові користувацькі типи, які будуються на них, полегшує ваше життя.
  2. Вам не доведеться успадковувати objectтипи, оскільки типи в Python 3 (який єдиний підтримується на сьогодні) успадковують objectза замовчуванням.

Але, нарешті, немає ідеальної відповіді, найкращим способом було б спробувати обидва підходи та побачити, що вам більше комфортно.


7

Це те, що ми називаємо «дизайнерськими рішеннями». Часто "правильний" спосіб - це питання думки. Як початківець, я думаю, було б доцільно спробувати обидві реалізації, щоб побачити, як вони працюють. Будуть розпродажі незалежно від того, яку з них ви виберете. Ви повинні вирішити, який з цих компромісів є найважливішим. Приймаючи такі рішення, ви будете поінформовані, коли ви отримаєте більше досвіду.


Так, дякую, я роблю саме так, як ви кажете - просто шукаю настанови у людей, які мають достатньо досвіду, щоб інстинктивно знати хороший підхід, і сподіваємось зрозуміти, чому.
teeeeee

2

Ви могли використовувати спадщину. Тут ви створюєте основний клас, тоді у вас є підкласи, які все ще містять функції та значення материнського класу, проте можуть також мати додаткові значення та функції для цього конкретного класу.

class Apple:
    def __init__(self, yearMade):
        pass

    def ring(self):
        print('ring ring')

class iPhone(Apple):
    def __init__(self, number)
        number = number

    def func():
        pass

Тепер клас iPhone має ті ж функції, що і клас Apple, і свою функцію. Якщо ви хочете дізнатися більше про спадщину, рекомендую провести кілька досліджень.


@teeeeee Оскільки кожна картка має значення, ви можете торгувати ними та грати в них, ви можете створити функції / процедури в класі для обробки цих подій, а потім мати додаткові атрибути та функції для певних карт у підкласі.
MoriartyPy

0

Щодо монополії, я б розробив точку зору ігрових посадок. Не картки. Картки просто представляють посадки для реального світу.


Будь ласка, докладно.
teeeeee
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.