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

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

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

Резултати

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

Код

import random
SUITS = [
'spades', 'hearts',
'diamonds', 'clubs',
]
FACES = ['2', '3', '4', '5', '6', '7', '8',
'9', '10', 'J', 'Q', 'K', 'A']
class Card:
"""
A class to represent a Card in a card game.
Attributes
----------
suit : str
Represents the suit of a card: ('spades', 'hearts', 'diamonds', 'clubs').
face : str
Represents the face of a card: ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'].
"""
def __init__(self, suit, face):
"""
Constructs all the necessary prerequisites for the Card object.
Parameters
----------
suit : str
Represents the suit of a card: ('spades', 'hearts', 'diamonds', 'clubs').
face : str
Represents the face of a card: ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'].
"""
self.suit = suit
self.face = face
def get_suit(self):
"""Returns the suit(str) of the Card."""
return self.suit
def get_face(self):
"""Returns the face(str) of the Card."""
return self.face
class Deck:
"""
A class to represent a Deck in a card game.
Attributes
----------
__cards : list of Card
List of cards in the current Deck.
"""
def __init__(self, face_filter=FACES):
"""
Constructs all the necessary prerequisites for the Deck object.
Parameters
----------
face_filter : list of str (optional)
Specifies the eligible faces in the current deck and adds a card from each suit of those faces.
Fills the list with all standard 52 cards if no face_filter argument is supplied.
"""
self.__cards = []

Използването на две долни черти тук според мен е излишно. Една стига. Не мисля, че би искал да си толкова стриктен в това дали някой пипа в този лист. НО, това не е никакъв проблем. така си решил - така си направил. Тук мисля, че мнението ми е по-скоро субективно.

