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

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

Към профила на Георги Чобанов

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 15 успешни тест(а)
  • 0 неуспешни тест(а)

Код

import random
allowed_suits = ['clubs', 'diamonds', 'hearts', 'spades']
allowed_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
class CardException(Exception):
def __init__(self, message: str = "not a valid card UwU"):
super().__init__(message)
class GameException(Exception):
def __init__(self, message: str = "not a valid game UwU"):
super().__init__(message)
class Card:
def __init__(self, suit: str, face: str):
self.set_suit(suit)
self.set_face(face)
def set_suit(self, suit):
if suit in allowed_suits:
self._suit = suit
else:
raise CardException("not a valid suit UwU")
def set_face(self, face):
if face in allowed_faces:
self._face = face
else:
raise CardException("not a valid face UwU")
def get_suit(self):
return str(self._suit)
def get_face(self):
return str(self._face)
class CardsMixin:
def pop_cards(self, ammount: int):
cards_count = len(self._cards)
if cards_count == 0:
return []
popped_cards = self._cards[(cards_count - ammount): cards_count]
del self._cards[cards_count - ammount: cards_count]
return popped_cards
class Deck(CardsMixin):
def __init__(self, face_filter: list = allowed_faces):
self._cards = []
self._face_filter = face_filter
self._generate_deck()
def _generate_deck(self):
for suit in allowed_suits:
for face in allowed_faces:
if face in self._face_filter:
new_card = Card(suit, face)
self._cards.append(new_card)
def cut(self):
number_of_cards_to_cut = random.randint(1, len(self._cards))
self._cards = self._cards[number_of_cards_to_cut:] + self._cards[:number_of_cards_to_cut]
def shuffle(self):
random.shuffle(self._cards)
def get_cards(self):
return list(self._cards)
def is_empty(self):
return len(self._cards) == 0
def add_cards(self, new_cards):
self._cards += new_cards
class Player(CardsMixin):
def __init__(self):
self._cards = []
def get_cards(self):
return list(self._cards)
def cards_count(self):
return len(self._cards)
def add_cards(self, cards):
self._cards += cards
class Game:
def __init__(self,
number_of_players: int,
dealing_direction: str,
dealing_instructions: tuple,
face_filter: list = allowed_faces):
if dealing_direction not in ['rtl', 'ltr']:
raise GameException("Not a valid direction UwU, should be rtl or ltr")
self._num_of_players = number_of_players
self._dealing_direction = dealing_direction
self._dealing_instructions = dealing_instructions
self._players = [Player() for _ in range(self._num_of_players)]
self._deck = Deck(face_filter)
def get_deck(self):
return self._deck
def get_players(self):
starting_player = random.randint(0, len(self._players))
players = self._players[starting_player:] + self._players[:starting_player]
return players
def prepare_deck(self):
for player in self._players:
if player.cards_count != 0:
self._deck.add_cards(player.pop_cards(player.cards_count()))

Имайки предвид имплементацията, по-скоро бих дефинирал player.get_all_cards() или нещо такова. Ти винаги взимаш всички карти. Разбирам, че в бъдеще би ти било удобно да можеш да вземеш произволен брой карти, така че решението е субективно. Просто споменавам. Не е нужно да преправяш нищо.

self._deck.shuffle()
self._deck.cut()
def deal(self, player: Player):
player_count = len(self._players)
starting_player = self._players.index(player)
direction = 1 if self._dealing_direction == "ltr" else -1
for instruction in self._dealing_instructions:
for index in range(player_count):
if self._deck.is_empty():
break
actual_index = (starting_player + direction*index) % player_count
self._players[actual_index].add_cards(self._deck.pop_cards(instruction))
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))

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

...............
----------------------------------------------------------------------
Ran 15 tests in 0.160s

OK

История (4 версии и 9 коментара)

Георги обнови решението на 12.11.2022 19:43 (преди над 1 година)

