Решение на От ливадите до Лас Вегас (и назад) от Ива Гочева

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

Към профила на Ива Гочева

Резултати

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

Код

import random
class Card:
suits = ["spades", "hearts", "diamonds", "clubs"]
values = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
def __init__(self, face, suit):
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):

*face_filter значи, че можеш да подадеш и повече от един аргумент на този метод, а ти искаш да можеш да подаваш само един (или нула). За да стане optional, трябва просто да добавиш стойност по подразбиране.

self.cards = []
for face in face_filter:

Класът ти трябва да може да се инициализира дори без да дам face_filter, а сега това няма да се случи, защото няма да му добавиш карти. При инициализиране без филтър, трябва да получа тесте с всички 52 карти.

for i in range(4):

for suit in suits е за предпочитане. Първо, после не бъркаш в колекцията по индекс, а директно използваш обекта. Второ, не се налага да хардкоудваш дължината на колекцията.

self.cards.append(Card(face, Card.suits[i]))
def cut(self):
size = len(self.cards) - 1
split = random.randint(1,size)
first_half = self.cards[:split]
second_half = self.cards[split:]
self.cards = second_half
self.cards.extend(first_half)
def shuffle(self):
random.shuffle(self.cards)
def get_cards(self):
return self.cards
def fill_with_all_cards(self):
for face in Card.values:
for i in range(4):
self.cards.append(Card(face, Card.suits[i]))
class Player:
def __init__(self):
self.cards =[]
def get_cards(self):
return self.cards
def return_cards(self):
cards = self.cards
self.cards=[]
return cards
def draw(self, deck, times):
for i in range(times):
self.cards.append(deck.get_cards().pop())
class Game:
round = 0

Целта на тази дефиниция не ми е много ясна. Искаш да се подсигуриш, че първото раздаване няма да събира карти от играчите? Ако е така, просто си го остави да събира. Те няма да имат карти, но кодът ти пак трябва да сработи.

deck = Deck()

Така дефинирано, всяка инстанция на Game ще има едно и също тесте. При повече игри ще стане преплитане на тестетата. Правилният начин е deck да е атрибут на иснтанцията, а не на класа.

def __init__(self, number_of_players, dealing_direction, *dealing_instructions):

dealing_instructions винаги трябва да бъде един елемент - ние подаваме tuple. С този синтаксис позволяваш повече аргументи към инициализатора, отлкото е нужно.

self.players = []
for i in range(number_of_players):
self.players.append(Player())
self.dealing_direction = dealing_direction
self.dealing_instructions = dealing_instructions
def get_players(self):
return self.players
def prepare_deck(self):
if(self.round != 0):
for p in self.players:
self.deck.cards.extend(p.return_cards())
self.deck.shuffle()
self.deck.cut()
def deal(self, player):
if not self.deck.cards or player not in self.players:
return
self._deal_out(self.__indexMove(self.players.index(player)))
self.round += 1
def _deal_out(self, order):
for j in self.dealing_instructions:
for p in [self.players[i] for i in order]:
p.draw(self.deck, j)
def __indexMove(self, idx):
if self.dealing_direction == 'ltr':
return (list(range(idx, len(self.players))) + list(range(0, idx)))
else:
return (list(range(idx, -1, -1)) + list(range(len(self.players) -1, idx, -1)))
def get_deck(self):
return self.deck
class Belot(Game):
def __init__(self):
super().__init__(4, 'ltr', 2,3,3)
self.deck = Deck('7', '8', '9', '10', 'J', 'Q', 'K', 'A')
class Poker(Game):
def __init__(self):
super().__init__(9, 'rtl', 1, 1 )
self.deck.fill_with_all_cards()
def _deal_out(self, order):
for j in range(5):
for p in [self.players[i] for i in order]:
p.draw(self.deck, 1)

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

..FF.EFFEEE....
======================================================================
ERROR: test_init_filtered (test.TestDeck)
Test initialized cards with filter.
----------------------------------------------------------------------
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
TypeError: unhashable type: 'list'

======================================================================
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
ValueError: empty range for randrange() (1, 0, -1)

======================================================================
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
IndexError: list index out of range

======================================================================
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
IndexError: list index out of range

======================================================================
FAIL: test_get_face (test.TestCard)
Test the get_face method.
----------------------------------------------------------------------
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
AssertionError: 'spades' != 'A'
- spades
+ A


======================================================================
FAIL: test_get_suit (test.TestCard)
Test the get_suit method.
----------------------------------------------------------------------
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
AssertionError: 'A' != 'spades'
- A
+ spades


