python I can not use the break

1

This is a game that simulates a race. However, when a player reaches level 3 I want to stop the loop and clear all data, but I can not use break so that when the level of one of the players is 3, game and finish.

import random
class Jogador:
    def __init__(self, nome):
        self.nome = nome
        self.nivel=0
        self.passos= 0
        self.passos_parcial=0

    def mostra_tudo(self):
        print 'nivel',self.nivel
        print 'passos', self.passos
        print 'bonus', self.bonus

    def andar(self):
            self.passos_parcial = random.randint(1,60)
            self.passos+=self.passos_parcial
            self.checknivel()
            self.victory()
            print self.nome, "Andou mais", self.passos_parcial, "e está a", (120 - self.passos), "do próximo nível"

    def checknivel(self):
        if self.passos>=120:
              self.nivel+=1
              self.passos= self.passos-120
              print self.nome, 'está no nível', self.nivel

    def victory(self):
            if self.nivel == 3:
                print self.nome, 'ganhou'
                self.nivel=0
                self.passos= 0
                self.passos_parcial=0
                break



a=Jogador('Jogador 1')
b=Jogador('Jogador 2')
while True:
    a.andar()
    b.andar()
    
asked by anonymous 16.11.2017 / 11:32

1 answer

2

break has limited utility for cases like these: it comes out of a single loop in the same function.

You are creating the game with a good separation of what does what, but apparently the desperation to make break running messed up your code.

Every game will have an excerpt that is what we call the main loop - "mainloop": the stretch that has to be repeated every frame , or every interaction with the player, to the game to run. In this code it is easy to notice that the part that does this is in its andar function, which updates positions, calls update and verification functions, and prints the current state of the game. For this code to make sense, it is the walk function that is the main loop, which needs to be executed with every game interaction .

Update - I only realized after writing that you actually have several "players". In this case, you will have a "main loop" in another point of the program, which calls the andar function in each interaction: that is where the try...except block that I describe at the end should be. If you choose the variable, it has to be a global variable, not an attribute then.

So, the while True that went into the victory function should be covering the whole block that is in andar . And, yes, we need a mechanism so that the victory function can break this loop, and that's your question.

There are two ways: you can keep a variable with the global state of the game (in this case, simply an attribute of the Player class): while in andar checks this variable, and victory same:

...
def __init__(...):
    ...
    self.vitoria_aconteceu = False
    ...
    self.andar()
...
    def andar(self):
        while not self.vitoria_aconteceu:
            self.passos_parcial = random.randint(1,60)
            self.passos+=self.passos_parcial
            self.checknivel()
            self.victory()
            print self.nome, "Andou mais", self.passos_parcial, "e está a", (120 - self.passos), "do próximo nível"

...
    def victory(self):
        if self.nivel == 3:
            ...
            vitoria_aconteceu = True
Now imagine that this is a complex game, with multiple instances of Jogador , and various tests to stop the game: a player may die, or find the treasure, or arrive at a point where there is a change of stage to another map.

The functions could have more levels - in another type of game, the death of a player can happen in the position update of an object of class Tiro , in its method atualizar (and this method would not have access to the attribute in the game's main class).

So, a common way to handle the problem is to create custom exceptions, and put the main loop block within a try...except .

Creating a custom exception may sound complicated, but it's the simplest thing in the world: empty classes inherit from Exception .

You can even create an exception for each type of event that would lead to a main loop output, and then a block of except appropriate for each

class GameException(Exception): pass

class VicrotyException(GameException): pass

class LostException(GameException): pass

...

    def andar(self):
        try:
            while True:
                self.passos_parcial = random.randint(1,60)
                self.passos+=self.passos_parcial
                self.checknivel()
                self.victory()
                print self.nome, "Andou mais", self.passos_parcial, "e está a", (120 - self.passos), "do próximo nível"
         except VictoryException:
                print(self.nome, "ganhou")
                ...
...
    def victory(self):
        if self.nivel == 3:
            # Levanta uma excelççao de vitória,
            # que dsvia o código para o except correspondente:
            raise VitctoryException

Exceptions are by no means a bad thing, as it may seem - for more information see my answer about exceptions:

Why make exceptions in Python using raise?

Two more general tips for your code:

  • Are you sweating Python 2 why? It's a language of the past millennium, with ever shorter support - try switching to using Python 3.6

  • Try to maintain a consistency of nomenclature: you are using variables and methods with names in Portuguese and English at random. Ideally use in English: you never know when your project will look cool, and you'll want to put it in github and have international collaborators.

16.11.2017 / 12:08