Một cách tốt để tạo các lớp cho các loại thẻ chơi phức tạp hơn các loại được tìm thấy trong một cỗ bài tiêu chuẩn?


9

Tôi cực kỳ mới đối với lập trình hướng đối tượng và đang cố gắng bắt đầu học về python bằng cách tạo ra một trò chơi bài đơn giản (dường như là truyền thống!). Tôi đã thực hiện ví dụ sau đây hoạt động tốt và dạy tôi về việc tạo nhiều thể hiện của PlayingCard()lớp để tạo một thể hiện của Deck()lớp:

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()



Tôi muốn tạo ra một cái gì đó ngay bây giờ với các thẻ phức tạp hơn, không chỉ là một cỗ bài 52 tiêu chuẩn (có giá trị tăng dần). Bộ bài tôi có trong đầu là trò chơi bài Monopoly:

nhập mô tả hình ảnh ở đây

Có 3 loại thẻ cơ bản - thẻ HÀNH ĐỘNG, THẺ TÀI SẢN và thẻ TIỀN. Thẻ hành động thực hiện các hành động khác nhau, thẻ thuộc tính thuộc các bộ màu khác nhau và thẻ tiền có thể có các giá trị khác nhau. Ngoài ra, thẻ thuộc tính có thể là "ký tự đại diện" và có thể được sử dụng như một phần của một trong hai bộ. Cuối cùng, mỗi thẻ cũng có một giá trị tiền tương đương (được chỉ định ở góc trên cùng của mỗi thẻ). Trong thẻ hành động thuê, thẻ chỉ có thể áp dụng cho thuộc tính màu được chỉ định trên thẻ.

Câu hỏi của tôi nói chung là làm thế nào để xử lý một tình huống như thế này, và cách tốt nhất để đưa các thẻ khác nhau này vào một chương trình python dựa trên lớp là gì? Tôi có nên giữ PlayingCard()lớp duy nhất của mình và chỉ cần có nhiều đầu vào, chẳng hạn như PlayingCard(type="PROPERTY", value="3M"). Hoặc nó sẽ được tốt hơn để tạo ra các lớp học riêng biệt chẳng hạn như ActionPlayingCard(), PropertyPlayingCard(), vv? đây có phải là cách tốt hơn không? Như tôi đã nói, tôi đang bắt đầu học ở đây và làm thế nào để tổ chức các loại tình huống này theo thiết kế cấp cao hơn.

Cảm ơn nhiều.


Nếu bạn thấy rằng các loại thẻ khác nhau có chung một số tính năng, bạn có thể sử dụng tính kế thừa hoặc thậm chí là một lớp Trừu tượng. Bạn có thể đọc và sử dụng Mẫu nhà máy để bạn có thể chuyển loại thẻ và loại phù hợp sẽ được sử dụng
Tomerikoo

@Tomerikoo Cảm ơn bạn đã chỉ ra điều đó - Tôi đã đọc một chút về mô hình nhà máy mà bạn đề cập. Theo tôi hiểu, điều này hữu ích nhất khi bạn không biết trước những lớp đối tượng nào bạn sẽ cần tạo (có lẽ chỉ biết khi chạy). Tuy nhiên, vì trong trường hợp này tôi biết toàn bộ bộ bài sẽ trông như thế nào (có bao nhiêu loại thẻ, mỗi loại chúng làm gì, v.v.), mô hình nhà máy có thể áp dụng ở đây không?
teeeeee

Câu trả lời:


3

Khi bạn đang tiếp cận một vấn đề với OOP , bạn thường muốn mô hình hóa các hành vi và các thuộc tính theo cách có thể sử dụng lại, tức là bạn nên nghĩ về trừu tượng hóa và sắp xếp hệ thống phân cấp lớp của bạn dựa trên đó.

Tôi sẽ viết một cái gì đó như sau:

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)


Do Python là một ngôn ngữ được gõ động, theo quan điểm của tôi , OOP khó hơn một chút, vì chúng ta chỉ có thể dựa vào gõ vịtràng buộc động , cách bạn sắp xếp thứ bậc của bạn ít quan trọng hơn.

Ví dụ, nếu tôi mô hình hóa vấn đề này trong C # , tôi chắc chắn sẽ sử dụng hệ thống phân cấp được trình bày ở trên, bởi vì tôi có thể dựa vào đa hình để biểu diễn các loại khác nhau và hướng dẫn luồng logic của tôi dựa trên loại thẻ nào được phân tích.

Một vài nhận xét cuối cùng:

  1. Python có các loại dựng sẵn rất mạnh mẽ, nhưng hầu hết thời gian sử dụng các loại tùy chỉnh mới xây dựng trên chúng giúp cuộc sống của bạn dễ dàng hơn.
  2. Bạn không phải kế thừa từ objectcác loại trong Python 3 (là loại duy nhất được duy trì tính đến ngày hôm nay) objecttheo mặc định.

Nhưng, vào cuối ngày, không có câu trả lời hoàn hảo, cách tốt nhất là thử cả hai cách tiếp cận và xem bạn cảm thấy thoải mái hơn với điều gì.


7

Đây là những gì chúng ta gọi là "quyết định thiết kế". Thông thường cách "chính xác" là một vấn đề quan điểm. Là người mới bắt đầu, tôi nghĩ sẽ rất hữu ích khi thử cả hai triển khai để xem cách chúng hoạt động. Sẽ có sự đánh đổi cho dù bạn chọn cái nào. Bạn phải quyết định sự đánh đổi nào là quan trọng nhất. Thực hiện các loại quyết định này sẽ được thông báo khi bạn có thêm kinh nghiệm.


Vâng, cảm ơn, tôi đang làm chính xác như bạn nói - chỉ cần tìm kiếm hướng dẫn từ những người đủ kinh nghiệm để theo bản năng biết một cách tiếp cận tốt, và hy vọng hiểu lý do tại sao.
teeeeee

2

Bạn có thể sử dụng thừa kế. Đây là nơi bạn tạo một lớp chính sau đó có các lớp con vẫn chứa các hàm và giá trị từ lớp mẹ, tuy nhiên cũng có thể có các giá trị và hàm bổ sung cho lớp cụ thể đó.

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

Bây giờ lớp iPhone có các chức năng tương tự như lớp Apple và chức năng riêng của nó. Nếu bạn muốn tìm hiểu thêm về thừa kế, tôi khuyên bạn nên thực hiện một số nghiên cứu.


Cảm ơn, tôi hiểu sự kế thừa và cách thức hoạt động. Mặc dù vậy, tôi quan tâm nhiều hơn đến cách nó có thể được áp dụng cho tình huống cụ thể của tôi, dựa trên các thuộc tính mà bộ bài Monopoly có.
teeeeee

@teeeeee Vì mỗi thẻ có một giá trị, bạn có thể giao dịch chúng và có thể chơi chúng, bạn có thể tạo các hàm / thủ tục trong một lớp để xử lý các sự kiện này và sau đó có các thuộc tính và chức năng bổ sung cho các thẻ nhất định trong một lớp con.
MoriartyPy

0

Để độc quyền, tôi sẽ thiết kế quan điểm hạ cánh trò chơi. Không phải thẻ. Thẻ chỉ đơn giản là đại diện cho cuộc đổ bộ cho thế giới thực.


Xin hãy giải thích.
teeeeee
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.