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.