for face in face_filter:
if face.upper() in FACES:
for suit in SUITS:
self.__cards.append(Card(suit, face))
def cut(self):
"""Performs a cut action on the Deck of Cards by placing random number of Card elements from the top(end of the list)
to the bottom(beginning of the list) of the deck."""
random_index = random.randrange(1, len(self.__cards) - 1)
self.__cards = self.__cards[-random_index:] + self.__cards[:-random_index]
def shuffle(self):
"""Shuffles the order of the Card elements in __cards."""
random.shuffle(self.__cards)
def get_cards(self):
"""Returns a list of Card elements in this Deck."""
return self.__cards
# Extra functions
def add_cards(self, cards):
"""Adds Card elements to the end of the list of cards in this Deck."""
self.__cards.extend(cards)
def deal_top_card(self):
"""Removes and returns the top card in this Deck."""
return self.__cards.pop()
def is_empty(self):
"""Returns True if there are no Card elements in this Deck, otherwise - False."""
return len(self.__cards) == 0
class Player:
"""
A class to represent a Player in a card game.
Attributes
----------
__cards : list of Card
List of cards representing the cards in this Player's hand.
"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Player object."""
self.__cards = []
def get_cards(self):
"""Returns the list of Card elements that are in this Player's hand."""
return self.__cards
# Extra functions
def add_card(self, card):
"""Adds a Card element to the list cards(__cards) that are in this Player's hand."""
self.__cards.append(card)
def return_cards(self):
"""Removes all Card elements from this Player's hand(__cards) and returns them."""
hand = self.__cards
self.__cards = []
return hand
class Game:
"""
A class to represent a Game of cards.
Attributes
----------
number_of_players : int
Represents the number of players that this game will start with when instantiated.
dealing_direction : str
Represents the direction of card dealing: 'ltr'=left-to-right | 'rtl'=right-to-left.
dealing_instructions : tuple of int
Represents instructions of how much cards from the top of the deck should be dealt to each player on each dealing cycle.
__players : list of Player
List of players assigned to the current game.
__deck : Deck
Deck object that represents the deck of cards assigned to the current game.
"""
def __init__(self, number_of_players, dealing_direction, dealing_instructions):
"""
Constructs all the necessary prerequisites for the Game object.
Parameters
----------
number_of_players : int
Represents the number of players that this game will start with when instantiated.
dealing_direction : str
Represents the direction of card dealing: 'ltr'=left-to-right | 'rtl'=right-to-left.
dealing_instructions : tuple of int
Represents instructions of how much cards from the top of the deck should be dealt to each player on each dealing cycle.
"""
self.__players = []
self.__deck = Deck()
self.number_of_players = number_of_players
self.dealing_direction = dealing_direction
self.dealing_instructions = dealing_instructions
self.__add_players(self.number_of_players)
def get_players(self):
"""Returns list of all Players in this Game starting from a random Player and ordered from left to right"""
if self.__players:
random_index = random.randrange(len(self.__players))
self.__players = self.__players[random_index:] + self.__players[:random_index]
return self.__players
def prepare_deck(self):
"""Collects all cards from players (for each Player in this Game) back in the deck,
shuffles the deck and cuts it"""
for player in self.__players:
self.__deck.add_cards(player.return_cards())
self.__deck.shuffle()
self.__deck.cut()
def deal(self, player):
"""Deals cards based on this Game's 'dealing_direction'(str) and 'dealing_instruction'(tuple)
starting from the specified 'player'(Player) until there are no cards left in the Deck."""
if player in self.__players:
i = self.__players.index(player)
step = -1 if self.dealing_direction == 'rtl' else 1
order_of_dealing = self.__players[i::step] + self.__players[:i:step]
for instruction in self.dealing_instructions:
for current_player in order_of_dealing:
for _ in range(instruction):
if self.__deck.is_empty():
break
current_player.add_card(self.__deck.deal_top_card())
def get_deck(self):
"""Returns the Deck(list of Card elements) for this Game"""
return self.__deck
# Extra functions
def _set_deck_filter(self, filter):
"""Takes a list of strings 'filter' and creates a new Deck for this Game based on that filter"""
self.__deck = Deck(filter)
def __add_players(self, num):
"""Adds 'num'(int) number of new Players to the current Game"""
self.__players.extend(Player() for _ in range(num))
class Belot(Game):
"""A class to represent a Belot Game"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Belot object"""
super().__init__(4, 'ltr', (2, 3, 3))
self._set_deck_filter(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Poker(Game):
"""A class to represent a Poker Game"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Poker object"""
super().__init__(9, 'rtl', (1, 1, 1, 1, 1)) # no filter = all cards

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

...............
----------------------------------------------------------------------
Ran 15 tests in 0.162s

OK

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

Александър обнови решението на 04.11.2022 20:47 (преди над 1 година)

+import random
+
+SUITS = [
+ 'spades', 'hearts',
+ 'diamonds', 'clubs',
+]
+
+FACES = ['2', '3', '4', '5', '6', '7', '8',
+ '9', '10', 'J', 'Q', 'K', 'A']
+
+
+class Card:
+ def __init__(self, suit, face):
+ # Предполагам, че валидността на входните данни е гарантирана, "but just in case it's not"
+ if (suit not in SUITS) or (face not in FACES):
+ raise ValueError("Invalid suit or/and face arguments")
+ 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=FACES):
+ self.__cards = []
+ for face in face_filter:
+ if face.upper() in FACES:
+ for suit in SUITS:
+ self.__cards.append(Card(suit, face))
+
+ def cut(self):
+ # Предполагам, че с 'една или повече' се има предвид, че се избира произволно от 1 до (length - 1)
+ r = random.randrange(1, len(self.__cards) - 1)
+ # Приемам, че картите най-отгоре на тестето са последните в списъка
+ # с други думи, ако имаме списък [1,2,3,4,5] и r=2, cut би привел списъка във вид [4,5,1,2,3]
+ self.__cards = self.__cards[-r:] + self.__cards[:-r]
+
+ def shuffle(self):
+ random.shuffle(self.__cards)
+
+ def get_cards(self):
+ return self.__cards
+
+ # Extra functions
+ def add_cards(self, cards):
+ for c in cards:
+ self.__cards.append(c)
+
+ def deal_top_card(self):
+ return self.__cards.pop()
+
+ def get_size(self):
+ return len(self.__cards)
+
+
+class Player:
+ def __init__(self):
+ self.__cards = []
+
+ def get_cards(self):
+ return self.__cards
+
+ # Extra functions
+ def add_card(self, card):
+ self.__cards.append(card)
+
+ def return_cards(self):
+ hand = self.__cards
+ self.__cards = []
+ return hand
+
+
+class Game:
+ def __init__(self, number_of_players, dealing_direction, dealing_instructions):
+ self.__players = []
+ self.__deck = Deck()
+ self.number_of_players = number_of_players
+ self.dealing_direction = dealing_direction
+ self.dealing_instructions = dealing_instructions
+ self.__add_players(self.number_of_players)
+
+ def get_players(self):
+ # Предполагам, че редът в __players трябва да си остане същият, а само връщаме подредба от произволен индекс надясно
+ if self.__players: # randrange се оплаква при 'empty range'
+ r = random.randrange(len(self.__players))
+ return self.__players[r:] + self.__players[:r]
+ else:
+ return self.__players
+
+ def prepare_deck(self):
+ # Tук може просто да се инстанцира deck наново вместо да връщам всяка карта обратно в тестето,
+ # и след това да затрия 'ръката' на всеки играч, но смятам, че така е по-автентично спрямо условието:
+ for p in self.__players:
+ self.__deck.add_cards(p.return_cards())
+ self.__deck.shuffle()
+ self.__deck.cut()
+
+ def deal(self, player):
+ if player in self.__players:
+ i = self.__players.index(player)
+
+ if self.dealing_direction == 'rtl':
+ self.__players = self.__players[i::-1] + self.__players[:i:-1]
+ else:
+ self.__players = self.__players[i:] + self.__players[:i]
+
+ # Предполагам, че ако dealing_instructions е tuple с един елемент,
+ # ще се подава във формат (x,) и по този начин не трябва да се подсигурявам за int
+ for instruction in self.dealing_instructions:
+ for _ in range(instruction):
+ for p in self.__players:
+ if self.__deck.get_size() == 0:
+ break
+ p.add_card(self.__deck.deal_top_card())
+
+ def get_deck(self):
+ return self.__deck
+
+ # Extra functions
+ def _set_deck_filter(self, filter):
+ self.__deck = Deck(filter)
+
+ def __add_players(self, n):
+ for _ in range(n):
+ if len(self.__players) < self.number_of_players:
+ self.__players.append(Player())
+
+
+class Belot(Game):
+ def __init__(self):
+ super().__init__(4, 'ltr', (2, 3, 3))
+ # Може би super()._set_deck_filter() е по-коректно, ако имаме multi-inheritance?
+ self._set_deck_filter(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
+
+
+class Poker(Game):
+ def __init__(self):
+ super().__init__(9, 'rtl', (1, 1, 1, 1, 1)) # no filter = all cards

Александър обнови решението на 05.11.2022 08:19 (преди над 1 година)

import random
SUITS = [
'spades', 'hearts',
'diamonds', 'clubs',
]
FACES = ['2', '3', '4', '5', '6', '7', '8',
'9', '10', 'J', 'Q', 'K', 'A']
class Card:
def __init__(self, suit, face):
- # Предполагам, че валидността на входните данни е гарантирана, "but just in case it's not"
- if (suit not in SUITS) or (face not in FACES):
- raise ValueError("Invalid suit or/and face arguments")
+ # Предполагам, че валидността на входните данни е гарантирана
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=FACES):
self.__cards = []