+import random
+
+allowed_suits = ['clubs', 'diamonds', 'hearts', 'spades']
+allowed_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
+
+
+class CardException(Exception):
+
+ def __init__(self, message: str = "not a valid card UwU"):
+ super().__init__(message)
+
+
+class Card:
+
+ def __init__(self, suit: str, face: str):
+ self.set_suit(suit)
+ self.set_face(face)
+
+ def set_suit(self, suit):
+ if suit in allowed_suits:
+ self._suit = suit
+ else:
+ raise CardException("not a valid suit UwU")
+
+ def set_face(self, face):
+ if face in allowed_faces:
+ self._face = face
+ else:
+ raise CardException("not a valid face UwU")
+
+ def get_suit(self):
+ return str(self._suit)
+
+ def get_face(self):
+ return str(self._face)
+
+
+def pop_cards(cards, ammount: int):
+ cards_count = len(cards)
+ if cards_count == 0:
+ return []
+ popped_cards = cards[(cards_count - ammount): cards_count]
+ del cards[cards_count - ammount: cards_count]
+ return popped_cards
+
+
+class Deck:
+
+ def __init__(self, face_filter: list = allowed_faces):
+ self._cards = []
+ self._face_filter = face_filter
+ self._generate_deck()
+
+ def _generate_deck(self):
+ for suit in allowed_suits:
+ for face in allowed_faces:
+ if face in self._face_filter:
+ new_card = Card(suit, face)
+ self._cards.append(new_card)
+
+ def cut(self):
+ cards_to_cut = random.randint(1, len(self._cards))
+ cut_cards = self._cards[:cards_to_cut]
+ del self._cards[:cards_to_cut]
+ self._cards += cut_cards
+
+ def shuffle(self):
+ random.shuffle(self._cards)
+
+ def get_cards(self):
+ return list(self._cards)
+
+ def is_empty(self):
+ return len(self._cards) == 0
+
+ def pop_cards(self, ammount):
+ return pop_cards(self._cards, ammount)
+
+ def add_cards(self, new_cards):
+ self._cards += new_cards
+
+
+class Player:
+
+ def __init__(self):
+ self._cards = []
+
+ def get_cards(self):
+ return list(self._cards)
+
+ def cards_count(self):
+ return len(self._cards)
+
+ def add_cards(self, cards):
+ self._cards += cards
+
+ def pop_cards(self, ammount):
+ return pop_cards(self._cards, ammount)
+
+
+class Game:
+
+ def __init__(self,
+ number_of_players: int,
+ dealing_direction: str,
+ dealing_instructions: tuple,
+ face_filter: list = allowed_faces):
+ if dealing_direction not in ['rtl', 'ltr']:
+ print('invalid dealing direction, it should be rtl or ltr')
+ self._num_of_players = number_of_players
+ self._dealing_direction = dealing_direction
+ self._dealing_instructions = dealing_instructions
+ self._players = [Player() for _ in range(self._num_of_players)]
+ self._deck = Deck(face_filter)
+
+ def get_deck(self):
+ return self._deck
+
+ def get_players(self):
+ player_count = len(self._players)
+ starting_player = random.randint(0, player_count - 1)
+ players = []
+ for index in range(starting_player, starting_player + player_count):
+ players.append(self._players[index % player_count])
+ return players
+
+ def prepare_deck(self):
+ for player in self._players:
+ if player.cards_count != 0:
+ self._deck.add_cards(player.pop_cards(player.cards_count()))
+ self._deck.shuffle()
+ self._deck.cut()
+
+ def deal(self, player: Player):
+ player_count = len(self._players)
+ starting_player = self._players.index(player)
+ direction = 1 if self._dealing_direction == "ltr" else -1
+ for instruction in self._dealing_instructions:
+ for index in range(player_count):
+ if self._deck.is_empty():
+ break
+ self._players[(starting_player + direction*index) % player_count].add_cards(self._deck.pop_cards(instruction))
+
+
+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))

Георги обнови решението на 12.11.2022 19:47 (преди над 1 година)

