Problema con il serpente e la scala oops
Sto imparando e cercando di implementare le migliori pratiche per il gioco del serpente e della scala.
Le regole del gioco
- La scheda avrà 100 celle numerate da 1 a 100.
- Il gioco avrà un dado a sei facce numerato da 1 a 6 e darà sempre un numero casuale al lancio.
- Ogni giocatore ha un pezzo che inizialmente è tenuto fuori dal tabellone (cioè, in posizione 0).
- 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).
- Un giocatore vince se raggiunge esattamente la posizione 100 e il gioco finisce lì.
- Dopo il lancio dei dadi, se un pezzo dovrebbe muoversi fuori dalla posizione 100, non si muove.
- 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.
- 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.
- 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
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) \$.