Използването на две долни черти тук според мен е излишно. Една стига. Не мисля, че би искал да си толкова стриктен в това дали някой пипа в този лист. НО, това не е никакъв проблем. така си решил - така си направил. Тук мисля, че мнението ми е по-скоро субективно.

for face in face_filter:
if face.upper() in FACES:
for suit in SUITS:
self.__cards.append(Card(suit, face))
def cut(self):
# Предполагам, че с 'една или повече' се има предвид, че се избира произволно от 1 до (length - 1)
r = random.randrange(1, len(self.__cards) - 1)
# Приемам, че картите най-отгоре на тестето са последните в списъка
# с други думи, ако имаме списък [1,2,3,4,5] и r=2, cut би привел списъка във вид [4,5,1,2,3]
self.__cards = self.__cards[-r:] + self.__cards[:-r]

Реално погледнато този минус преди r е излишен. Все пак работиш със случайно число - слагайки минус просто променяш случайното число, но то пак си е случайно :)

def shuffle(self):
random.shuffle(self.__cards)
def get_cards(self):
return self.__cards
# Extra functions
def add_cards(self, cards):
for c in cards:
self.__cards.append(c)
def deal_top_card(self):
return self.__cards.pop()
def get_size(self):
return len(self.__cards)
class Player:
def __init__(self):
self.__cards = []
def get_cards(self):
return self.__cards
# Extra functions
def add_card(self, card):
self.__cards.append(card)
def return_cards(self):
hand = self.__cards
self.__cards = []
return hand
class Game:
def __init__(self, number_of_players, dealing_direction, dealing_instructions):
self.__players = []
self.__deck = Deck()
self.number_of_players = number_of_players
self.dealing_direction = dealing_direction
self.dealing_instructions = dealing_instructions
self.__add_players(self.number_of_players)
def get_players(self):
# Предполагам, че редът в __players трябва да си остане същият, а само връщаме подредба от произволен индекс надясно

Да. Дори бих казал, че слуачйният индекс е излишен. Ако просто върнеш self.__players ще опростиш класа си, а реално този случай е частен случай на твоя, така че не внасяш никаква промяна. От функционална гледна точка, смятам, че дори е по-логично всеки път да връщаш един и същи ред.

