Решение на От ливадите до Лас Вегас (и назад) от Кристияна Николова

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

Към профила на Кристияна Николова

Резултати

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

Код

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, face):
self.suit = self.is_valid_suit(suit)
self.face = self.is_valid_face(face)
def is_valid_suit(self, suit):
if suit.lower() not in valid_suits:
raise ValueError("Suit should be: clubs, diamonds, hearts, spades.")
return suit.lower()
def is_valid_face(self, face):
if face.upper() not in valid_faces:
raise ValueError("Face should be: 2-10, J, Q, K, A.")
return face.upper()
def get_suit(self):
return str(self.suit)
def get_face(self):
return str(self.face)
def __repr__(self):
return str(self.face + " of " + self.suit)
def get_card_info(self):

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

return self
class Deck:
def __init__(self, face_filter=None):
self.cards = []
if face_filter is None:
self.build()
else:
for face in face_filter:
for suit in valid_suits:
self.cards.append(Card(suit, face.upper()))
def build(self):
for suit in valid_suits:
for face in valid_faces:
self.cards.append(Card(suit, face))
def cut(self):
cut_point = random.choice(range(len(self.cards)))
self.cards = self.cards[cut_point:] + self.cards[:cut_point]
'''def shuffle(self):
for index in range(len(self.cards) - 1, 0, -1):
rand = random.randint(0, index)
self.cards[index], self.cards[rand] = self.cards[rand], self.cards[index]
'''
def shuffle(self):
random.shuffle(self.cards)
def get_cards(self):
return self.cards
def add_cards(self, cards):
for card in cards:
self.cards.append(card)
def remove_cards(self, cards):
for card in cards:
self.cards.remove(card)
class Player:
def __init__(self):
self.hand = []
def add_card_to_hand(self, card):
self.hand.append(card)
def get_cards(self):
return self.hand
def collect_cards(self):
collected = self.hand
self.hand = []
return collected
class Game:
def __init__(self, number_of_players, dealing_direction, dealing_instructions):
self.number_of_players = number_of_players
if dealing_direction in ["ltr", "rtl"]:
self.dealing_direction = dealing_direction
else:
raise ValueError("Dealing direction should be: ltr or rtl.")
if type(dealing_instructions) is tuple:
self.dealing_instructions = dealing_instructions
else:
raise TypeError("Dealing instructions should be: tuple.")
self.list_of_players = []
for _ in range(self.number_of_players):
player = Player()
self.list_of_players.append(player)
self.deck = Deck()
def get_players(self):
return self.list_of_players
def prepare_deck(self):
for player in self.list_of_players:
self.deck.add_cards(player.collect_cards())
self.deck.shuffle()
self.deck.cut()
def deal(self, player):
first_to_play = self.list_of_players.index(player)
for cards_to_deal in self.dealing_instructions:

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

if self.dealing_direction == "ltr":
for player in self.list_of_players[first_to_play:]:
drawed_cards = self.deck.get_cards()[0:cards_to_deal]
for card in drawed_cards:
player.add_card_to_hand(card)
self.deck.get_cards().remove(card)

self.deck.get_cards в момента връща копие на списъка с карти, така че според мен нищо не махаш от тестето, а само от временна променлива, която методът ти връща.

for player in self.list_of_players[0:first_to_play]:
drawed_cards = self.deck.get_cards()[0:cards_to_deal]
for card in drawed_cards:
player.add_card_to_hand(card)
self.deck.get_cards().remove(card)
if self.dealing_direction == "rtl":
for player in self.list_of_players[first_to_play:0:-1]:
drawed_cards = self.deck.get_cards()[0:cards_to_deal]
for card in drawed_cards:
player.add_card_to_hand(card)
self.deck.get_cards().remove(card)
for player in self.list_of_players[first_to_play+1::][::-1]:
drawed_cards = self.deck.get_cards()[0:cards_to_deal]
for card in drawed_cards:
player.add_card_to_hand(card)
self.deck.get_cards().remove(card)
def get_deck(self):
return self.deck
class Belot(Game):
num_of_players = 4
direction = "ltr"
instructions = (2, 3, 3)
face_filter = ['7', '8', '9', '10', 'J', 'Q', 'K', 'A']
def __init__(self):
super().__init__(self.num_of_players, self.direction, self.instructions)
self.deck = Deck(self.face_filter)
class Poker(Game):
num_of_players = 9
direction = "rtl"
instructions = (1, 1, 1, 1, 1)
def __init__(self):
super().__init__(self.num_of_players, self.direction, self.instructions)

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

