結果

問題 No.769 UNOシミュレータ
ユーザー Theta
提出日時 2022-12-07 16:15:43
言語 Python3
(3.13.1 + numpy 2.2.1 + scipy 1.14.1)
結果
AC  
実行時間 1,065 ms / 2,000 ms
コード長 3,612 bytes
コンパイル時間 125 ms
コンパイル使用メモリ 12,928 KB
実行使用メモリ 40,832 KB
最終ジャッジ日時 2024-10-13 22:03:47
合計ジャッジ時間 9,616 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 23
権限があれば一括ダウンロードができます

ソースコード

diff #

from abc import abstractclassmethod, abstractmethod
from enum import Enum


class Player:
    def __init__(self) -> None:
        self.used = 0
        self.drawn = 0

    def use(self):
        self.used += 1

    def draw(self, num: int):
        self.drawn += num


class ICard:
    pass


class Game:
    def __init__(self, players: int) -> None:
        self.current_turn = 0
        self.previous_player_idx = None
        self.players = [Player() for _ in range(players)]
        self.current_direction_assc = True
        self.draw_stack = 0
        self.field_surface = None

    def force_draw_from_pile(self):
        if self.draw_stack:
            self.draw_from_pile(self.draw_stack)
            self.draw_stack = 0
            self.next_turn()

    def draw_from_pile(self, num: int = 1):
        self.players[self.current_turn].draw(num)

    def add_draw_stack(self, num: int):
        self.draw_stack += num

    def use_card(self, card: ICard):
        self.players[self.current_turn].use()
        self.update_used_card(card)
        self.previous_player_idx = self.current_turn

    def next_turn(self, diff: int = 1):
        if self.current_direction_assc:
            self.current_turn = (self.current_turn + diff) % len(self.players)
        else:
            self.current_turn = (self.current_turn - diff) % len(self.players)

    def skip(self):
        self.next_turn(2)

    def reverse(self):
        self.current_direction_assc ^= True

    def update_used_card(self, card: ICard):
        self.field_surface = card

    @property
    def previous_player(self):
        if self.previous_player_idx is None:
            return
        return self.players[self.previous_player_idx]


class Card(ICard):
    @abstractmethod
    def effect(self, game: Game):
        pass

    @classmethod
    def isinstance(cls, other):
        return isinstance(other, cls)


class NumberCard(Card):
    def effect(self, game: Game):
        game.force_draw_from_pile()
        game.use_card(self)
        game.next_turn()


class SkipCard(Card):
    def effect(self, game: Game):
        game.force_draw_from_pile()
        game.use_card(self)
        game.skip()


class ReverseCard(Card):
    def effect(self, game: Game):
        game.force_draw_from_pile()
        game.use_card(self)
        game.reverse()
        game.next_turn()


class DrawTwoCard(Card):
    def effect(self, game: Game):

        if not (game.field_surface is None or game.field_surface.isinstance(self)):
            game.force_draw_from_pile()

        game.use_card(self)
        game.add_draw_stack(2)
        game.next_turn()


class DrawFourCard(Card):
    def effect(self, game: Game):
        if not (game.field_surface is None or game.field_surface.isinstance(self)):
            game.force_draw_from_pile()

        game.use_card(self)
        game.add_draw_stack(4)
        game.next_turn()


def card_create(card_type: str) -> Card:
    match card_type:
        case "number":
            return NumberCard()
        case "drawtwo":
            return DrawTwoCard()
        case "drawfour":
            return DrawFourCard()
        case "skip":
            return SkipCard()
        case "reverse":
            return ReverseCard()
        case _:
            raise ValueError


def main():
    N, M = map(int, input().split())
    card_logs = [card_create(input()) for _ in range(M)]

    game = Game(N)

    for card in card_logs:
        card.effect(game)

    print(game.previous_player_idx + 1,
          (game.previous_player.used - game.previous_player.drawn))


if __name__ == "__main__":
    main()
0