if self.__players: # randrange се оплаква при 'empty range'
r = random.randrange(len(self.__players))
return self.__players[r:] + self.__players[:r]
else:
return self.__players
def prepare_deck(self):
# Tук може просто да се инстанцира deck наново вместо да връщам всяка карта обратно в тестето,
# и след това да затрия 'ръката' на всеки играч, но смятам, че така е по-автентично спрямо условието:
for p in self.__players:
self.__deck.add_cards(p.return_cards())
self.__deck.shuffle()
self.__deck.cut()
def deal(self, player):
if player in self.__players:
i = self.__players.index(player)
if self.dealing_direction == 'rtl':

С този if бих определил посоката, т.е. стъпката 1/-1 след което просто да използвам посоката в цикъла на ред 112.

if self.dealing_direction == 'rtl':
    step = -1
else:
    step = 1
# Помисли дори как можеш да опростиш горния израз :)

...

for p in self__players[::step]:
  ...
self.__players = self.__players[i::-1] + self.__players[:i:-1]
else:
self.__players = self.__players[i:] + self.__players[:i]
# Предполагам, че ако dealing_instructions е tuple с един елемент,
# ще се подава във формат (x,) и по този начин не трябва да се подсигурявам за int
for instruction in self.dealing_instructions:
- for _ in range(instruction):
- for p in self.__players:
+ for p in self.__players:
+ for _ in range(instruction):
if self.__deck.get_size() == 0:
break
p.add_card(self.__deck.deal_top_card())
def get_deck(self):
return self.__deck
# Extra functions
def _set_deck_filter(self, filter):
self.__deck = Deck(filter)
def __add_players(self, n):
for _ in range(n):
if len(self.__players) < self.number_of_players:

Тази проверка е излишна. Щом си казал, че методът ти е private, ти си в пълен контрол на инпута. В случая подаваш self.number_of_players като инпут. Не е нужно да проверяваш дали е по-малко, или не.