....F.....F...F
======================================================================
FAIL: test_cutting_deck (test.TestDeck)
Test cutting 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: [2 of clubs, 2 of diamonds, 2 of hearts, 2 of spades, 5 of clubs, 5 of diamonds, 5 of hearts, 5 of spades, 10 of clubs, 10 of diamonds, 10 of hearts, 10 of spades, J of clubs, J of diamonds, J of hearts, J of spades, A of clubs, A of diamonds, A of hearts, A of spades] == [2 of clubs, 2 of diamonds, 2 of hearts, 2 of spades, 5 of clubs, 5 of diamonds, 5 of hearts, 5 of spades, 10 of clubs, 10 of diamonds, 10 of hearts, 10 of spades, J of clubs, J of diamonds, J of hearts, J of spades, A of clubs, A of diamonds, A of hearts, A of spades]

======================================================================
FAIL: 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
AssertionError: {('clubs', '8'), ('clubs', '2'), ('clubs', '3')} not found in ({('clubs', '2'), ('clubs', '3'), ('clubs', '10')}, {('spades', 'K'), ('spades', '6'), ('spades', 'A')})

======================================================================
FAIL: 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
AssertionError: {('hearts', '8'), ('diamonds', '5'), ('clubs', '2'), ('clubs', '10'), ('diamonds', 'K')} not found in ({('hearts', '3'), ('clubs', 'J'), ('diamonds', '7'), ('clubs', '2'), ('hearts', 'Q')}, {('spades', '5'), ('hearts', '9'), ('diamonds', '4'), ('spades', 'A'), ('diamonds', 'K')})

----------------------------------------------------------------------
Ran 15 tests in 0.175s

FAILED (failures=3)

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

Кристияна обнови решението на 13.11.2022 10:13 (преди над 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, face):
+ self.suit = self.is_valid_suit(suit)
+ self.face = self.is_valid_face(face)
+
+ def is_valid_suit(self, suit):
+ if suit.lower() not in valid_suits:
+ raise ValueError("Suit should be: clubs, diamonds, hearts, spades.")
+ return suit.lower()
+
+ def is_valid_face(self, face):
+ if face.upper() not in valid_faces:
+ raise ValueError("Face should be: 2-10, J, Q, K, A.")
+ return face.upper()
+
+ def get_suit(self):
+ return str(self.suit)
+
+ def get_face(self):
+ return str(self.face)
+
+ def __repr__(self):
+ return str(self.face + " of " + self.suit)
+
+ def get_card_info(self):

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

+ return self
+
+
+class Deck:
+ def __init__(self, face_filter = None):
+ self.cards = []
+ if face_filter is None:
+ self.build()
+ else:
+ for face in face_filter:
+ for suit in valid_suits:
+ self.cards.append(Card(suit, face.upper()))
+
+ def build(self):
+ for suit in valid_suits:
+ for face in valid_faces:
+ self.cards.append(Card(suit, face))
+
+ def cut(self):
+ cut_point = random.choice(range(len(self.cards)))
+ self.cards = self.cards[cut_point :] + self.cards[: cut_point]
+
+ '''def shuffle(self):
+ for index in range(len(self.cards) - 1, 0, -1):
+ rand = random.randint(0, index)
+ self.cards[index], self.cards[rand] = self.cards[rand], self.cards[index]
+ '''
+ def shuffle(self):
+ random.shuffle(self.cards)
+
+ def get_cards(self):
+ list_of_cards = []

А защо не просто return self.cards? Притесняваш се, че връщаш същия списък и искаш да го копираш ли? Ако да, това не е нужно, но дори да искаш да го копираш, можеш просто да напишеш return self.cards[:]

