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


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.