self.__players.append(Player())
class Belot(Game):
def __init__(self):
super().__init__(4, 'ltr', (2, 3, 3))
- # Може би super()._set_deck_filter() е по-коректно, ако имаме multi-inheritance?
self._set_deck_filter(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Poker(Game):
def __init__(self):
super().__init__(9, 'rtl', (1, 1, 1, 1, 1)) # no filter = all cards

Добро решение!

Генерално бих те посъветвал да украсиш с docstring-ове. Казахме, че не държим на това, но това е единственото, което ми липсва. Харесва ми, че си слагал коментари. Всички са напълно намясто и си направил правилните предположения.

Александър обнови решението на 14.11.2022 14:07 (преди над 1 година)

import random
SUITS = [
'spades', 'hearts',
'diamonds', 'clubs',
]
FACES = ['2', '3', '4', '5', '6', '7', '8',
'9', '10', 'J', 'Q', 'K', 'A']
class Card:
+ """
+ A class to represent a Card in a card game.
+
+ Attributes
+ ----------
+ suit : str
+ Represents the suit of a card: ('spades', 'hearts', 'diamonds', 'clubs').
+ face : str
+ Represents the face of a card: ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'].
+ """
+
def __init__(self, suit, face):
- # Предполагам, че валидността на входните данни е гарантирана
+ """
+ Constructs all the necessary prerequisites for the Card object.
+
+ Parameters
+ ----------
+ suit : str
+ Represents the suit of a card: ('spades', 'hearts', 'diamonds', 'clubs').
+ face : str
+ Represents the face of a card: ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'].
+ """
self.suit = suit
self.face = face
def get_suit(self):
+ """Returns the suit(str) of the Card."""
return self.suit
def get_face(self):
+ """Returns the face(str) of the Card."""
return self.face
class Deck:
+ """
+ A class to represent a Deck in a card game.
+
+ Attributes
+ ----------
+ __cards : list of Card
+ List of cards in the current Deck.
+ """
+
def __init__(self, face_filter=FACES):
+ """
+ Constructs all the necessary prerequisites for the Deck object.
+
+ Parameters
+ ----------
+ face_filter : list of str (optional)
+ Specifies the eligible faces in the current deck and adds a card from each suit of those faces.
+ Fills the list with all standard 52 cards if no face_filter argument is supplied.
+ """
self.__cards = []
for face in face_filter:
if face.upper() in FACES:
for suit in SUITS:
self.__cards.append(Card(suit, face))
def cut(self):
- # Предполагам, че с 'една или повече' се има предвид, че се избира произволно от 1 до (length - 1)
+ """Performs a cut action on the Deck of Cards by placing random number of Card elements from the top(end of the list)
+ to the bottom(beginning of the list) of the deck."""
r = random.randrange(1, len(self.__cards) - 1)
- # Приемам, че картите най-отгоре на тестето са последните в списъка
- # с други думи, ако имаме списък [1,2,3,4,5] и r=2, cut би привел списъка във вид [4,5,1,2,3]
self.__cards = self.__cards[-r:] + self.__cards[:-r]
def shuffle(self):
+ """Shuffles the order of the Card elements in __cards."""
random.shuffle(self.__cards)
def get_cards(self):
+ """Returns a list of Card elements in this Deck."""
return self.__cards
# Extra functions
def add_cards(self, cards):
- for c in cards:
- self.__cards.append(c)
+ """Adds Card elements to the end of the list of cards in this Deck."""
+ self.__cards.extend(cards)
def deal_top_card(self):
+ """Removes and returns the top card in this Deck."""
return self.__cards.pop()
- def get_size(self):
- return len(self.__cards)
+ def is_empty(self):
+ """Returns True if there are no Card elements in this Deck, otherwise - False."""
+ return len(self.__cards) == 0
class Player:
+ """
+ A class to represent a Player in a card game.
+
+ Attributes
+ ----------
+ __cards : list of Card
+ List of cards representing the cards in this Player's hand.
+ """
+
def __init__(self):
+ """Constructs all the necessary prerequisites for the Player object."""
self.__cards = []
def get_cards(self):
+ """Returns the list of Card elements that are in this Player's hand."""
return self.__cards
# Extra functions
def add_card(self, card):
+ """Adds a Card element to the list cards(__cards) that are in this Player's hand."""
self.__cards.append(card)
def return_cards(self):
+ """Removes all Card elements from this Player's hand(__cards) and returns them."""
hand = self.__cards
self.__cards = []
return hand
class Game:
+ """
+ A class to represent a Game of cards.
+
+ Attributes
+ ----------
+ number_of_players : int
+ Represents the number of players that this game will start with when instantiated.
+ dealing_direction : str
+ Represents the direction of card dealing: 'ltr'=left-to-right | 'rtl'=right-to-left.
+ dealing_instructions : tuple of int
+ Represents instructions of how much cards from the top of the deck should be dealt to each player on each dealing cycle.
+ __players : list of Player
+ List of players assigned to the current game.
+ __deck : Deck
+ Deck object that represents the deck of cards assigned to the current game.
+ """
+
def __init__(self, number_of_players, dealing_direction, dealing_instructions):
+ """
+ Constructs all the necessary prerequisites for the Game object.
+
+ Parameters
+ ----------
+ number_of_players : int
+ Represents the number of players that this game will start with when instantiated.
+ dealing_direction : str
+ Represents the direction of card dealing: 'ltr'=left-to-right | 'rtl'=right-to-left.
+ dealing_instructions : tuple of int
+ Represents instructions of how much cards from the top of the deck should be dealt to each player on each dealing cycle.
+ """
self.__players = []
self.__deck = Deck()
self.number_of_players = number_of_players
self.dealing_direction = dealing_direction
self.dealing_instructions = dealing_instructions
self.__add_players(self.number_of_players)
def get_players(self):
- # Предполагам, че редът в __players трябва да си остане същият, а само връщаме подредба от произволен индекс надясно
- if self.__players: # randrange се оплаква при 'empty range'
+ """Returns list of all Players in this Game starting from a random Player and ordered from left to right"""
+ if self.__players:
r = random.randrange(len(self.__players))
- return self.__players[r:] + self.__players[:r]
- else:
- return self.__players
+ self.__players = self.__players[r:] + self.__players[:r]
+ return self.__players
def prepare_deck(self):
- # Tук може просто да се инстанцира deck наново вместо да връщам всяка карта обратно в тестето,
- # и след това да затрия 'ръката' на всеки играч, но смятам, че така е по-автентично спрямо условието:
- for p in self.__players:
- self.__deck.add_cards(p.return_cards())
+ """Collects all cards from players (for each Player in this Game) back in the deck,
+ shuffles the deck and cuts it"""
+ for player in self.__players:
+ self.__deck.add_cards(player.return_cards())
self.__deck.shuffle()
self.__deck.cut()
def deal(self, player):
+ """Deals cards based on this Game's 'dealing_direction'(str) and 'dealing_instruction'(tuple)
+ starting from the specified 'player'(Player) until there are no cards left in the Deck."""
if player in self.__players:
i = self.__players.index(player)
-
- if self.dealing_direction == 'rtl':
- self.__players = self.__players[i::-1] + self.__players[:i:-1]
- else:
- self.__players = self.__players[i:] + self.__players[:i]
+ step = -1 if self.dealing_direction == 'rtl' else 1
+ order_of_dealing = self.__players[i::step] + self.__players[:i:step]
- # Предполагам, че ако dealing_instructions е tuple с един елемент,
- # ще се подава във формат (x,) и по този начин не трябва да се подсигурявам за int
for instruction in self.dealing_instructions:
- for p in self.__players:
+ for current_player in order_of_dealing:
for _ in range(instruction):
- if self.__deck.get_size() == 0:
+ if self.__deck.is_empty():
break
- p.add_card(self.__deck.deal_top_card())
+ current_player.add_card(self.__deck.deal_top_card())
def get_deck(self):
+ """Returns the Deck(list of Card elements) for this Game"""
return self.__deck
# Extra functions
def _set_deck_filter(self, filter):
+ """Takes string argument 'filter' and creates a new Deck for this Game based on that filter"""
self.__deck = Deck(filter)
def __add_players(self, n):
- for _ in range(n):
- if len(self.__players) < self.number_of_players:
- self.__players.append(Player())
+ """Adds 'n'(int) number of new Players to the current Game"""
+ self.__players.extend(Player() for _ in range(n))
class Belot(Game):
+ """A class to represent a Belot Game"""
+
def __init__(self):
+ """Constructs all the necessary prerequisites for the Belot object"""
super().__init__(4, 'ltr', (2, 3, 3))
self._set_deck_filter(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Poker(Game):
+ """A class to represent a Poker Game"""
+
def __init__(self):
+ """Constructs all the necessary prerequisites for the Poker object"""
super().__init__(9, 'rtl', (1, 1, 1, 1, 1)) # no filter = all cards

Александър обнови решението на 14.11.2022 14:15 (преди над 1 година)

import random
SUITS = [
'spades', 'hearts',
'diamonds', 'clubs',
]
FACES = ['2', '3', '4', '5', '6', '7', '8',
'9', '10', 'J', 'Q', 'K', 'A']
class Card:
"""
A class to represent a Card in a card game.
Attributes
----------
suit : str
Represents the suit of a card: ('spades', 'hearts', 'diamonds', 'clubs').
face : str
Represents the face of a card: ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'].
"""
def __init__(self, suit, face):
"""
Constructs all the necessary prerequisites for the Card object.
Parameters
----------
suit : str
Represents the suit of a card: ('spades', 'hearts', 'diamonds', 'clubs').
face : str
Represents the face of a card: ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'].
"""
self.suit = suit
self.face = face
def get_suit(self):
"""Returns the suit(str) of the Card."""
return self.suit
def get_face(self):
"""Returns the face(str) of the Card."""
return self.face
class Deck:
"""
A class to represent a Deck in a card game.
Attributes
----------
__cards : list of Card
List of cards in the current Deck.
"""
def __init__(self, face_filter=FACES):
"""
Constructs all the necessary prerequisites for the Deck object.
Parameters
----------
face_filter : list of str (optional)
Specifies the eligible faces in the current deck and adds a card from each suit of those faces.
Fills the list with all standard 52 cards if no face_filter argument is supplied.
"""
self.__cards = []
for face in face_filter:
if face.upper() in FACES:
for suit in SUITS:
self.__cards.append(Card(suit, face))
def cut(self):
"""Performs a cut action on the Deck of Cards by placing random number of Card elements from the top(end of the list)
to the bottom(beginning of the list) of the deck."""
r = random.randrange(1, len(self.__cards) - 1)
self.__cards = self.__cards[-r:] + self.__cards[:-r]
def shuffle(self):
"""Shuffles the order of the Card elements in __cards."""
random.shuffle(self.__cards)
def get_cards(self):
"""Returns a list of Card elements in this Deck."""
return self.__cards
# Extra functions
def add_cards(self, cards):
"""Adds Card elements to the end of the list of cards in this Deck."""
self.__cards.extend(cards)
def deal_top_card(self):
"""Removes and returns the top card in this Deck."""
return self.__cards.pop()
def is_empty(self):
"""Returns True if there are no Card elements in this Deck, otherwise - False."""
return len(self.__cards) == 0
class Player:
"""
A class to represent a Player in a card game.
Attributes
----------
__cards : list of Card
List of cards representing the cards in this Player's hand.
"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Player object."""
self.__cards = []
def get_cards(self):
"""Returns the list of Card elements that are in this Player's hand."""
return self.__cards
# Extra functions
def add_card(self, card):
"""Adds a Card element to the list cards(__cards) that are in this Player's hand."""
self.__cards.append(card)
def return_cards(self):
"""Removes all Card elements from this Player's hand(__cards) and returns them."""
hand = self.__cards
self.__cards = []
return hand
class Game:
"""
A class to represent a Game of cards.
Attributes
----------
number_of_players : int
Represents the number of players that this game will start with when instantiated.
dealing_direction : str
Represents the direction of card dealing: 'ltr'=left-to-right | 'rtl'=right-to-left.
dealing_instructions : tuple of int
Represents instructions of how much cards from the top of the deck should be dealt to each player on each dealing cycle.
__players : list of Player
List of players assigned to the current game.
__deck : Deck
Deck object that represents the deck of cards assigned to the current game.
"""
def __init__(self, number_of_players, dealing_direction, dealing_instructions):
"""
Constructs all the necessary prerequisites for the Game object.
Parameters
----------
number_of_players : int
Represents the number of players that this game will start with when instantiated.
dealing_direction : str
Represents the direction of card dealing: 'ltr'=left-to-right | 'rtl'=right-to-left.
dealing_instructions : tuple of int
Represents instructions of how much cards from the top of the deck should be dealt to each player on each dealing cycle.
"""
self.__players = []
self.__deck = Deck()
self.number_of_players = number_of_players
self.dealing_direction = dealing_direction
self.dealing_instructions = dealing_instructions
self.__add_players(self.number_of_players)
def get_players(self):
"""Returns list of all Players in this Game starting from a random Player and ordered from left to right"""
if self.__players:
r = random.randrange(len(self.__players))
self.__players = self.__players[r:] + self.__players[:r]
return self.__players
def prepare_deck(self):
"""Collects all cards from players (for each Player in this Game) back in the deck,
shuffles the deck and cuts it"""
for player in self.__players:
self.__deck.add_cards(player.return_cards())
self.__deck.shuffle()
self.__deck.cut()
def deal(self, player):
"""Deals cards based on this Game's 'dealing_direction'(str) and 'dealing_instruction'(tuple)
starting from the specified 'player'(Player) until there are no cards left in the Deck."""
if player in self.__players:
i = self.__players.index(player)
step = -1 if self.dealing_direction == 'rtl' else 1
order_of_dealing = self.__players[i::step] + self.__players[:i:step]
for instruction in self.dealing_instructions:
for current_player in order_of_dealing:
for _ in range(instruction):
if self.__deck.is_empty():
break
current_player.add_card(self.__deck.deal_top_card())
def get_deck(self):
"""Returns the Deck(list of Card elements) for this Game"""
return self.__deck
# Extra functions
def _set_deck_filter(self, filter):
- """Takes string argument 'filter' and creates a new Deck for this Game based on that filter"""
+ """Takes a list of strings 'filter' and creates a new Deck for this Game based on that filter"""
self.__deck = Deck(filter)
def __add_players(self, n):
"""Adds 'n'(int) number of new Players to the current Game"""
self.__players.extend(Player() for _ in range(n))
class Belot(Game):
"""A class to represent a Belot Game"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Belot object"""
super().__init__(4, 'ltr', (2, 3, 3))
self._set_deck_filter(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Poker(Game):
"""A class to represent a Poker Game"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Poker object"""
super().__init__(9, 'rtl', (1, 1, 1, 1, 1)) # no filter = all cards

Александър обнови решението на 14.11.2022 14:21 (преди над 1 година)

import random
SUITS = [
'spades', 'hearts',
'diamonds', 'clubs',
]
FACES = ['2', '3', '4', '5', '6', '7', '8',
'9', '10', 'J', 'Q', 'K', 'A']
class Card:
"""
A class to represent a Card in a card game.
Attributes
----------
suit : str
Represents the suit of a card: ('spades', 'hearts', 'diamonds', 'clubs').
face : str
Represents the face of a card: ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'].
"""
def __init__(self, suit, face):
"""
Constructs all the necessary prerequisites for the Card object.
Parameters
----------
suit : str
Represents the suit of a card: ('spades', 'hearts', 'diamonds', 'clubs').
face : str
Represents the face of a card: ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'].
"""
self.suit = suit
self.face = face
def get_suit(self):
"""Returns the suit(str) of the Card."""
return self.suit
def get_face(self):
"""Returns the face(str) of the Card."""
return self.face
class Deck:
"""
A class to represent a Deck in a card game.
Attributes
----------
__cards : list of Card
List of cards in the current Deck.
"""
def __init__(self, face_filter=FACES):
"""
Constructs all the necessary prerequisites for the Deck object.
Parameters
----------
face_filter : list of str (optional)
Specifies the eligible faces in the current deck and adds a card from each suit of those faces.
Fills the list with all standard 52 cards if no face_filter argument is supplied.
"""
self.__cards = []
for face in face_filter:
if face.upper() in FACES:
for suit in SUITS:
self.__cards.append(Card(suit, face))
def cut(self):
"""Performs a cut action on the Deck of Cards by placing random number of Card elements from the top(end of the list)
to the bottom(beginning of the list) of the deck."""
- r = random.randrange(1, len(self.__cards) - 1)
- self.__cards = self.__cards[-r:] + self.__cards[:-r]
+ random_index = random.randrange(1, len(self.__cards) - 1)
+ self.__cards = self.__cards[-random_index:] + self.__cards[:-random_index]
def shuffle(self):
"""Shuffles the order of the Card elements in __cards."""
random.shuffle(self.__cards)
def get_cards(self):
"""Returns a list of Card elements in this Deck."""
return self.__cards
# Extra functions
def add_cards(self, cards):
"""Adds Card elements to the end of the list of cards in this Deck."""
self.__cards.extend(cards)
def deal_top_card(self):
"""Removes and returns the top card in this Deck."""
return self.__cards.pop()
def is_empty(self):
"""Returns True if there are no Card elements in this Deck, otherwise - False."""
return len(self.__cards) == 0
class Player:
"""
A class to represent a Player in a card game.
Attributes
----------
__cards : list of Card
List of cards representing the cards in this Player's hand.
"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Player object."""
self.__cards = []
def get_cards(self):
"""Returns the list of Card elements that are in this Player's hand."""
return self.__cards
# Extra functions
def add_card(self, card):
"""Adds a Card element to the list cards(__cards) that are in this Player's hand."""
self.__cards.append(card)
def return_cards(self):
"""Removes all Card elements from this Player's hand(__cards) and returns them."""
hand = self.__cards
self.__cards = []
return hand
class Game:
"""
A class to represent a Game of cards.
Attributes
----------
number_of_players : int
Represents the number of players that this game will start with when instantiated.
dealing_direction : str
Represents the direction of card dealing: 'ltr'=left-to-right | 'rtl'=right-to-left.
dealing_instructions : tuple of int
Represents instructions of how much cards from the top of the deck should be dealt to each player on each dealing cycle.
__players : list of Player
List of players assigned to the current game.
__deck : Deck
Deck object that represents the deck of cards assigned to the current game.
"""
def __init__(self, number_of_players, dealing_direction, dealing_instructions):
"""
Constructs all the necessary prerequisites for the Game object.
Parameters
----------
number_of_players : int
Represents the number of players that this game will start with when instantiated.
dealing_direction : str
Represents the direction of card dealing: 'ltr'=left-to-right | 'rtl'=right-to-left.
dealing_instructions : tuple of int
Represents instructions of how much cards from the top of the deck should be dealt to each player on each dealing cycle.
"""
self.__players = []
self.__deck = Deck()
self.number_of_players = number_of_players
self.dealing_direction = dealing_direction
self.dealing_instructions = dealing_instructions
self.__add_players(self.number_of_players)
def get_players(self):
"""Returns list of all Players in this Game starting from a random Player and ordered from left to right"""
if self.__players:
- r = random.randrange(len(self.__players))
- self.__players = self.__players[r:] + self.__players[:r]
+ random_index = random.randrange(len(self.__players))
+ self.__players = self.__players[random_index:] + self.__players[:random_index]
return self.__players
def prepare_deck(self):
"""Collects all cards from players (for each Player in this Game) back in the deck,
shuffles the deck and cuts it"""
for player in self.__players:
self.__deck.add_cards(player.return_cards())
self.__deck.shuffle()
self.__deck.cut()
def deal(self, player):
"""Deals cards based on this Game's 'dealing_direction'(str) and 'dealing_instruction'(tuple)
starting from the specified 'player'(Player) until there are no cards left in the Deck."""
if player in self.__players:
i = self.__players.index(player)
step = -1 if self.dealing_direction == 'rtl' else 1
order_of_dealing = self.__players[i::step] + self.__players[:i:step]
for instruction in self.dealing_instructions:
for current_player in order_of_dealing:
for _ in range(instruction):
if self.__deck.is_empty():
break
current_player.add_card(self.__deck.deal_top_card())
def get_deck(self):
"""Returns the Deck(list of Card elements) for this Game"""
return self.__deck
# Extra functions
def _set_deck_filter(self, filter):
"""Takes a list of strings 'filter' and creates a new Deck for this Game based on that filter"""
self.__deck = Deck(filter)
- def __add_players(self, n):
- """Adds 'n'(int) number of new Players to the current Game"""
- self.__players.extend(Player() for _ in range(n))
+ def __add_players(self, num):
+ """Adds 'num'(int) number of new Players to the current Game"""
+ self.__players.extend(Player() for _ in range(num))
class Belot(Game):
"""A class to represent a Belot Game"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Belot object"""
super().__init__(4, 'ltr', (2, 3, 3))
self._set_deck_filter(['7', '8', '9', '10', 'J', 'Q', 'K', 'A'])
class Poker(Game):
"""A class to represent a Poker Game"""
def __init__(self):
"""Constructs all the necessary prerequisites for the Poker object"""
super().__init__(9, 'rtl', (1, 1, 1, 1, 1)) # no filter = all cards