+ for card in self.cards:
+ list_of_cards.append(card.get_card_info())
+ return list_of_cards
+
+ def add_cards(self, cards):
+ for card in cards:
+ self.cards.append(card)
+
+ def remove_cards(self, cards):
+ for card in cards:
+ self.cards.remove(card)
+
+
+class Player:
+ def __init__(self):
+ self.hand = []
+
+ def add_card_to_hand(self, card):
+ self.hand.append(card)
+
+ def get_cards(self):
+ return self.hand
+
+ def collect_cards(self):
+ collected = self.hand
+ self.hand = []
+ return collected
+
+
+class Game:
+
+ def __init__(self, number_of_players, dealing_direction, dealing_instructions):
+ self.number_of_players = number_of_players
+ if dealing_direction in ["ltr", "rtl"]:
+ self.dealing_direction = dealing_direction
+ else:
+ raise ValueError("Dealing direction should be: ltr or rtl.")
+
+ if type(dealing_instructions) is tuple:
+ self.dealing_instructions = dealing_instructions
+ else:
+ raise TypeError("Dealing instructions should be: tuple.")
+
+ self.list_of_players = []
+
+ for i in range(self.number_of_players):
+ player = Player()
+ self.list_of_players.append(player)
+
+ self.deck = Deck()
+
+ def get_players(self):
+ return self.list_of_players
+
+ def prepare_deck(self):
+ for player in self.list_of_players:
+ self.deck.add_cards(player.collect_cards())
+
+ self.deck.shuffle()
+ self.deck.cut()
+
+ def deal(self, player):
+ first_to_play = self.list_of_players.index(player)
+
+ for cards_to_deal in self.dealing_instructions:

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

+ if self.dealing_direction == "ltr":
+ for player in self.list_of_players[first_to_play:]:
+ drawed_cards = self.deck.get_cards()[0:cards_to_deal]
+
+ for card in drawed_cards:
+ player.add_card_to_hand(card)
+ self.deck.get_cards().remove(card)

self.deck.get_cards в момента връща копие на списъка с карти, така че според мен нищо не махаш от тестето, а само от временна променлива, която методът ти връща.

+
+ for player in self.list_of_players[0:first_to_play]:
+ drawed_cards = self.deck.get_cards()[0:cards_to_deal]
+
+ for card in drawed_cards:
+ player.add_card_to_hand(card)
+ self.deck.get_cards().remove(card)
+
+ if self.dealing_direction == "rtl":
+ for player in self.list_of_players[first_to_play:0:-1]:
+ drawed_cards = self.deck.get_cards()[0:cards_to_deal]
+
+ for card in drawed_cards:
+ player.add_card_to_hand(card)
+ self.deck.get_cards().remove(card)
+
+ for player in self.list_of_players[first_to_play+1::][::-1]:
+ drawed_cards = self.deck.get_cards()[0:cards_to_deal]
+
+ for card in drawed_cards:
+ player.add_card_to_hand(card)
+ self.deck.get_cards().remove(card)
+
+ def get_deck(self):
+ return self.deck
+
+
+class Belot(Game):
+ num_of_players = 4
+ direction = "ltr"
+ instructions = (2, 3, 3)
+ face_filter = ['7', '8', '9', '10', 'J', 'Q', 'K', 'A']
+
+ def __init__(self):
+ super().__init__(self.num_of_players, self.direction, self.instructions)
+ self.deck = Deck(self.face_filter)
+
+
+class Poker(Game):
+ num_of_players = 9
+ direction = "rtl"
+ instructions = (1, 1, 1, 1, 1)
+
+ def __init__(self):
+ super().__init__(self.num_of_players, self.direction, self.instructions)
+

