Problem z wężem i drabiną oops
Uczę się i próbuję wdrażać najlepsze praktyki w grze w węża i drabinie.
Zasady gry
- Plansza będzie miała 100 komórek ponumerowanych od 1 do 100.
- Gra będzie miała sześciościenne kości ponumerowane od 1 do 6 i zawsze da losową liczbę podczas rzutu.
- Każdy gracz ma kawałek, który początkowo jest trzymany poza planszą (tj. Na pozycji 0).
- Każdy gracz rzuca kośćmi, gdy nadejdzie jego kolej. Na podstawie wartości kości gracz przesuwa swój kawałek do przodu o określoną liczbę komórek. Przykład: Jeśli wartość kości wynosi 5, a figura jest na pozycji 21, gracz kładzie teraz swój kawałek na pozycji 26 (21 + 5).
- Gracz wygrywa, jeśli dokładnie osiągnie pozycję 100 i gra się tam zakończy.
- Po rzucie kośćmi, jeśli bierka ma przesunąć się poza pozycję 100, nie porusza się.
- Na planszy znajdują się również węże i drabiny. Każdy wąż będzie miał głowę w pewnej liczbie, a ogon w mniejszej liczbie. Ilekroć kawałek kończy się na pozycji z głową węża, kawałek powinien zejść do pozycji ogona tego węża.
- Każda drabina będzie miała swoją pozycję początkową pod pewną liczbą, a pozycję końcową pod większą liczbą. Zawsze, gdy bierka kończy się na początku drabiny, bierka powinna iść w górę do pozycji końca tej drabiny.
- Na końcu węża lub końcowej pozycji drabiny może znajdować się inny wąż / drabina, a element powinien odpowiednio iść w górę / w dół.
Założenia
- W wieku 100 lat nie będzie węża.
- Nie będzie wielu węży / drabin w tym samym punkcie początkowym / głównym.
- Można osiągnąć 100, czyli można wygrać grę.
- Węże i drabiny nie tworzą nieskończonej pętli.
class Snake:
def __init__(self, start, end):
self.start = start
self.end = end
class Ladder:
def __init__(self, start, end):
self.start = start
self.end = end
class Board:
def __init__(self, size = 100):
self.size = size
self.snake_list = []
self.ladder_list = []
def add_snake(self, snake):
self.snake_list.append(snake)
def add_ladder(self, ladder):
self.snake_list.append(ladder)
class Dice:
dice_count = 1
@staticmethod
def roll():
return random.randint(1 * Dice.dice_count, 6 * Dice.dice_count)
class Player:
def __init__(self, name):
self.name = name
class PlayerPosition:
def __init__(self, player, position):
self.player = player
self.position = position
def update_position(self, new_position):
self.position = new_position
class Game:
def __init__(self, board):
self.board = board
self.players_position = []
def add_players(self, player, position=0):
player_position = PlayerPosition(player, position)
self.players_position.append(player_position)
def check_win_condition(self, position):
if position == self.board.size:
return True
return False
def check_for_snake(self, new_position):
for snake in self.board.snake_list:
start, end = snake.start, snake.end
if start == new_position:
return end
def check_for_ladder(self, new_position):
for ladder in self.board.ladder_list:
start, end = ladder.start, ladder.end
if start == new_position:
return end
def find_new_position(self, new_position):
if self.check_for_snake(new_position):
return self.check_for_snake(new_position)
elif self.check_for_ladder(new_position):
return self.check_for_ladder(new_position)
else:
return new_position
def start(self):
still_playing = len(self.players_position)
while(still_playing):
for player_position in self.players_position:
dice_value = Dice.roll()
current_position = player_position.position
new_position = current_position + dice_value
if new_position < self.board.size:
new_position = self.find_new_position(new_position)
player_position.update_position(new_position)
print(player_position.player.name, 'moved from', current_position, 'to', new_position)
if self.check_win_condition(new_position):
print("player", player_position.player.name, "wins!")
player_position.update_position(new_position + 1)
still_playing -= 1
class GameRunner:
@classmethod
def run_game(cls):
board = Board()
s1 = Snake(62, 5)
s2 = Snake(33, 6)
s3 = Snake(49, 9)
s4 = Snake(56, 53)
s5 = Snake(98, 64)
s6 = Snake(88, 16)
s7 = Snake(93, 73)
s8 = Snake(95, 75)
l1 = Ladder(2,37)
l2 = Ladder(27, 46)
l3 = Ladder(10, 32)
l4 = Ladder(51, 68)
l5 = Ladder(61, 79)
l6 = Ladder(65, 84)
l7 = Ladder(71, 91)
l8 = Ladder(81, 100)
board = Board()
board.add_ladder(l1)
board.add_ladder(l2)
board.add_ladder(l3)
board.add_ladder(l4)
board.add_ladder(l5)
board.add_ladder(l6)
board.add_ladder(l7)
board.add_ladder(l8)
board.add_snake(s1)
board.add_snake(s2)
board.add_snake(s3)
board.add_snake(s4)
board.add_snake(s5)
board.add_snake(s6)
board.add_snake(s7)
board.add_snake(s8)
player1 = Player("python")
player2 = Player("java")
player3 = Player("go")
game = Game(board)
game.add_players(player1)
game.add_players(player2)
game.add_players(player3)
game.start()
GameRunner.run_game()
Proszę sugerować miejsca ulepszeń i poprawek w tym zakresie.
Odpowiedzi
Niepotrzebne zajęcia
Klasy węża, drabiny i kości wcale nie są przydatne. Można je po prostu zastąpić nazwaną kratką lub klasą danych.
Podobnie, gracz i jego pozycja powinny być jednym elementem klasowym. Obiekt gracza powinien być odpowiedzialny za śledzenie jego pozycji.
Gadatliwość
s1, s2, ... s8 i podobne l1, l2, ... l8 nie są tak naprawdę używane. Zachowaj krotkę pozycji i iteruj po nich, wzywając albo add_ladderlub add_snakeodpowiednio.
Kontrola przepływu
Aktualizacje pozycji powinny mieć miejsce na końcu gracza, a nie podczas gry. Wydruk oświadczenia, kiedy pozycja gracza zostanie zaktualizowana, będzie miał miejsce w klasie gracza. Celem gry jest tylko kontrolowanie i potwierdzanie ruchów.
Nie ma żadnych stwierdzeń pokazujących, kiedy gracz napotka drabinę lub węża. tylko ich pozycja zmienia się w tej pełnej siatce instrukcji drukowania.
Podwójne wykonanie
if self.check_for_snake(new_position):
return self.check_for_snake(new_position)
elif self.check_for_ladder(new_position):
return self.check_for_ladder(new_position)
else:
return new_position
Masz tę samą funkcję wywoływaną dwukrotnie, dwukrotnie. W przypadku dużego zestawu komórek planszy nie ma węża ani drabiny. Jednak nadal wywołujesz obie funkcje.
Alternatywy
Rzut kostką
sum(random.choices(range(1, 7), k=dice_count))
Warunek wygranej
def check_win_condition(self, position):
return position == self.board.size
Kontrola głowy węża lub podstawy drabiny
Prowadź konto, używając setlub tupledla dodawanych węży i drabiny tablicy. Deska powinna sprawdzić, czy pozycja ma albo głowę węża, albo podstawę drabiny. Obecnie wykonujesz iterację wszystkich węży i drabin (dwukrotnie, jak wspomniano powyżej) dla każdej pozycji, podczas gdy wyszukiwanie byłoby \$ O(1) \$.