Schlangen- und Leiterproblem oops Anwendung

Oct 16 2020

Ich lerne und versuche, die besten Praktiken für Schlangen- und Leiterspiele umzusetzen.

Spielregeln

  1. Die Karte hat 100 Zellen, die von 1 bis 100 nummeriert sind.
  2. Das Spiel hat sechsseitige Würfel von 1 bis 6 und gibt beim Würfeln immer eine Zufallszahl.
  3. Jeder Spieler hat eine Figur, die anfänglich außerhalb des Bretts gehalten wird (dh auf Position 0).
  4. Jeder Spieler würfelt, wenn er an der Reihe ist. Basierend auf dem Würfelwert bewegt der Spieler seine Figur um diese Anzahl von Zellen vorwärts. Beispiel: Wenn der Würfelwert 5 ist und sich die Figur auf Position 21 befindet, legt der Spieler seine Figur jetzt auf Position 26 (21 + 5).
  5. Ein Spieler gewinnt, wenn er genau die Position 100 erreicht und das Spiel dort endet.
  6. Wenn sich ein Stück nach dem Würfelwurf außerhalb der Position 100 bewegen soll, bewegt es sich nicht.
  7. Das Brett enthält auch einige Schlangen und Leitern. Jede Schlange hat ihren Kopf bei einer bestimmten Anzahl und ihren Schwanz bei einer kleineren Anzahl. Immer wenn ein Stück an einer Position mit dem Kopf der Schlange landet, sollte das Stück in die Position des Schwanzes dieser Schlange abfallen.
  8. Jede Leiter hat ihre Startposition bei einer bestimmten Nummer und ihre Endposition bei einer größeren Nummer. Immer wenn ein Stück an einer Position mit dem Anfang der Leiter landet, sollte das Stück bis zur Position des Endes dieser Leiter gehen.
  9. Es könnte sich eine andere Schlange / Leiter am Schwanz der Schlange oder an der Endposition der Leiter befinden und das Stück sollte entsprechend auf / ab gehen.

Annahmen

  • Bei 100 wird es keine Schlange geben.
  • Es werden nicht mehrere Schlangen / Leitern am selben Start- / Kopfpunkt sein.
  • Es ist möglich, 100 zu erreichen, dh es ist möglich, das Spiel zu gewinnen.
  • Schlangen und Leitern bilden keine Endlosschleife.
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()

Bitte schlagen Sie hier Verbesserungen und Korrekturen vor.

Antworten

3 hjpotter92 Oct 16 2020 at 05:15

Unnötige Klassen

Die Schlangen-, Leiter- und Würfelklassen sind überhaupt nicht nützlich. Sie können einfach durch ein Namedtuple oder eine Datenklasse ersetzt werden.

Ebenso sollten Spieler und Spielerposition ein einzelnes Klassenelement sein. Ein Spielerobjekt sollte dafür verantwortlich sein, seine Position zu verfolgen.

Ausführlichkeit

s1, s2, ... s8 und ähnliche l1, l2, ... l8 werden nicht wirklich verwendet. Behalten Sie ein Tupel von Positionen bei und wiederholen Sie diese, indem Sie entweder add_ladderoder add_snakeentsprechend aufrufen .

Kontrollfluss

Die Positionsaktualisierungen sollten am Ende des Spielers und nicht im Spiel erfolgen. Die Druckanweisung für die Aktualisierung der Spielerposition erfolgt innerhalb der Spielerklasse. Das Ziel des Spiels ist nur die Steuerung und Validierung von Zügen.

Es gibt keine Aussagen darüber, wann ein Spieler auf eine Leiter oder eine Schlange trifft. Nur ihre Position ändert sich in diesem ausführlichen Druckanweisungsnetz.

Doppelte Ausführung

    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

Sie haben dieselbe Funktion, die zweimal, zweimal aufgerufen wird. Für einen größeren Satz der Brettzellen gibt es weder eine Schlange noch eine Leiter. Sie rufen jedoch weiterhin beide Funktionen auf.

Alternativen

Würfelwurf

sum(random.choices(range(1, 7), k=dice_count))

Gewinnbedingung

def check_win_condition(self, position):
    return position == self.board.size

Schlangenkopf- oder Leiterbasisprüfung

Führen Sie ein Konto mit einem setoder tuplefür das Hinzufügen von Schlangen und Leitern. Das Board sollte überprüfen, ob eine Position dort entweder den Kopf einer Schlange oder die Basis einer Leiter hat. Sie durchlaufen derzeit alle Schlangen und Leitern (zweimal, wie oben erwähnt) für jede Position, während eine Suche \ wäre$ O(1) \$.