======================================================================
FAIL: test_init_regular (test.TestDeck)
Test initialized cards without filter.
----------------------------------------------------------------------
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
AssertionError: Items in the first set but not the second:
('clubs', 'Q')
('spades', '5')
('diamonds', 'Q')
('clubs', '2')
('clubs', '9')
('spades', 'A')
('diamonds', '5')
('clubs', '5')
('diamonds', '2')
('diamonds', '9')
('spades', '3')
('spades', '8')
('clubs', 'A')
('clubs', '3')
('diamonds', '8')
('clubs', '8')
('diamonds', 'A')
('hearts', '9')
('hearts', 'Q')
('diamonds', '3')
('hearts', '5')
('hearts', '2')
('spades', 'J')
('clubs', 'J')
('spades', '4')
('hearts', '3')
('hearts', '8')
('diamonds', 'J')
('hearts', 'A')
('spades', '6')
('spades', '7')
('diamonds', '4')
('clubs', '4')
('diamonds', '6')
('clubs', '6')
('clubs', '7')
('diamonds', '7')
('hearts', 'J')
('spades', '10')
('hearts', '4')
('spades', 'K')
('hearts', '6')
('diamonds', '10')
('clubs', '10')
('hearts', '7')
('clubs', 'K')
('diamonds', 'K')
('hearts', '10')
('spades', 'Q')
('spades', '2')
('spades', '9')
('hearts', 'K')

======================================================================
FAIL: test_shuffling_deck (test.TestDeck)
Test shuffling a 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
AssertionError: [] == []

----------------------------------------------------------------------
Ran 15 tests in 0.183s

FAILED (failures=4, errors=4)

История (1 версия и 18 коментара)

Ива обнови решението на 15.11.2022 14:38 (преди над 1 година)

+import random
+
+class Card:
+
+ suits = ["spades", "hearts", "diamonds", "clubs"]
+ values = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
+
+ def __init__(self, face, suit):
+ 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):

*face_filter значи, че можеш да подадеш и повече от един аргумент на този метод, а ти искаш да можеш да подаваш само един (или нула). За да стане optional, трябва просто да добавиш стойност по подразбиране.

+ self.cards = []
+ for face in face_filter:

Класът ти трябва да може да се инициализира дори без да дам face_filter, а сега това няма да се случи, защото няма да му добавиш карти. При инициализиране без филтър, трябва да получа тесте с всички 52 карти.

+ for i in range(4):

for suit in suits е за предпочитане. Първо, после не бъркаш в колекцията по индекс, а директно използваш обекта. Второ, не се налага да хардкоудваш дължината на колекцията.

+ self.cards.append(Card(face, Card.suits[i]))
+
+ def cut(self):
+ size = len(self.cards) - 1
+ split = random.randint(1,size)
+ first_half = self.cards[:split]
+ second_half = self.cards[split:]
+ self.cards = second_half
+ self.cards.extend(first_half)
+
+ def shuffle(self):
+ random.shuffle(self.cards)
+
+ def get_cards(self):
+ return self.cards
+
+ def fill_with_all_cards(self):
+ for face in Card.values:
+ for i in range(4):
+ self.cards.append(Card(face, Card.suits[i]))
+
+class Player:
+
+ def __init__(self):
+ self.cards =[]
+
+ def get_cards(self):
+ return self.cards
+
+ def return_cards(self):
+ cards = self.cards
+ self.cards=[]
+ return cards
+
+ def draw(self, deck, times):
+ for i in range(times):
+ self.cards.append(deck.get_cards().pop())
+
+class Game:
+ round = 0

Целта на тази дефиниция не ми е много ясна. Искаш да се подсигуриш, че първото раздаване няма да събира карти от играчите? Ако е така, просто си го остави да събира. Те няма да имат карти, но кодът ти пак трябва да сработи.

+ deck = Deck()

Така дефинирано, всяка инстанция на Game ще има едно и също тесте. При повече игри ще стане преплитане на тестетата. Правилният начин е deck да е атрибут на иснтанцията, а не на класа.

+ def __init__(self, number_of_players, dealing_direction, *dealing_instructions):

dealing_instructions винаги трябва да бъде един елемент - ние подаваме tuple. С този синтаксис позволяваш повече аргументи към инициализатора, отлкото е нужно.

+ self.players = []
+ for i in range(number_of_players):
+ self.players.append(Player())
+ self.dealing_direction = dealing_direction
+ self.dealing_instructions = dealing_instructions
+
+ def get_players(self):
+ return self.players
+
+ def prepare_deck(self):
+ if(self.round != 0):
+ for p in self.players:
+ self.deck.cards.extend(p.return_cards())
+ self.deck.shuffle()
+ self.deck.cut()
+
+ def deal(self, player):
+ if not self.deck.cards or player not in self.players:
+ return
+ self._deal_out(self.__indexMove(self.players.index(player)))
+ self.round += 1
+
+ def _deal_out(self, order):
+ for j in self.dealing_instructions:
+ for p in [self.players[i] for i in order]:
+ p.draw(self.deck, j)
+
+ def __indexMove(self, idx):
+ if self.dealing_direction == 'ltr':
+ return (list(range(idx, len(self.players))) + list(range(0, idx)))
+ else:
+ return (list(range(idx, -1, -1)) + list(range(len(self.players) -1, idx, -1)))
+
+ def get_deck(self):
+ return self.deck
+
+class Belot(Game):
+
+ def __init__(self):
+ super().__init__(4, 'ltr', 2,3,3)
+ self.deck = Deck('7', '8', '9', '10', 'J', 'Q', 'K', 'A')
+
+class Poker(Game):
+ def __init__(self):
+ super().__init__(9, 'rtl', 1, 1 )
+ self.deck.fill_with_all_cards()
+
+ def _deal_out(self, order):
+ for j in range(5):
+ for p in [self.players[i] for i in order]:
+ p.draw(self.deck, 1)