Решение на От ливадите до Лас Вегас (и назад) от Никола Михайлов

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

Към профила на Никола Михайлов

Резултати

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

Код

import random
from enum import Enum
SUITS = ['clubs', 'diamonds', 'hearts', 'spades']
FACES = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
DEAL_DIRECTIONS = {
'ltr' : 1,
'rtl' : -1
}
class GameType(tuple, Enum):
POKER = (9, 'rtl', (1, 1, 1, 1, 1), FACES)
BELOT = (4, 'ltr', (2, 3, 3), ['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Card:
def __init__(self, suit, face):
self.__suit = suit
self.__face = face
def get_suit(self):
return self.__suit
def get_face(self):
return self.__face
# For debugging purposes
def __repr__(self):
return f"{self.__face} of {self.__suit}"
class Deck:
def __init__(self, face_filter=FACES):
self.__cards = []
for suit in SUITS:
for face in face_filter:
self.__cards.append(Card(suit, face))
def cut(self):
number_to_cut = random.randint(1, len(self.__cards) - 1)
cut_pile = self.__cards[:number_to_cut]
left_pile = self.__cards[number_to_cut:]
self.__cards = left_pile + cut_pile
def shuffle(self):
random.shuffle(self.__cards)
def get_cards(self):
return self.__cards
# Top card has index (len(cards) - 1) or -1
# Bottom card has index 0
# Implemented it that way because of time complexity reasons
# with removing(popping) the top card of the deck -> O(1)
def get_top_card(self):
return self.__cards[-1]
def add_card(self, card):
self.__cards.append(card)
def pop_card(self):
self.__cards.pop()
def clear_deck(self):
self.__cards.clear()
class Player():
# Using Composition because the Player HAS Deck

Ок, самият аз не бях взел предвид тази възможност, а и не видях друг досега да го е направил. Напълно достатъчно е да дефинираш картите в list, вместо да използваш Deck, но идеята ми харесва - хитро е!

def __init__(self):
self.__deck = Deck([])
def add_card(self, card):
self.__deck.add_card(card)
def clear_cards(self):
self.__deck.clear_deck()
def get_cards(self):
return self.__deck.get_cards()
class Game:
# Added optional argument 'deck_cards' which allows us to create custom games.
# 'deck_cards' has default value of all the cards.
def __init__(self, number_of_players, dealing_direction, dealing_instructions, deck_cards=FACES):
self._number_of_players = number_of_players
self._dealing_direction = DEAL_DIRECTIONS[dealing_direction]
self._dealing_instructions = dealing_instructions
self._deck = Deck(deck_cards)
self.__create_players()
def __create_players(self):
self._players = []
for _ in range(self._number_of_players):
self._players.append(Player())
def get_players(self):
return self._players
def prepare_deck(self):
self.__collect_dealt_cards()
self._deck.shuffle()
self._deck.cut()
def __collect_dealt_cards(self):
for player in self._players:
player_deck = player.get_cards()
for card in player_deck:
self._deck.add_card(card)
player.clear_cards()
def deal(self, player):
player_index = self._players.index(player)
start_index = player_index
for instruction in self._dealing_instructions:
for num_player in range(self._number_of_players):
for num_card in range(instruction):
self._players[player_index].add_card(self._deck.get_top_card())
self._deck.pop_card()
player_index = (player_index + self._dealing_direction) % self._number_of_players
player_index = start_index
def get_deck(self):
return self._deck
class Belot(Game):
def __init__(self):
number_of_players, dealing_direction, dealing_instructions, card_faces = GameType.BELOT
super().__init__(number_of_players, dealing_direction, dealing_instructions, card_faces)
class Poker(Game):
def __init__(self):
number_of_players, dealing_direction, dealing_instructions, card_faces = GameType.POKER
super().__init__(number_of_players, dealing_direction, dealing_instructions, card_faces)

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

...............
----------------------------------------------------------------------
Ran 15 tests in 0.164s

OK

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

Никола обнови решението на 10.11.2022 13:26 (преди над 2 години)

+import random
+from enum import Enum
+
+suits = ['clubs', 'diamonds', 'hearts', 'spades']
+faces = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
+
+
+deal_direction = {
+ 'ltr' : 1,
+ 'rtl' : -1
+}
+
+
+class GameType(tuple, Enum):
+ POKER = (9, 'rtl', (1, 1, 1, 1, 1), faces)
+ BELOT = (4, 'ltr', (2, 3, 3), ['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
+
+
+class Card:
+ def __init__(self, suit, face):
+ self.suit = suit
+ self.face = face
+
+ def get_suit(self):
+ return self.suit
+
+ def get_face(self):
+ return self.face
+
+ # For debugging purposes
+ def __repr__(self):
+ return f"{self.face} of {self.suit}"
+
+
+class Deck:
+ def __init__(self, face_filter = faces):
+ self.cards = []
+ for suit in suits:
+ for face in face_filter:
+ self.cards.append(Card(suit, face))
+
+ def cut(self):
+ number_to_cut = random.randint(1, len(self.cards) - 1)
+ cut_pile = self.cards[:number_to_cut]
+ left_pile = self.cards[number_to_cut:]
+ self.cards = left_pile + cut_pile
+
+ def shuffle(self):
+ random.shuffle(self.cards)
+
+ def get_cards(self):
+ return self.cards
+
+ # Top card has index (len(cards) - 1) or -1
+ # Bottom card has index 0
+ # Implemented it that way because of time complexity reasons
+ # with removing(popping) the top card of the deck -> O(1)
+ def get_top_card(self):
+ return self.cards[-1]
+
+ def add_card(self, card):
+ self.cards.append(card)
+
+ def pop_card(self):
+ self.cards.pop()
+
+ def clear_deck(self):
+ self.cards.clear()
+
+
+class Player():
+ # Using Composition because the Player HAS Deck

Ок, самият аз не бях взел предвид тази възможност, а и не видях друг досега да го е направил. Напълно достатъчно е да дефинираш картите в list, вместо да използваш Deck, но идеята ми харесва - хитро е!

+ def __init__(self):
+ self.deck = Deck([])
+
+ def add_card(self, card):
+ self.deck.add_card(card)
+
+ def clear_cards(self):
+ self.deck.clear_deck()
+
+ def get_cards(self):
+ return self.deck.get_cards()
+
+
+class Game:
+ # Added optional argument 'deck_cards' which allows us to create custom games.
+ # 'deck_cards' has default value of all the cards.
+ def __init__(self, number_of_players, dealing_direction, dealing_instructions, deck_cards = faces):
+ self.number_of_players = number_of_players
+ self.dealing_direction = deal_direction[dealing_direction]
+ self.dealing_instructions = dealing_instructions
+ self.deck = Deck(deck_cards)
+ self.__create_players()
+
+ def __create_players(self):
+ self.players = []
+ for _ in range(self.number_of_players):
+ self.players.append(Player())
+
+ def get_players(self):
+ return self.players
+
+ def prepare_deck(self):
+ self.__collect_dealt_cards()
+ self.deck.shuffle()
+ self.deck.cut()
+
+ def __collect_dealt_cards(self):
+ for player in self.players:
+ player_deck = player.get_cards()
+ for card in player_deck:
+ self.deck.add_card(card)
+ player.clear_cards()
+
+ def deal(self, player):
+ player_index = self.players.index(player)
+ start_index = player_index
+
+ for num_instruction in range(len(self.dealing_instructions)):
+ instruction = self.dealing_instructions[num_instruction]
+ for num_player in range(self.number_of_players):
+ for num_card in range(instruction):
+ self.players[player_index].add_card(self.deck.get_top_card())
+ self.deck.pop_card()
+ player_index = (player_index + self.dealing_direction) % self.number_of_players
+ player_index = start_index
+
+ def get_deck(self):
+ return self.deck
+
+
+class Belot(Game):
+ def __init__(self):
+ number_of_players, dealing_direction, dealing_instructions, card_faces = GameType.BELOT
+ super().__init__(number_of_players, dealing_direction, dealing_instructions, card_faces)
+
+
+class Poker(Game):
+ def __init__(self):
+ number_of_players, dealing_direction, dealing_instructions, card_faces = GameType.POKER
+ super().__init__(number_of_players, dealing_direction, dealing_instructions, card_faces)

Заради чистия стил, използването на Enum, което елегантно се справя с проблема за различните тестета в двете игри, както и за идеята да инстанцираш Deck в Player, получаваш бонус точка.

Никола обнови решението на 12.11.2022 16:09 (преди над 2 години)

import random
from enum import Enum
-suits = ['clubs', 'diamonds', 'hearts', 'spades']
-faces = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
+SUITS = ['clubs', 'diamonds', 'hearts', 'spades']
+FACES = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
-deal_direction = {
+DEAL_DIRECTIONS = {
'ltr' : 1,
'rtl' : -1
}
class GameType(tuple, Enum):
- POKER = (9, 'rtl', (1, 1, 1, 1, 1), faces)
+ POKER = (9, 'rtl', (1, 1, 1, 1, 1), FACES)
BELOT = (4, 'ltr', (2, 3, 3), ['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Card:
def __init__(self, suit, face):
- 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
# For debugging purposes
def __repr__(self):
- return f"{self.face} of {self.suit}"
+ return f"{self.__face} of {self.__suit}"
class Deck:
- def __init__(self, face_filter = faces):
- self.cards = []
- for suit in suits:
+ def __init__(self, face_filter=FACES):
+ self.__cards = []
+ for suit in SUITS:
for face in face_filter:
- self.cards.append(Card(suit, face))
+ self.__cards.append(Card(suit, face))
def cut(self):
- number_to_cut = random.randint(1, len(self.cards) - 1)
- cut_pile = self.cards[:number_to_cut]
- left_pile = self.cards[number_to_cut:]
- self.cards = left_pile + cut_pile
+ number_to_cut = random.randint(1, len(self.__cards) - 1)
+ cut_pile = self.__cards[:number_to_cut]
+ left_pile = self.__cards[number_to_cut:]
+ self.__cards = left_pile + cut_pile
def shuffle(self):
- random.shuffle(self.cards)
+ random.shuffle(self.__cards)
def get_cards(self):
- return self.cards
+ return self.__cards
# Top card has index (len(cards) - 1) or -1
# Bottom card has index 0
# Implemented it that way because of time complexity reasons
# with removing(popping) the top card of the deck -> O(1)
def get_top_card(self):
- return self.cards[-1]
+ return self.__cards[-1]
def add_card(self, card):
- self.cards.append(card)
+ self.__cards.append(card)
def pop_card(self):
- self.cards.pop()
+ self.__cards.pop()
def clear_deck(self):
- self.cards.clear()
+ self.__cards.clear()
class Player():
# Using Composition because the Player HAS Deck
def __init__(self):
- self.deck = Deck([])
+ self.__deck = Deck([])
def add_card(self, card):
- self.deck.add_card(card)
+ self.__deck.add_card(card)
def clear_cards(self):
- self.deck.clear_deck()
+ self.__deck.clear_deck()
def get_cards(self):
- return self.deck.get_cards()
+ return self.__deck.get_cards()
class Game:
- # Added optional argument 'deck_cards' which allows us to create custom games.
+ # Added optional argument 'deck_cards' which allows us to create custom games.
# 'deck_cards' has default value of all the cards.
- def __init__(self, number_of_players, dealing_direction, dealing_instructions, deck_cards = faces):
- self.number_of_players = number_of_players
- self.dealing_direction = deal_direction[dealing_direction]
- self.dealing_instructions = dealing_instructions
- self.deck = Deck(deck_cards)
+ def __init__(self, number_of_players, dealing_direction, dealing_instructions, deck_cards=FACES):
+ self._number_of_players = number_of_players
+ self._dealing_direction = DEAL_DIRECTIONS[dealing_direction]
+ self._dealing_instructions = dealing_instructions
+ self._deck = Deck(deck_cards)
self.__create_players()
def __create_players(self):
- self.players = []
- for _ in range(self.number_of_players):
- self.players.append(Player())
+ self._players = []
+ for _ in range(self._number_of_players):
+ self._players.append(Player())
def get_players(self):
- return self.players
+ return self._players
def prepare_deck(self):
self.__collect_dealt_cards()
- self.deck.shuffle()
- self.deck.cut()
+ self._deck.shuffle()
+ self._deck.cut()
def __collect_dealt_cards(self):
- for player in self.players:
+ for player in self._players:
player_deck = player.get_cards()
for card in player_deck:
- self.deck.add_card(card)
+ self._deck.add_card(card)
player.clear_cards()
def deal(self, player):
- player_index = self.players.index(player)
+ player_index = self._players.index(player)
start_index = player_index
- for num_instruction in range(len(self.dealing_instructions)):
- instruction = self.dealing_instructions[num_instruction]
- for num_player in range(self.number_of_players):
+ for instruction in self._dealing_instructions:
+ for num_player in range(self._number_of_players):
for num_card in range(instruction):
- self.players[player_index].add_card(self.deck.get_top_card())
- self.deck.pop_card()
- player_index = (player_index + self.dealing_direction) % self.number_of_players
+ self._players[player_index].add_card(self._deck.get_top_card())
+ self._deck.pop_card()
+ player_index = (player_index + self._dealing_direction) % self._number_of_players
player_index = start_index
def get_deck(self):
- return self.deck
+ return self._deck
class Belot(Game):
def __init__(self):
number_of_players, dealing_direction, dealing_instructions, card_faces = GameType.BELOT
super().__init__(number_of_players, dealing_direction, dealing_instructions, card_faces)
class Poker(Game):
def __init__(self):
number_of_players, dealing_direction, dealing_instructions, card_faces = GameType.POKER
super().__init__(number_of_players, dealing_direction, dealing_instructions, card_faces)