import random
allowed_suits = ['clubs', 'diamonds', 'hearts', 'spades']
allowed_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
class CardException(Exception):
def __init__(self, message: str = "not a valid card UwU"):
super().__init__(message)
+class GameException(Exception):
+
+ def __init__(self, message: str = "not a valid game UwU"):
+ super().__init__(message)
+
+
class Card:
def __init__(self, suit: str, face: str):
self.set_suit(suit)
self.set_face(face)
def set_suit(self, suit):
if suit in allowed_suits:
self._suit = suit
else:
raise CardException("not a valid suit UwU")
def set_face(self, face):
if face in allowed_faces:
self._face = face
else:
raise CardException("not a valid face UwU")
def get_suit(self):
return str(self._suit)
def get_face(self):
return str(self._face)
def pop_cards(cards, ammount: int):

Няма проблем с текущата имплементация, но тъй като това е по-скоро свойство на някои класове, защо не опиташ да го дефинираш като миксин?

cards_count = len(cards)
if cards_count == 0:
return []
popped_cards = cards[(cards_count - ammount): cards_count]
del cards[cards_count - ammount: cards_count]
return popped_cards
class Deck:
def __init__(self, face_filter: list = allowed_faces):
self._cards = []
self._face_filter = face_filter
self._generate_deck()
def _generate_deck(self):
for suit in allowed_suits:
for face in allowed_faces:
if face in self._face_filter:
new_card = Card(suit, face)
self._cards.append(new_card)
def cut(self):
cards_to_cut = random.randint(1, len(self._cards))
cut_cards = self._cards[:cards_to_cut]
del self._cards[:cards_to_cut]
self._cards += cut_cards
def shuffle(self):
random.shuffle(self._cards)
def get_cards(self):
return list(self._cards)
def is_empty(self):
return len(self._cards) == 0
def pop_cards(self, ammount):
return pop_cards(self._cards, ammount)
def add_cards(self, new_cards):
self._cards += new_cards
class Player:
def __init__(self):
self._cards = []
def get_cards(self):
return list(self._cards)
def cards_count(self):
return len(self._cards)
def add_cards(self, cards):
self._cards += cards
def pop_cards(self, ammount):
return pop_cards(self._cards, ammount)
class Game:
def __init__(self,
number_of_players: int,
dealing_direction: str,
dealing_instructions: tuple,
face_filter: list = allowed_faces):
if dealing_direction not in ['rtl', 'ltr']:
- print('invalid dealing direction, it should be rtl or ltr')
+ raise GameException("Not a valid direction UwU, should be rtl or ltr")
self._num_of_players = number_of_players
self._dealing_direction = dealing_direction
self._dealing_instructions = dealing_instructions
self._players = [Player() for _ in range(self._num_of_players)]
self._deck = Deck(face_filter)
def get_deck(self):
return self._deck
def get_players(self):
player_count = len(self._players)

Тук можеш да използваш подобен похват на този, който си използвал за цепенете на тестето. Не е проблем да го оставиш и така, просто ще си спестиш няколко реда код.

starting_player = random.randint(0, player_count - 1)
players = []
for index in range(starting_player, starting_player + player_count):
players.append(self._players[index % player_count])
return players
def prepare_deck(self):
for player in self._players:
if player.cards_count != 0:
self._deck.add_cards(player.pop_cards(player.cards_count()))

Имайки предвид имплементацията, по-скоро бих дефинирал player.get_all_cards() или нещо такова. Ти винаги взимаш всички карти. Разбирам, че в бъдеще би ти било удобно да можеш да вземеш произволен брой карти, така че решението е субективно. Просто споменавам. Не е нужно да преправяш нищо.

self._deck.shuffle()
self._deck.cut()
def deal(self, player: Player):
player_count = len(self._players)
starting_player = self._players.index(player)
direction = 1 if self._dealing_direction == "ltr" else -1
for instruction in self._dealing_instructions:
for index in range(player_count):
if self._deck.is_empty():
break
self._players[(starting_player + direction*index) % player_count].add_cards(self._deck.pop_cards(instruction))

