Решение на От ливадите до Лас Вегас (и назад) от Александра Павлова

Обратно към всички решения

Към профила на Александра Павлова

Резултати

  • 5 точки от тестове
  • 2 бонус точки
  • 7 точки общо
  • 8 успешни тест(а)
  • 7 неуспешни тест(а)

Код

from random import shuffle, randint
suits = ('clubs', 'diamonds', 'hearts', 'spades')
faces = ('2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A')
class Card:
def __init__(self, suit: str, face: str):
self._suit = suit
self._face = face
def get_suit(self):
return self._suit
def get_face(self):
return self._face
class Deck:
def __init__(self, face_filter=None):
self.face_filter = face_filter
self.deck = []
if face_filter:
[self.deck.append(Card(suit, face)) for face in self.face_filter for suit in suits]
else:
[self.deck.append(Card(suit, face)) for face in faces for suit in suits]
def cut(self):
index = randint(1, len(self.deck) - 1)
self.deck = self.deck[index:] + self.deck[:index]
return self.deck
def shuffle(self):
shuffle(self.deck)
def get_cards(self):
return self.deck
class Player:
def __init__(self):
self.player_cards = []
def get_cards(self):
return self.player_cards
class Game:

Разбирам, че при евентуална имплементация на истинска игра, може би било удачно да използваш абстрактни класове/методи, но за целта на домашното, моля дефинирай методите тук. Нека Game класа работи неутрално, дори да не бъде наследен от някоя конкретна игра. Ще има тестове, които разчитат на това. Ако дефинираш методите тук, те така или иначе ще са налични при наследяване, а реално ще си спестиш дублиране на код. Сега методите ти са дефинирани два пъти - един път в Belot и един път в Poker.

