Problema con il serpente e la scala oops

Oct 16 2020

Sto imparando e cercando di implementare le migliori pratiche per il gioco del serpente e della scala.

Le regole del gioco

  1. La scheda avrà 100 celle numerate da 1 a 100.
  2. Il gioco avrà un dado a sei facce numerato da 1 a 6 e darà sempre un numero casuale al lancio.
  3. Ogni giocatore ha un pezzo che inizialmente è tenuto fuori dal tabellone (cioè, in posizione 0).
  4. Ogni giocatore lancia i dadi quando arriva il proprio turno. In base al valore dei dadi, il giocatore sposta la propria pedina in avanti di quel numero di celle. Es: se il valore dei dadi è 5 e il pezzo è in posizione 21, il giocatore metterà il pezzo in posizione 26 ora (21 + 5).
  5. Un giocatore vince se raggiunge esattamente la posizione 100 e il gioco finisce lì.
  6. Dopo il lancio dei dadi, se un pezzo dovrebbe muoversi fuori dalla posizione 100, non si muove.
  7. Il tabellone contiene anche alcuni serpenti e scale. Ogni serpente avrà la testa in un certo numero e la coda in un numero inferiore. Ogni volta che un pezzo finisce in una posizione con la testa del serpente, il pezzo dovrebbe scendere nella posizione della coda di quel serpente.
  8. Ogni ladder avrà la sua posizione iniziale in un certo numero e la posizione finale in un numero maggiore. Ogni volta che un pezzo finisce in una posizione con l'inizio della scala, il pezzo dovrebbe salire alla posizione della fine di quella scala.
  9. Potrebbe esserci un altro serpente / scala alla coda del serpente o alla posizione finale della scala e il pezzo dovrebbe salire / scendere di conseguenza.

Presupposti

  • Non ci sarà un serpente a 100.
  • Non ci saranno più serpenti / scale nello stesso punto di partenza / testa.
  • È possibile arrivare a 100, cioè è possibile vincere la partita.
  • I serpenti e le scale non formano un ciclo infinito.
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()

Si prega di suggerire luoghi di miglioramenti e correzioni su questo.

Risposte

3 hjpotter92 Oct 16 2020 at 05:15

Classi non necessarie

Le classi serpente, scala e dadi non sono affatto utili. Possono essere semplicemente sostituiti con una namedtuple o una dataclass.

Allo stesso modo, player e playerposition dovrebbero essere entrambi un unico elemento di classe. Un oggetto giocatore dovrebbe essere responsabile di tenere traccia della propria posizione.

Verbosità

s1, s2, ... s8 e simili l1, l2, ... l8 non sono realmente utilizzati. Mantieni una tupla di posizioni e itera su di esse, chiamando una add_laddero l' altra di add_snakeconseguenza.

Flusso di controllo

Gli aggiornamenti di posizione dovrebbero avvenire alla fine del giocatore e non al gioco. La dichiarazione di stampa per quando la posizione del giocatore viene aggiornata avverrebbe all'interno della classe del giocatore. Lo scopo del gioco è solo controllare e convalidare le mosse.

Non ci sono dichiarazioni che mostrano quando un giocatore incontra una scala o un serpente. solo la loro posizione cambia in quella maglia prolissa dell'istruzione print.

Doppia esecuzione

    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

Hai la stessa funzione che viene chiamata due volte, due volte. Per una serie principale di celle della scacchiera, non c'è né un serpente né una scala. Tuttavia, continui a chiamare entrambe le funzioni.

Alternative

Rotolo di dadi

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

Condizione di vittoria

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

Testa di serpente o controllo della base della scala

Mantieni un account utilizzando un seto tupleper l'aggiunta di serpenti e scala della bacheca. La tavola dovrebbe convalidare se una posizione ha la testa di serpente o la base della scala. Stai attualmente iterando su tutti i serpenti e le scale (due volte, come menzionato sopra) per ogni posizione, mentre una ricerca sarebbe \$ O(1) \$.