Problem z wężem i drabiną oops

Oct 16 2020

Uczę się i próbuję wdrażać najlepsze praktyki w grze w węża i drabinie.

Zasady gry

  1. Plansza będzie miała 100 komórek ponumerowanych od 1 do 100.
  2. Gra będzie miała sześciościenne kości ponumerowane od 1 do 6 i zawsze da losową liczbę podczas rzutu.
  3. Każdy gracz ma kawałek, który początkowo jest trzymany poza planszą (tj. Na pozycji 0).
  4. 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).
  5. Gracz wygrywa, jeśli dokładnie osiągnie pozycję 100 i gra się tam zakończy.
  6. Po rzucie kośćmi, jeśli bierka ma przesunąć się poza pozycję 100, nie porusza się.
  7. 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.
  8. 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.
  9. 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

3 hjpotter92 Oct 16 2020 at 05:15

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) \$.