Ако направиш една временна променлива за играча на отделен ред, ще стане малко по-лесно за четене. Това е просто препоръка. Няма нужда да преправяш.

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))

Решението ти е хубаво и методично. Просто оставих някои неща, които си струва да се вземат предвид, но няма нищо, за което наистина да кажа, че е направено зле.

Георги обнови решението на 14.11.2022 16:51 (преди над 1 година)

import random
allowed_suits = ['clubs', 'diamonds', 'hearts', 'spades']
allowed_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
class CardException(Exception):
def __init__(self, message: str = "not a valid card UwU"):
super().__init__(message)
class GameException(Exception):
def __init__(self, message: str = "not a valid game UwU"):
super().__init__(message)
class Card:
def __init__(self, suit: str, face: str):
self.set_suit(suit)
self.set_face(face)
def set_suit(self, suit):
if suit in allowed_suits:
self._suit = suit
else:
raise CardException("not a valid suit UwU")
def set_face(self, face):
if face in allowed_faces:
self._face = face
else:
raise CardException("not a valid face UwU")
def get_suit(self):
return str(self._suit)
def get_face(self):
return str(self._face)
def pop_cards(cards, ammount: int):
cards_count = len(cards)
if cards_count == 0:
- return []
+ return []
popped_cards = cards[(cards_count - ammount): cards_count]
del cards[cards_count - ammount: cards_count]
return popped_cards
-class Deck:
+class Deck():
def __init__(self, face_filter: list = allowed_faces):
self._cards = []
self._face_filter = face_filter
self._generate_deck()
def _generate_deck(self):
for suit in allowed_suits:
for face in allowed_faces:
if face in self._face_filter:
new_card = Card(suit, face)
self._cards.append(new_card)
def cut(self):
- cards_to_cut = random.randint(1, len(self._cards))
- cut_cards = self._cards[:cards_to_cut]
- del self._cards[:cards_to_cut]
- self._cards += cut_cards
+ number_of_cards_to_cut = random.randint(1, len(self._cards))
+ self._cards = self._cards[number_of_cards_to_cut:] + self._cards[:number_of_cards_to_cut]
def shuffle(self):
random.shuffle(self._cards)
def get_cards(self):
return list(self._cards)
def is_empty(self):
return len(self._cards) == 0
def pop_cards(self, ammount):
return pop_cards(self._cards, ammount)
def add_cards(self, new_cards):
self._cards += new_cards
-class Player:
+class Player():
def __init__(self):
self._cards = []
def get_cards(self):
return list(self._cards)
def cards_count(self):
return len(self._cards)
def add_cards(self, cards):
self._cards += cards
def pop_cards(self, ammount):
return pop_cards(self._cards, ammount)
class Game:
def __init__(self,
number_of_players: int,
dealing_direction: str,
dealing_instructions: tuple,
face_filter: list = allowed_faces):
if dealing_direction not in ['rtl', 'ltr']:
raise GameException("Not a valid direction UwU, should be rtl or ltr")
self._num_of_players = number_of_players
self._dealing_direction = dealing_direction
self._dealing_instructions = dealing_instructions
self._players = [Player() for _ in range(self._num_of_players)]
self._deck = Deck(face_filter)
def get_deck(self):
return self._deck
def get_players(self):
- player_count = len(self._players)
- starting_player = random.randint(0, player_count - 1)
- players = []
- for index in range(starting_player, starting_player + player_count):
- players.append(self._players[index % player_count])
+ starting_player = random.randint(0, len(self._players))
+ players = self._players[starting_player:] + self._players[:starting_player]
return players
def prepare_deck(self):
for player in self._players:
if player.cards_count != 0:
self._deck.add_cards(player.pop_cards(player.cards_count()))
self._deck.shuffle()
self._deck.cut()
def deal(self, player: Player):
player_count = len(self._players)
starting_player = self._players.index(player)
direction = 1 if self._dealing_direction == "ltr" else -1
for instruction in self._dealing_instructions:
for index in range(player_count):
if self._deck.is_empty():
break
- self._players[(starting_player + direction*index) % player_count].add_cards(self._deck.pop_cards(instruction))
+ actual_index = (starting_player + direction*index) % player_count
+ self._players[actual_index].add_cards(self._deck.pop_cards(instruction))
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))
+

