Depois destas corridas, é hora de festejar! Para isto, vamos ensinar os buggles a jogar Dance Revolution, este jogo amado por alguns estudantes: O jogador tem que mover os pés num carpete de acordo com as instruções apresentadas na tela, e seguir a música. Mas antes disto, temos alguns detalhes para estudar primeiro.
[!java|scala|c]Existe um detalhe que nós omitimos sobre a sintaxe do condicional: se um ramo contém apenas uma instrução, então o colchetes se torna opcional. Portanto, estes dois pedaços de código são equivalentes:
if (condition) { whatToDoIfTheConditionIsTrue(); } else { whatToDoElse(); }
if (condição) oQueFazerSeACondiçãoÉVerdadeira(); else oQueFazerCasoContrário();
Na verdade, você pode fazer o mesmo em corpos de loop que se reduzem aa apenas uma instrução. Mas cuidado, isto se torna perigoso se sua cadeia de instruções if parece com isto:
if (estáSobreBaggle()) if (x == 5) esquerda(); else direita(); [!c]avançarUmPasso();[/!][!java|scala]avançar();[/!]
De fato, não é para virar à direita quando não existe baggle no chão E x é igual a 5, mas quando o buggle encontra um baggle no chão e x é diferente de 5. Colocando de outra forma, o buggle entende o código anterior como se ele fosse escrito da seguinte forma (note que o else foi movido para a direita):
if (estáSobreBaggle()) if (x == 5) esquerda(); else direita(); avançar();
A primeira lição a tirar daí é que identação é muito importante para ajudar os humanos a entender, mesmo que não mude o significado do código. Nós poderíamos ter escrito o seguinte código e teríamos obtido o mesmo resultado. Mas se você quer que um humano leia e revise seu código, você vai com certeza querer indentar ele corretamente. Este é o caso, por exemplo, se você quer que um professor leia ele (para dar nota ou tirar uma dúvida), ou se você quiser reutilizar seu código mais tarde, ou mesmo se você quiser depurar você mesmo seu código.
if (estáSobreBaggle()) if (x == 5) esquerda(); else direita(); [!c]avançarUmPasso();[/!][!java|scala]avançar();[/!]
A segunda lição é que o ramo do else sempre se conecta ao if mais próximo. Isto pode se tornar confuso em alguns casos, e torna-se mais fácil adicionar mais chaves do que o estritamente necessário para remover quaisquer ambiguidades.
[/!]Algumas vezes você quer perguntar ao buggle algo similar a:
se está chovendo, pegue um guarda-chuva; se não, e se está quente, pegue uma garrafa de água; se não e se hoje é 4 de Julho, pegue uma bandeira dos estados unidos
O armadilha é que nós queremos que pelo menos uma destas ações sejam feitas.É como dizer, se está chovendo num 4 de Julho quente, não queremos que o buggle vá para fora com um guarda-chuva, água e um bandeira, mas simplesmente com um guarda-chuva. O código seguinte está, então, ERRADO.
[!scala|c|java]if (chovendo()) pegueGuarda-Chuva(); if (quente()) pegueAgua(); if (hoje4Julho()) pegueBandeira();[/!][!python]if chovendo(): pegueGuarda-Chuva() if quente(): pegueAgua() if hoje4Julho(): pegueBandeira()[/!]
Na verdade, já que as condições são calculadas uma depois da outra, existe um risco de que você vá para a marcha de 4 de Julho num dia chuvoso. Na verdade, nós devemos usar algo como isto para garantir que uma vez que encontremos a condição verdadeira, não passemos para as próximas.
[!java|scala|c]if (chuvoso()) { pegarGuardaChuva(); } else { if (diaQuente()) { pegarAgua(); } else { if (jogoDaCopa()) { pegarBandeira(); } } }[/!][!python]if chuvoso(): pegarGuardaChuva() else: if diaQuente(): pegarAgua() else: if jogoDaCopa(): pegarBandeira()[/!]
Infelizmente, tal cascata de condicionais é bastante difícil de ler. É
melhor [!java|scala|c]omitir as chaves para as assertivas
else. Algumas linguagens até mesmo introduzem uma construção
específica para estes else if, mas não [!thelang].[/!]
[!python]mudar os sub-blocos usando a palavra-chave elif
para marcar explicitamente estes ramos "else if".[/!]
[!c|java|scala]if (chuvoso()) { pegarGuardaChuva(); } else if (diaQuente()) { pegarAgua(); } else if (jogoDaCopa()) { pegarBandeira(); }[/!][!python]if chuvoso(): pegarGuardaChuva() elif diaQuente(): pegarAgua() elif jogoDaCopa(): pegarBandeira()[/!]
Os buggles podem grafitar no chão de seu mundo. Para isto, use os quatro métodos seguintes:
[!c]int[/!][!java]boolean[/!]
estaSobreMensagem()[!scala]:Boolean[/!]
: returns
[!c]1[/!][!java|scala]true[/!][!python]True[/!]
se e
somente se existe uma mensagem no chão.[!c]char*[/!][!java]String[/!] lerMensagem()[!scala]:
String[/!]
: retorna a mensagem lida no chão (ou uma string
vazia se não há nada escrito
).[!java|c]void[/!] escreverMensagem([!c]char*[/!][!java]String
[/!]msg[!scala]: String[/!])
: escreve a mensagem especificada
no chão. Se já existe uma mensagem no chão, a nova é adicionada no
final da mensagem existente.[!java|c]void [/!]clearMessage()
: limpa o que está escrito no
chão.Mensagem | O que fazer | Mnemônico |
[!java|c]'R'[/!][!scala|python]"R"[/!] | Vire a direita (R de right) e mova um passo a frente | Direita |
[!java|c]'L'[/!][!scala|python]"L"[/!] | Vire a esquerda e mova um passo a frente | Esquerda |
[!java|c]'I'[/!][!scala|python]"I"[/!] | Vire para trás (meia-volta) e mova um passo a frente | Inversa |
[!java|c]'A'[/!][!scala|python]"A"[/!] | Mova um passo a frente | Primeira letra do alfabeto |
[!java|c]'B'[/!][!scala|python]"B"[/!] | Mova dois passos a frente | Segunda letra do alfabeto |
[!java|c]'C'[/!][!scala|python]"C"[/!] | Mova três passos a frente | Terceira letra do alfabeto |
[!java|c]'Z'[/!][!scala|python]"Z"[/!] | Mova um passo para trás | última letra do alfabeto |
[!java|c]'Y'[/!][!scala|python]"Y"[/!] | Mova dois passos para trás | penúltima letra do alfabeto |
[!java|c]'X'[/!][!scala|python]"X"[/!] | Mova três passos para trás | Antepenúltima letra do alfabeto |
(qualquer outra coisa) | Parar de dançar. |
You have to keep dancing as long as there is some dancing steps to do, i.e.,
as long as we are in a cell which content is described in the table. The
easier for that is to use a boolean variable (finished
) as
termination condition to a while
loop. It should be
initialized to
[!c]0[/!][!java|scala]false[/!][!python]False[/!]
, and switched
to [!c]1[/!][!java|scala]true[/!][!python]True[/!]
as soon as
the buggle find a cell with a value not described in the table. Thus, the
loop will stop and the program will terminate.
Another subtlety is that detecting if strings are equals is a bit annoying
in [!thelang]. So, we use the char getIndication[!c]Bdr[/!]()
instead of [!java]String[/!][!c]char*[/!] readMessage()
. This
method, only known by the buggles of this exercise, returns the first char
of the message written on the ground (or ' ' -- the space char -- if nothing
is written down). It enables to work with chars instead of strings, that is
much simpler in [!thelang].
abaixarPincel()
no seu método. Isto pede
ao buggle para abaixar um pincel deixando um rastro por onde
passar. Isto pode ajudar você a entender a trajetória dele, mas não
esqueça de remover esta chamada quando você quiser testar se seu
código é uma solução válida para o exercício: você pode fazer o buggle
dançar, mas não pichar a pista de dança.
Quando seu programa finalmente funcionar, vá para o próximo exercício.