Кристияна обнови решението на 14.11.2022 00:31 (преди над 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, face):
self.suit = self.is_valid_suit(suit)
self.face = self.is_valid_face(face)
def is_valid_suit(self, suit):
if suit.lower() not in valid_suits:
raise ValueError("Suit should be: clubs, diamonds, hearts, spades.")
return suit.lower()
def is_valid_face(self, face):
if face.upper() not in valid_faces:
raise ValueError("Face should be: 2-10, J, Q, K, A.")
return face.upper()
def get_suit(self):
return str(self.suit)
def get_face(self):
return str(self.face)
def __repr__(self):
return str(self.face + " of " + self.suit)
def get_card_info(self):
return self
class Deck:
- def __init__(self, face_filter = None):
+ def __init__(self, face_filter=None):
self.cards = []
if face_filter is None:
self.build()
else:
for face in face_filter:
for suit in valid_suits:
self.cards.append(Card(suit, face.upper()))
def build(self):
for suit in valid_suits:
for face in valid_faces:
self.cards.append(Card(suit, face))
def cut(self):
cut_point = random.choice(range(len(self.cards)))
- self.cards = self.cards[cut_point :] + self.cards[: cut_point]
+ self.cards = self.cards[cut_point:] + self.cards[:cut_point]
'''def shuffle(self):
for index in range(len(self.cards) - 1, 0, -1):
rand = random.randint(0, index)
self.cards[index], self.cards[rand] = self.cards[rand], self.cards[index]
'''
def shuffle(self):
random.shuffle(self.cards)
def get_cards(self):
- list_of_cards = []
- for card in self.cards:
- list_of_cards.append(card.get_card_info())
- return list_of_cards
+ return self.cards
def add_cards(self, cards):
for card in cards:
self.cards.append(card)
def remove_cards(self, cards):
for card in cards:
self.cards.remove(card)
class Player:
def __init__(self):
self.hand = []
def add_card_to_hand(self, card):
self.hand.append(card)
def get_cards(self):
return self.hand
def collect_cards(self):
collected = self.hand
self.hand = []
return collected
class Game:
def __init__(self, number_of_players, dealing_direction, dealing_instructions):
self.number_of_players = number_of_players
if dealing_direction in ["ltr", "rtl"]:
self.dealing_direction = dealing_direction
else:
raise ValueError("Dealing direction should be: ltr or rtl.")
if type(dealing_instructions) is tuple:
self.dealing_instructions = dealing_instructions
else:
raise TypeError("Dealing instructions should be: tuple.")
self.list_of_players = []
- for i in range(self.number_of_players):
+ for _ in range(self.number_of_players):
player = Player()
self.list_of_players.append(player)
self.deck = Deck()
def get_players(self):
return self.list_of_players
def prepare_deck(self):
for player in self.list_of_players:
self.deck.add_cards(player.collect_cards())
self.deck.shuffle()
self.deck.cut()
def deal(self, player):
first_to_play = self.list_of_players.index(player)
for cards_to_deal in self.dealing_instructions:
if self.dealing_direction == "ltr":
for player in self.list_of_players[first_to_play:]:
drawed_cards = self.deck.get_cards()[0:cards_to_deal]
for card in drawed_cards:
player.add_card_to_hand(card)
self.deck.get_cards().remove(card)
for player in self.list_of_players[0:first_to_play]:
drawed_cards = self.deck.get_cards()[0:cards_to_deal]
for card in drawed_cards:
player.add_card_to_hand(card)
self.deck.get_cards().remove(card)
if self.dealing_direction == "rtl":
for player in self.list_of_players[first_to_play:0:-1]:
drawed_cards = self.deck.get_cards()[0:cards_to_deal]
for card in drawed_cards:
player.add_card_to_hand(card)
self.deck.get_cards().remove(card)
for player in self.list_of_players[first_to_play+1::][::-1]:
drawed_cards = self.deck.get_cards()[0:cards_to_deal]
for card in drawed_cards:
player.add_card_to_hand(card)
self.deck.get_cards().remove(card)
def get_deck(self):
return self.deck
class Belot(Game):
num_of_players = 4
direction = "ltr"
instructions = (2, 3, 3)
face_filter = ['7', '8', '9', '10', 'J', 'Q', 'K', 'A']
def __init__(self):
super().__init__(self.num_of_players, self.direction, self.instructions)
self.deck = Deck(self.face_filter)
class Poker(Game):
num_of_players = 9
direction = "rtl"
instructions = (1, 1, 1, 1, 1)
def __init__(self):
super().__init__(self.num_of_players, self.direction, self.instructions)