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

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

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

Резултати

  • 9 точки от тестове
  • 0 бонус точки
  • 9 точки общо
  • 13 успешни тест(а)
  • 2 неуспешни тест(а)

Код

import random
valid_suits = ['clubs', 'diamonds', 'hearts', 'spades']
valid_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
class Card:
def __init__(self, suit: str, face: str):
if self.is_valid_suit(suit):
self._suit = suit
if self.is_valid_face(face):
self._face = face
@staticmethod
def is_valid_suit(suit):
return suit in valid_suits
@staticmethod
def is_valid_face(face):
return face in valid_faces
def get_suit(self):
return self._suit
def get_face(self):
return self._face
def __str__(self):
return '{} : {}'.format(self._suit, self._face)
class Deck:
def __init__(self, face_filter=valid_faces):
self.cards = []
for face in face_filter:
for suit in valid_suits:
self.cards.append(Card(suit, face))
def cut(self):
cards_to_cut = random.randint(0, len(self.cards) - 1)
moved_cards = self.cards[:cards_to_cut]
del self.cards[:cards_to_cut]
self.cards += moved_cards
def shuffle(self):
random.shuffle(self.cards)
def get_cards(self):
return self.cards
def __str__(self):
return ', '.join(str(card) for card in self.cards)
class Player:
def __init__(self):
self.cards = []
self.id = 0
def get_cards(self):
return self.cards
def set_player_id(self, id):
self.id = id
def __str__(self):
return ', '.join(str(card) for card in self.cards)
class Game:
def __init__(self, number_of_players: int, dealing_direction: str, dealing_instructions: tuple, face_filter=valid_faces):
self.players = []
self.deck = Deck(face_filter)
for player_idx in range(number_of_players):
new_player = Player()
new_player.set_player_id(player_idx)
self.players.append(new_player)
self.dealing_direction = dealing_direction
self.dealing_instructions = dealing_instructions
def get_players(self):
return self.players
def prepare_deck(self):
for player in self.players:
return_cards = player.get_cards()
for card_idx in range(len(return_cards)):
self.deck.cards.append(player.cards[card_idx])
for _ in range(len(return_cards)):
player.cards.pop()
self.deck.shuffle()
self.deck.cut()
def get_player_index(self, player):
for p in self.players:
index += 1
if p.id == player.id:
return index
def deal(self, player):
player_start_index = self.get_player_index(player)
if self.dealing_direction == 'ltr':
for cards_to_deal in self.dealing_instructions:
for player_idx in range(player_start_index, len(self.players)):
self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
del self.deck.cards[:cards_to_deal]
for player_idx in range(player_start_index):
self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
del self.deck.cards[:cards_to_deal]
else:
for cards_to_deal in self.dealing_instructions:
for player_idx in range(player_start_index, 0, -1):
self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
del self.deck.cards[:cards_to_deal]
for player_idx in range(len(self.players), player_start_index, -1):
self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
del self.deck.cards[:cards_to_deal]
def get_deck(self):
return self.deck
class Belot(Game):
def __init__(self):
super().__init__(4, 'ltr', (2, 3, 3), ['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Poker(Game):
def __init__(self):
super().__init__(9, 'rtl', (1, 1, 1, 1, 1))

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

..........E...E
======================================================================
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

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

----------------------------------------------------------------------
Ran 15 tests in 0.156s

FAILED (errors=2)

История (2 версии и 7 коментара)

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

+import random
+
+valid_suits = ['clubs', 'diamonds', 'hearts', 'spades']
+valid_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
+
+
+class Card:
+
+ def __init__(self, suit: str, face: str):
+ if self.is_valid_suit(suit):
+ self.suit = suit
+ if self.is_valid_face(face):
+ self.face = face
+
+ @staticmethod
+ def is_valid_suit(suit):
+ return suit in valid_suits
+
+ @staticmethod
+ def is_valid_face(face):
+ return face in valid_faces
+
+ def get_suit(self):
+ return self.suit
+
+ def get_face(self):
+ return self.face
+
+ def __eq__(self, other):

Добавяйки __eq__ правиш обектa си unhashable, освен ако не дефинираш и __hash__. Това значи, че ако искам да взема списък карти и ги поставя в set, което по една случайност е точно това, което правим в тестовете си, няма да ни позволиш.
Ако наистина в кода си използваш тази функционалност, добави и __hash__ = object.__hash__ във всеи обект, който предефинира __eq__. Ако не, просто махни __eq__.
Ако не го направиш, доста тестове ще гръмнат. Бих преправил тестовете да заобикалят този проблем, но не смятам, че проблемът е в тестовете. Проблемът е в твоя код. Използването на карти в set е от огромна важност за една истинска игра с карти.

+ return self.suit == other.suit and self.face == other.face
+
+
+def generate_full_deck():
+ deck = []
+ for suit in valid_suits:
+ for face in valid_faces:
+ deck.append(Card(suit, face))
+
+ return deck
+
+
+class Deck:
+ def __init__(self, face_filter=valid_faces):
+ self.cards = []
+ for face in face_filter:
+ for suit in valid_suits:
+ self.cards.append(Card(suit, face))
+
+ def cut(self):
+ cards_to_cut = random.randint(0, len(self.cards))
+ moved_cards = self.cards[:cards_to_cut]
+ del self.cards[:cards_to_cut]
+ self.cards += moved_cards
+
+ def shuffle(self):
+ random.shuffle(self.cards)
+
+ def get_cards(self):
+ return self.cards
+
+ def __eq__(self, other):
+ return self.cards == other.cards
+
+
+class Player:
+ def __init__(self):
+ self.cards = []
+
+ def get_cards(self):
+ return self.cards
+
+ def __eq__(self, other):
+ return self.cards == other.cards
+
+
+class Game:
+ def __init__(self, number_of_players: int, dealing_direction: str, dealing_instructions: tuple, face_filter=valid_faces):
+ self.players = []
+ self.deck = Deck(face_filter)
+ for _ in range(number_of_players):
+ self.players.append(Player())
+
+ self.dealing_direction = dealing_direction
+ self.dealing_instructions = dealing_instructions
+
+ def get_players(self):
+ from_player = random.randrange(len(self.players))

Може просто да върнеш self.players, което е частен случай на твоят вариант. Причината в условието да пише произволен играч е, че не знаем как ще държиш играчите си в класа и не можем да дефинираме кой е пръв и кой последен.

+ players_row = []
+ for player_idx in range(from_player, len(self.players)):
+ players_row.append(self.players[player_idx])
+ for player_idx in range(0, from_player):
+ players_row.append(self.players[player_idx])
+
+ return players_row
+
+ def prepare_deck(self):
+ for player in self.players:
+ return_cards = player.get_cards()
+ print("Player hand: ", player)
+ for card_idx in range(len(return_cards)):
+ self.deck.cards.append(player.cards[card_idx])
+ for _ in range(len(return_cards)):
+ player.cards.pop()
+
+ self.deck.shuffle()
+ self.deck.cut()
+
+ def get_player_index(self, player):
+ index = -1
+ for p in self.players:
+ index += 1
+ if p == player:
+ return index
+
+ def deal(self, player):
+ player_start_index = self.get_player_index(player)
+ if self.dealing_direction.startswith('l'):
+ for cards_to_deal in self.dealing_instructions:
+ for player_idx in range(player_start_index, len(self.players)):
+ self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
+ del self.deck.cards[:cards_to_deal]
+ for player_idx in range(player_start_index):
+ self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
+ del self.deck.cards[:cards_to_deal]
+ else:
+ for cards_to_deal in self.dealing_instructions:
+ for player_idx in range(player_start_index, 0, -1):
+ self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
+ del self.deck.cards[:cards_to_deal]
+ for player_idx in range(len(self.players), player_start_index, -1):
+ self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
+ del self.deck.cards[:cards_to_deal]
+
+ def get_deck(self):
+ return self.deck
+
+
+class Belot(Game):
+ def __init__(self):
+ super().__init__(4, 'ltr', (2, 3, 3), ['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
+
+
+class Poker(Game):
+ def __init__(self):
+ super().__init__(9, 'rtl', (1, 1, 1, 1, 1))

Алекс обнови решението на 15.11.2022 13:59 (преди над 1 година)

import random
valid_suits = ['clubs', 'diamonds', 'hearts', 'spades']
valid_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
class Card:
def __init__(self, suit: str, face: str):
if self.is_valid_suit(suit):
- self.suit = suit
+ self._suit = suit
if self.is_valid_face(face):
- self.face = face
+ self._face = face
@staticmethod
def is_valid_suit(suit):
return suit in valid_suits
@staticmethod
def is_valid_face(face):
return face in valid_faces
def get_suit(self):
- return self.suit
+ return self._suit
def get_face(self):
- return self.face
+ return self._face
- def __eq__(self, other):
- return self.suit == other.suit and self.face == other.face
+ def __str__(self):
+ return '{} : {}'.format(self._suit, self._face)
-def generate_full_deck():
- deck = []
- for suit in valid_suits:
- for face in valid_faces:
- deck.append(Card(suit, face))
-
- return deck
-
-
class Deck:
def __init__(self, face_filter=valid_faces):
self.cards = []
for face in face_filter:
for suit in valid_suits:
self.cards.append(Card(suit, face))
def cut(self):
- cards_to_cut = random.randint(0, len(self.cards))
+ cards_to_cut = random.randint(0, len(self.cards) - 1)
moved_cards = self.cards[:cards_to_cut]
del self.cards[:cards_to_cut]
self.cards += moved_cards
def shuffle(self):
random.shuffle(self.cards)
def get_cards(self):
return self.cards
- def __eq__(self, other):
- return self.cards == other.cards
+ def __str__(self):
+ return ', '.join(str(card) for card in self.cards)
class Player:
def __init__(self):
self.cards = []
+ self.id = 0
def get_cards(self):
return self.cards
- def __eq__(self, other):
- return self.cards == other.cards
+ def set_player_id(self, id):
+ self.id = id
+ def __str__(self):
+ return ', '.join(str(card) for card in self.cards)
+
class Game:
def __init__(self, number_of_players: int, dealing_direction: str, dealing_instructions: tuple, face_filter=valid_faces):
self.players = []
self.deck = Deck(face_filter)
- for _ in range(number_of_players):
- self.players.append(Player())
+ for player_idx in range(number_of_players):
+ new_player = Player()
+ new_player.set_player_id(player_idx)
+ self.players.append(new_player)
self.dealing_direction = dealing_direction
self.dealing_instructions = dealing_instructions
def get_players(self):
- from_player = random.randrange(len(self.players))
- players_row = []
- for player_idx in range(from_player, len(self.players)):
- players_row.append(self.players[player_idx])
- for player_idx in range(0, from_player):
- players_row.append(self.players[player_idx])
+ return self.players
- return players_row
-
def prepare_deck(self):
for player in self.players:
return_cards = player.get_cards()
- print("Player hand: ", player)
for card_idx in range(len(return_cards)):
self.deck.cards.append(player.cards[card_idx])
for _ in range(len(return_cards)):
player.cards.pop()
self.deck.shuffle()
self.deck.cut()
def get_player_index(self, player):
index = -1
for p in self.players:
index += 1
- if p == player:
+ if p.id == player.id:
return index
def deal(self, player):
player_start_index = self.get_player_index(player)
- if self.dealing_direction.startswith('l'):
+ if self.dealing_direction == 'ltr':
for cards_to_deal in self.dealing_instructions:
for player_idx in range(player_start_index, len(self.players)):
self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
del self.deck.cards[:cards_to_deal]
for player_idx in range(player_start_index):
self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
del self.deck.cards[:cards_to_deal]
else:
for cards_to_deal in self.dealing_instructions:
for player_idx in range(player_start_index, 0, -1):
self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
del self.deck.cards[:cards_to_deal]
for player_idx in range(len(self.players), player_start_index, -1):
self.players[player_idx].cards += self.deck.cards[:cards_to_deal]
del self.deck.cards[:cards_to_deal]
def get_deck(self):
return self.deck
class Belot(Game):
def __init__(self):
super().__init__(4, 'ltr', (2, 3, 3), ['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Poker(Game):
def __init__(self):
super().__init__(9, 'rtl', (1, 1, 1, 1, 1))