Георги обнови решението на 14.11.2022 17:05 (преди над 1 година)

import random
allowed_suits = ['clubs', 'diamonds', 'hearts', 'spades']
allowed_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
class CardException(Exception):
def __init__(self, message: str = "not a valid card UwU"):
super().__init__(message)
class GameException(Exception):
def __init__(self, message: str = "not a valid game UwU"):
super().__init__(message)
class Card:
def __init__(self, suit: str, face: str):
self.set_suit(suit)
self.set_face(face)
def set_suit(self, suit):
if suit in allowed_suits:
self._suit = suit
else:
raise CardException("not a valid suit UwU")
def set_face(self, face):
if face in allowed_faces:
self._face = face
else:
raise CardException("not a valid face UwU")
def get_suit(self):
return str(self._suit)
def get_face(self):
return str(self._face)
+class CardsMixin:
+
+ def pop_cards(self, ammount: int):
+ cards_count = len(self._cards)
+ if cards_count == 0:
+ return []
+ popped_cards = self._cards[(cards_count - ammount): cards_count]
+ del self._cards[cards_count - ammount: cards_count]
+ return popped_cards
-def pop_cards(cards, ammount: int):
- cards_count = len(cards)
- if cards_count == 0:
- return []
- popped_cards = cards[(cards_count - ammount): cards_count]
- del cards[cards_count - ammount: cards_count]
- return popped_cards
+class Deck(CardsMixin):
-class Deck():
-
def __init__(self, face_filter: list = allowed_faces):
self._cards = []
self._face_filter = face_filter
self._generate_deck()
def _generate_deck(self):
for suit in allowed_suits:
for face in allowed_faces:
if face in self._face_filter:
new_card = Card(suit, face)
self._cards.append(new_card)
def cut(self):
number_of_cards_to_cut = random.randint(1, len(self._cards))
self._cards = self._cards[number_of_cards_to_cut:] + self._cards[:number_of_cards_to_cut]
def shuffle(self):
random.shuffle(self._cards)
def get_cards(self):
return list(self._cards)
def is_empty(self):
return len(self._cards) == 0
- def pop_cards(self, ammount):
- return pop_cards(self._cards, ammount)
-
def add_cards(self, new_cards):
self._cards += new_cards
-class Player():
+class Player(CardsMixin):
def __init__(self):
self._cards = []
def get_cards(self):
return list(self._cards)
def cards_count(self):
return len(self._cards)
def add_cards(self, cards):
self._cards += cards
- def pop_cards(self, ammount):
- return pop_cards(self._cards, ammount)
-
class Game:
def __init__(self,
number_of_players: int,
dealing_direction: str,
dealing_instructions: tuple,
face_filter: list = allowed_faces):
if dealing_direction not in ['rtl', 'ltr']:
raise GameException("Not a valid direction UwU, should be rtl or ltr")
self._num_of_players = number_of_players
self._dealing_direction = dealing_direction
self._dealing_instructions = dealing_instructions
self._players = [Player() for _ in range(self._num_of_players)]
self._deck = Deck(face_filter)
def get_deck(self):
return self._deck
def get_players(self):
starting_player = random.randint(0, len(self._players))
players = self._players[starting_player:] + self._players[:starting_player]
return players
def prepare_deck(self):
for player in self._players:
if player.cards_count != 0:
self._deck.add_cards(player.pop_cards(player.cards_count()))
self._deck.shuffle()
self._deck.cut()
def deal(self, player: Player):
player_count = len(self._players)
starting_player = self._players.index(player)
direction = 1 if self._dealing_direction == "ltr" else -1
for instruction in self._dealing_instructions:
for index in range(player_count):
if self._deck.is_empty():
break
actual_index = (starting_player + direction*index) % player_count
self._players[actual_index].add_cards(self._deck.pop_cards(instruction))
+
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))
-
+