deck = Deck()
def __init__(self, number_of_players: int, dealing_direction: str, dealing_instructions: tuple):
self._number_of_players = number_of_players
self._dealing_direction = dealing_direction
self._dealing_instructions = dealing_instructions
self.players = []
def get_players(self):
for _ in range(self._number_of_players):
player = Player()
self.players.append(player)
return self.players
def prepare_deck(self):
for pl in self.players:
if pl.player_cards:
Game.deck.deck.extend(pl.player_cards)
pl.player_cards.clear()
Game.deck.shuffle()
Game.deck.cut()
def deal(self, player):
start = self.players.index(player)
if start != 0:
self.players = self.players[start:] + self.players[:start]
if self._dealing_direction == 'rtl':
self.players.reverse()
self.players.insert(0, self.players.pop())
for instruction in self._dealing_instructions:
for pl in self.players:
for _ in range(instruction):
curr_card = Game.deck.deck.pop()
pl.player_cards.append(curr_card)
return self.players
@staticmethod
def get_deck():
return Game.deck.deck
class Belot(Game):
deck = Deck(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
def __init__(self):
super().__init__(number_of_players=4, dealing_direction='ltr',
dealing_instructions=(2, 3, 3))
class Poker(Game):
def __init__(self):
super().__init__(number_of_players=9, dealing_direction='rtl', dealing_instructions=(1, 1, 1, 1, 1))

Лог от изпълнението

EE......EEE..EE
======================================================================
ERROR: test_correct_deck_init (test.TestBelot)
Test initialization with correct deck.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AttributeError: 'list' object has no attribute 'get_cards'

======================================================================
ERROR: test_correct_direction_and_players_deal (test.TestBelot)
Test dealing with correct direction and players.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AttributeError: 'list' object has no attribute 'get_cards'

======================================================================
ERROR: test_collecting_cards_before_dealing (test.TestGame)
Test collecting the cards before a new deal.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AttributeError: 'list' object has no attribute 'get_cards'

======================================================================
ERROR: test_dealing_ltr (test.TestGame)
Test dealing the cards left to right.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AttributeError: 'list' object has no attribute 'get_cards'

======================================================================
ERROR: test_dealing_rtl (test.TestGame)
Test dealing the cards right to left.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AttributeError: 'list' object has no attribute 'get_cards'

======================================================================
ERROR: test_correct_deck_init (test.TestPoker)
Test initialization with correct deck.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AttributeError: 'list' object has no attribute 'get_cards'

======================================================================
ERROR: test_correct_direction_and_players_deal (test.TestPoker)
Test dealing with correct direction and players.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AttributeError: 'list' object has no attribute 'get_cards'

----------------------------------------------------------------------
Ran 15 tests in 0.175s

FAILED (errors=7)

История (3 версии и 11 коментара)

Александра обнови решението на 07.11.2022 22:00 (преди над 1 година)

+from random import shuffle, randint
+from abc import ABC, abstractmethod
+
+suits = ('clubs', 'diamonds', 'hearts', 'spades')
+faces = ('2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A')
+
+
+class Card:
+
+ def __init__(self, suit: str, face: str):
+ self.suit = suit
+ self.face = face
+
+ def get_suit(self):
+ return self.suit
+
+ def get_face(self):
+ return self.face
+
+
+class Deck:
+
+ def __init__(self, face_filter=None):
+ self.face_filter = face_filter
+ self.deck = []
+
+ def build(self):
+ if self.face_filter:
+ [self.deck.append(Card(suit, face)) for face in self.face_filter for suit in suits]
+ else:
+ [self.deck.append(Card(suit, face)) for face in faces for suit in suits]
+ return self.deck
+
+ def cut(self):
+ index = randint(1, 52)
+ self.deck = self.deck[index:] + self.deck[:index]
+ return self.deck
+
+ def shuffle(self):
+ shuffle(self.deck)
+
+ def get_cards(self):
+ return self.deck
+
+
+class Player:
+
+ def __init__(self):
+ self.player_cards = []
+
+ def get_cards(self):
+ return self.player_cards
+
+
+class Game:

Разбирам, че при евентуална имплементация на истинска игра, може би било удачно да използваш абстрактни класове/методи, но за целта на домашното, моля дефинирай методите тук. Нека Game класа работи неутрално, дори да не бъде наследен от някоя конкретна игра. Ще има тестове, които разчитат на това. Ако дефинираш методите тук, те така или иначе ще са налични при наследяване, а реално ще си спестиш дублиране на код. Сега методите ти са дефинирани два пъти - един път в Belot и един път в Poker.

+
+ def __init__(self, number_of_players: int, dealing_direction: str, dealing_instructions: tuple):
+ self.number_of_players = number_of_players
+ self.dealing_direction = dealing_direction
+ self.dealing_instructions = dealing_instructions
+ self.players = []
+
+ @abstractmethod
+ def prepare_deck(self):
+ pass
+
+ @abstractmethod
+ def deal(self, player):
+ pass
+
+ @abstractmethod
+ def get_players(self):
+ pass
+
+ @abstractmethod
+ def get_deck(self):
+ pass
+
+
+class Belot(Game):
+ deck = Deck(['7', '8', '9', '10', 'J', 'Q', 'K', 'A']).build()
+
+ def get_players(self):
+ player1 = Player()
+ player2 = Player()
+ player3 = Player()
+ player4 = Player()
+ self.players.extend([player1, player2, player3, player4])
+ return self.players
+
+ def prepare_deck(self):
+ for pl in self.players:
+ Belot.deck.extend(pl.player_cards)
+ pl.player_cards.clear()
+ shuffle(Belot.deck)
+ index = randint(1, 52)
+ Belot.deck = Belot.deck[index:] + Belot.deck[:index]
+
+ def deal(self, player):
+ start = self.players.index(player)
+ if start != 0:
+ self.players = self.players[start:] + self.players[:start]
+ for instruction in self.dealing_instructions:
+ for pl in self.players:
+ for _ in range(instruction):
+ curr_card = Belot.deck.pop()
+ pl.player_cards.append(curr_card)
+ return self.players
+
+ def get_deck(self):
+ return Belot.deck
+
+
+# number of players - 4
+# dealing_direction - ltr
+# instructions - firstly 2 cards by player, then 3, then 3 more
+# cards_needed - 7, 8, 9, 10, J, Q, K, A
+
+
+class Poker(Game):
+ deck = Deck().build()
+
+ def get_players(self):
+ player1 = Player()
+ player2 = Player()
+ player3 = Player()
+ player4 = Player()
+ player5 = Player()
+ player6 = Player()
+ player7 = Player()
+ player8 = Player()
+ player9 = Player()
+ self.players.extend([player1, player2, player3, player4, player5, player6, player7, player8, player9])
+ return self.players
+
+ def prepare_deck(self):
+ for pl in self.players:
+ Poker.deck.extend(pl.player_cards)
+ pl.player_cards.clear()
+ shuffle(Poker.deck)
+ index = randint(1, 52)
+ Poker.deck = Poker.deck[index:] + Poker.deck[:index]
+
+ def deal(self, player):
+ start = self.players.index(player)
+ if start != 0:
+ self.players = self.players[start:] + self.players[:start]
+ for instruction in self.dealing_instructions:
+ for pl in reversed(self.players):
+ if len(pl.player_cards) == 5:
+ continue
+ for _ in range(instruction):
+ curr_card = Poker.deck.pop()
+ pl.player_cards.append(curr_card)
+ return self.players
+
+ def get_deck(self):
+ return Poker.deck
+ # number of players - 9
+ # dealing_direction - rtl
+ # instructions - 1 card to every player till they have 5 each
+ # cards_needed - whole deck

Александра обнови решението на 11.11.2022 16:22 (преди над 1 година)

from random import shuffle, randint
-from abc import ABC, abstractmethod
suits = ('clubs', 'diamonds', 'hearts', 'spades')
faces = ('2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A')
class Card:
def __init__(self, suit: str, face: str):
- self.suit = suit
- self.face = face
+ self._suit = suit
+ self._face = face
def get_suit(self):
- return self.suit
+ return self._suit
def get_face(self):
- return self.face
+ return self._face
class Deck:
def __init__(self, face_filter=None):
self.face_filter = face_filter
self.deck = []
-
- def build(self):
- if self.face_filter:
+ if face_filter:
[self.deck.append(Card(suit, face)) for face in self.face_filter for suit in suits]
else:
[self.deck.append(Card(suit, face)) for face in faces for suit in suits]
- return self.deck
def cut(self):
- index = randint(1, 52)
+ index = randint(1, len(self.deck) - 1)
self.deck = self.deck[index:] + self.deck[:index]
return self.deck
def shuffle(self):
shuffle(self.deck)
def get_cards(self):
return self.deck
class Player:
def __init__(self):
self.player_cards = []
def get_cards(self):
return self.player_cards
class Game:
+ deck = Deck()
def __init__(self, number_of_players: int, dealing_direction: str, dealing_instructions: tuple):
- self.number_of_players = number_of_players
- self.dealing_direction = dealing_direction
- self.dealing_instructions = dealing_instructions
+ self._number_of_players = number_of_players
+ self._dealing_direction = dealing_direction
+ self._dealing_instructions = dealing_instructions
self.players = []
- @abstractmethod
- def prepare_deck(self):
- pass
-
- @abstractmethod
- def deal(self, player):
- pass
-
- @abstractmethod
def get_players(self):
- pass
-
- @abstractmethod
- def get_deck(self):
- pass
-
-
-class Belot(Game):
- deck = Deck(['7', '8', '9', '10', 'J', 'Q', 'K', 'A']).build()
-
- def get_players(self):
- player1 = Player()
- player2 = Player()
- player3 = Player()
- player4 = Player()
- self.players.extend([player1, player2, player3, player4])
+ for _ in range(self._number_of_players):
+ player = Player()
+ self.players.append(player)
return self.players
def prepare_deck(self):
for pl in self.players:
- Belot.deck.extend(pl.player_cards)
- pl.player_cards.clear()
- shuffle(Belot.deck)
- index = randint(1, 52)
- Belot.deck = Belot.deck[index:] + Belot.deck[:index]
+ if pl.player_cards:
+ Game.deck.deck.extend(pl.player_cards)
+ pl.player_cards.clear()
+ Game.deck.shuffle()
+ Game.deck.cut()
def deal(self, player):
start = self.players.index(player)
if start != 0:
self.players = self.players[start:] + self.players[:start]
- for instruction in self.dealing_instructions:
+ if self._dealing_direction == 'rtl':
+ [self.players[0]].extend([reversed(self.players[1:])])
+ for instruction in self._dealing_instructions:
for pl in self.players:
for _ in range(instruction):
- curr_card = Belot.deck.pop()
+ curr_card = Game.deck.deck.pop()
pl.player_cards.append(curr_card)
return self.players
- def get_deck(self):
- return Belot.deck
+ @staticmethod
+ def get_deck():
+ return Game.deck.deck
-# number of players - 4
-# dealing_direction - ltr
-# instructions - firstly 2 cards by player, then 3, then 3 more
-# cards_needed - 7, 8, 9, 10, J, Q, K, A
+class Belot(Game):
+ deck = Deck(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
+ def __init__(self):
+ super().__init__(number_of_players=4, dealing_direction='ltr',
+ dealing_instructions=(2, 3, 3))
+
class Poker(Game):
- deck = Deck().build()
- def get_players(self):
- player1 = Player()
- player2 = Player()
- player3 = Player()
- player4 = Player()
- player5 = Player()
- player6 = Player()
- player7 = Player()
- player8 = Player()
- player9 = Player()
- self.players.extend([player1, player2, player3, player4, player5, player6, player7, player8, player9])
- return self.players
+ def __init__(self):
+ super().__init__(number_of_players=9, dealing_direction='rtl', dealing_instructions=(1, 1, 1, 1, 1))
- def prepare_deck(self):
- for pl in self.players:
- Poker.deck.extend(pl.player_cards)
- pl.player_cards.clear()
- shuffle(Poker.deck)
- index = randint(1, 52)
- Poker.deck = Poker.deck[index:] + Poker.deck[:index]
-
- def deal(self, player):
- start = self.players.index(player)
- if start != 0:
- self.players = self.players[start:] + self.players[:start]
- for instruction in self.dealing_instructions:
- for pl in reversed(self.players):
- if len(pl.player_cards) == 5:
- continue
- for _ in range(instruction):
- curr_card = Poker.deck.pop()
- pl.player_cards.append(curr_card)
- return self.players
-
- def get_deck(self):
- return Poker.deck
- # number of players - 9
- # dealing_direction - rtl
- # instructions - 1 card to every player till they have 5 each
- # cards_needed - whole deck

Александра обнови решението на 13.11.2022 22:52 (преди над 1 година)

from random import shuffle, randint
suits = ('clubs', 'diamonds', 'hearts', 'spades')
faces = ('2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A')
class Card:
def __init__(self, suit: str, face: str):
self._suit = suit
self._face = face
def get_suit(self):
return self._suit
def get_face(self):
return self._face
class Deck:
def __init__(self, face_filter=None):
self.face_filter = face_filter
self.deck = []
if face_filter:
[self.deck.append(Card(suit, face)) for face in self.face_filter for suit in suits]
else:
[self.deck.append(Card(suit, face)) for face in faces for suit in suits]
def cut(self):
index = randint(1, len(self.deck) - 1)
self.deck = self.deck[index:] + self.deck[:index]
return self.deck
def shuffle(self):
shuffle(self.deck)
def get_cards(self):
return self.deck
class Player:
def __init__(self):
self.player_cards = []
def get_cards(self):
return self.player_cards
class Game:
deck = Deck()
def __init__(self, number_of_players: int, dealing_direction: str, dealing_instructions: tuple):
self._number_of_players = number_of_players
self._dealing_direction = dealing_direction
self._dealing_instructions = dealing_instructions
self.players = []
def get_players(self):
for _ in range(self._number_of_players):
player = Player()
self.players.append(player)
return self.players
def prepare_deck(self):
for pl in self.players:
if pl.player_cards:
Game.deck.deck.extend(pl.player_cards)
pl.player_cards.clear()
Game.deck.shuffle()
Game.deck.cut()
def deal(self, player):
start = self.players.index(player)
if start != 0:
self.players = self.players[start:] + self.players[:start]
if self._dealing_direction == 'rtl':
- [self.players[0]].extend([reversed(self.players[1:])])
+ self.players.reverse()
+ self.players.insert(0, self.players.pop())
for instruction in self._dealing_instructions:
for pl in self.players:
for _ in range(instruction):
curr_card = Game.deck.deck.pop()
pl.player_cards.append(curr_card)
return self.players
@staticmethod
def get_deck():
return Game.deck.deck
class Belot(Game):
deck = Deck(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
def __init__(self):
super().__init__(number_of_players=4, dealing_direction='ltr',
dealing_instructions=(2, 3, 3))
class Poker(Game):
def __init__(self):
- super().__init__(number_of_players=9, dealing_direction='rtl', dealing_instructions=(1, 1, 1, 1, 1))
-
+ super().__init__(number_of_players=9, dealing_direction='rtl', dealing_instructions=(1, 1, 1, 1, 1))

Разбирам, че реално сигурно имаш само един проблем с кода, който ако оправиш, ще имаш максимума.
Това, обаче, е доста сериозен проблем.
Ако имаше проблем само с гетъра, който използваме за тестовете, бих преразгледал решението ти и евентуално бих те компенсирал, но тук проблемът се корени в това, че Game използва само една инстанция на Deck за всички свои инстанции - ред 52.
deck трябва да е атрибут на инстанцията, а не атрибут на класа. Така си постъпила с останалите си класове, но тук, незнайно защо, си подходила различно.
Колкото и игри да инстанцирам, винаги всички те ще споделят тесте, което значи, че не бих могъл да играя повече от веднъж. Тук се корени проблемът ти. Това е прекалено важен детайл от ООП моделът ти, за да мога да го пренебрегна.

За старанието с останалата част, с което си постигнала доста добро ниво на кода си, включително адресирането на коментарите, които оставих, както и за факта, че за 2 минути успях да преправя решението ти до максимум точки, а и за факта, че продължаваш да чоплиш по задачата след крайния срок, търсейки отговори на въпросите си, мога да те компенсирам с две точки. Смятам, че всичко повече от това, би било нечестно спрямо останалите. Надявам се да си доволна.

Твоето решение, пипнато тук-там, за да работи на 100%:

from random import shuffle, randint

suits = ('clubs', 'diamonds', 'hearts', 'spades')
faces = ('2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A')


class Card:

    def __init__(self, suit: str, face: str):
        self._suit = suit
        self._face = face

    def get_suit(self):
        return self._suit

    def get_face(self):
        return self._face


class Deck:

    def __init__(self, face_filter=None):
        self.face_filter = face_filter
        self.deck = []
        if face_filter:
            [self.deck.append(Card(suit, face)) for face in self.face_filter for suit in suits]
        else:
            [self.deck.append(Card(suit, face)) for face in faces for suit in suits]

    def cut(self):
        index = randint(1, len(self.deck) - 1)
        self.deck = self.deck[index:] + self.deck[:index]
        return self.deck

    def shuffle(self):
        shuffle(self.deck)

    def get_cards(self):
        return self.deck


class Player:

    def __init__(self):
        self.player_cards = []

    def get_cards(self):
        return self.player_cards


class Game:

    def __init__(self, number_of_players: int, dealing_direction: str, dealing_instructions: tuple):
        self._number_of_players = number_of_players
        self._dealing_direction = dealing_direction
        self._dealing_instructions = dealing_instructions
        self.players = []
        self.deck = Deck()

    def get_players(self):
        for _ in range(self._number_of_players):
            player = Player()
            self.players.append(player)
        return self.players

    def prepare_deck(self):
        for pl in self.players:
            if pl.player_cards:
                self.deck.get_cards().extend(pl.player_cards)
                pl.player_cards.clear()
        self.deck.shuffle()
        self.deck.cut()

    def deal(self, player):
        start = self.players.index(player)
        if start != 0:
            self.players = self.players[start:] + self.players[:start]
        if self._dealing_direction == 'rtl':
            self.players.reverse()
            self.players.insert(0, self.players.pop())
        for instruction in self._dealing_instructions:
            for pl in self.players:
                for _ in range(instruction):
                    curr_card = self.deck.get_cards().pop()
                    pl.player_cards.append(curr_card)
        return self.players

    def get_deck(self):
        return self.deck


class Belot(Game):

    def __init__(self):
        super().__init__(number_of_players=4, dealing_direction='ltr',
                         dealing_instructions=(2, 3, 3))
        self.deck = Deck(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])


class Poker(Game):

    def __init__(self):
        super().__init__(number_of_players=9, dealing_direction='rtl', dealing_instructions=(1, 1, 1, 1, 1))