写了一个小时的OOP解法,现将代码粘贴于此,警示后人
查看原帖
写了一个小时的OOP解法,现将代码粘贴于此,警示后人
315991
HairlessVillager楼主2023/8/27 15:50
import collections.deque as deque


class UnavailableCardError(Exception):
    pass


class Card:

    def use(self):
        raise NotImplementedError()


class CardP(Card):
    def use(self, user):
        if user.health_point < user.health_point_max:
            user.health_point += 1
        else:
            raise UnavailableCardError("Health point is max.")


class CardK(Card):
    # 在使用 K 卡的时候,需要判断该回合是否使用过一次 K 卡。这个判断应该放在 CardK 类内部以保证每个类只做分内之事,但是实现这个判断需要额外的参数,需要改动 Pig.__use_card() 函数调用 CardK.use() 的参数列表。
    # CardHelper 类是冗余代码,忽视即可
    def use(self, user, pig):

class CardHelper:

    def __init__(self, user, pigs):
        self.__user = user
        self.__pigs = pigs

    def run(self):
        while True:
            card = self.__user.popleft_card()
            try:
                self.__use(card)
            except UnavailableCardError:
                self.__user.appendleft_card(card)
                break

    def __use(self, card):
        if isinstance(card, CardK)
class Pig:

    def __init__(self, init_cards):
        self.__cards = deque(init_cards)
        self.__health_point = 4
        self.__health_point_max = 4

    @property
    def health_point(self):
        return self.__health_point

    @health_point.setter
    def set_health_point(self, value):
        if 0 <= value <= self.__health_point_max:
            self.__health_point = value
        else:
            raise ValueError(
                "Trying to set health_point "
                f"{self.__health_point} -> {value}."
            )

    @property
    def health_point_max(self):
        return self.__health_point_max

    def popleft_card(self):
        return self.__cards.popleft()

    def appendleft_card(self, card):
        return self.__cards.appendleft(card)

    def act(self, public_cards, pigs):
        self.__get_card(public_cards)
        self.__use_card(pigs)

    def __get_card(self, public_cards):
        num = 2
        for _ in range(num):
            card = public_cards.pop()
            self.__cards.append(card)

    def __use_card(self, pigs):
        helper = CardHelper(user=self, pigs=pigs)
        helper.run()


class Game:
    pass

说一下我自己的思路:对题目的每个对象在代码中实现,例如卡牌有 ABC Card 和其子类 CardP, CardK,对于猪有 Pig 类,以及还没有实现的 MajorPig, ZhongPig, FanPig,通用的代码在 Pig 中实现,不通的代码在不同的具体类中具体实现。

遇到的问题是访问控制的问题,具体可以看代码中的注释。简单解释一下就是 Python 中类的成员只有 public 和 private 两个属性,也就是说要么每一个类都能用,要么只有这个类本身能用。而为了最严格控制所有成员的访问权限,同时满足题目的要求,就不得不设计许多辅助类帮助实现访问控制。笔者无法优雅地设计这些类,因此暂时放弃实现。

当然这并不能说明 OOP 解法不合适,只能说明笔者功力不足,没有理解 OOP 的精髓。

写了这么多代码,得到的一个结论:面向对象中的对象绝对不是对客观事物属性和方法的简单抽象,而是对程序中针对不同变量和函数的访问控制。

2023/8/27 15:50
加载中...