O laço do menu
O menu (página anterior) precisa repetir o mesmo ciclo até o usuário
pedir para sair: desenhar, perguntar, reagir. Esta página escreve o método run, que gera o
primeiro labirinto e faz esse ciclo, e mostra o que pode interrompê-lo.
O método run
def run(self) -> int:
"""Generate the first maze and loop over the menu.
Exceptions are left to the caller: a failed regeneration, the end
of the input and Ctrl+C all reach main.
Returns:
0 when the user picks option 4.
"""
maze = self._generate.execute()
while True:
self._show(maze)
choice = self._read_choice()
if choice == "1":
maze = self._generate.execute()
elif choice == "2":
self._state.toggle_path()
elif choice == "3":
self._state.next_colour()
else:
return 0
Passo a passo:
maze = self._generate.execute()gera o primeiro labirinto, grava o arquivo de saída e guarda o retrato emmaze.while True:repete o bloco de baixo para sempre. A única saída é oreturn.self._show(maze)imprime o desenho e o menu (página 4).self._read_choice()pergunta até vir uma resposta válida e devolve"1","2","3"ou"4"(próxima página).- Conforme a resposta:
"1": gera outro labirinto (e regrava o arquivo);mazepassa a ser o novo;"2": liga ou desliga o caminho noViewState;"3": passa as paredes para a próxima cor;- qualquer outra: só pode ser
"4", porque_read_choicenunca devolve outra coisa. Oreturn 0sai do laço e do método.
- Nas opções
1,2e3, o laço volta ao passo 3 e desenha de novo, já com a mudança.
Uma sessão em que o usuário digita 2, depois 3, depois 1 e por fim 4:
| Resposta | O que muda | Desenho seguinte |
|---|---|---|
| (início) | gera e grava o primeiro labirinto | labirinto 1, sem caminho, paredes brancas |
2 | show_path vira True | labirinto 1, com caminho, paredes brancas |
3 | a cor passa para amarelo | labirinto 1, com caminho, paredes amarelas |
1 | gera e grava o labirinto 2 | labirinto 2, com caminho, paredes amarelas |
4 | return 0 | nenhum: o programa termina |
A opção 1 troca só o maze. O ViewState é o mesmo objeto do começo ao fim, então o caminho
continua visível e a cor continua a escolhida.
O desenho acontece num lugar só, no topo do laço. As opções não desenham nada: só mudam o estado
e deixam o laço voltar ao _show.
O 0 devolvido é o código de saída do programa: o número que um programa entrega ao sistema
quando termina. Por convenção, 0 quer dizer "terminou bem", e qualquer outro número quer dizer
"deu erro". Scripts e outras ferramentas leem esse número para saber se o programa funcionou; no
terminal, echo $? logo depois de um comando mostra o código dele (o $? guarda o código do
último comando). O run devolve o 0 ao main, que o passa ao sistema
(página 6).
As exceções sobem
O Menu não tem nenhum try. Quando uma função levanta uma exceção e não a trata, o Python sai
dessa função e entrega a exceção a quem a chamou; se esta também não trata, sai dela, e assim por
diante. Diz-se que a exceção sobe.
Quatro coisas podem interromper o laço:
- a gravação do arquivo falha numa regeneração: o
GenerateMazelevanta (lança)OutputError, o erro da aplicação para "não consegui gravar o arquivo de saída" (parte 10); - a geração falha: no modo Pac-Man, o
generate()do gerador levantaMazeErrorquando 20 tentativas seguidas não montam um tabuleiro válido (parte 9); - a entrada acaba: o
inputlevantaEOFError(End Of File, "fim do arquivo") quando não há mais nada para ler, por exemplo quando o usuário aperta Ctrl+D ou quando o texto de um pipe termina; - o usuário aperta Ctrl+C: o Python levanta
KeyboardInterrupt("interrupção pelo teclado").
As quatro sobem até o main, que tem um único lugar para transformar cada uma numa mensagem e
num código de saída (páginas 7 a
9). Tratar parte delas aqui espalharia a mesma decisão por
dois arquivos.