Buggle Dance Revolution (BDR)

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]

Condicionais sem colchetes

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.

[/!]

Encadeando condicionais

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()[/!]

Grafitagem no mundo dos Buggles

Os buggles podem grafitar no chão de seu mundo. Para isto, use os quatro métodos seguintes:

Objetivo do exercício

O objetivo é então organizar um jogo de BDR entre os buggles ensinando eles a se mover de acordo com as instruções escritas no chão. Estas instruções são mensagens escritas no chão, com o seguinte significado:
Mensagem O que fazer Mnemônico
[!java|c]'R'[/!][!scala|python]"R"[/!]Vire a direita (R de right) e mova um passo a frenteDireita
[!java|c]'L'[/!][!scala|python]"L"[/!]Vire a esquerda e mova um passo a frenteEsquerda
[!java|c]'I'[/!][!scala|python]"I"[/!]Vire para trás (meia-volta) e mova um passo a frenteInversa
[!java|c]'A'[/!][!scala|python]"A"[/!]Mova um passo a frentePrimeira letra do alfabeto
[!java|c]'B'[/!][!scala|python]"B"[/!]Mova dois passos a frenteSegunda letra do alfabeto
[!java|c]'C'[/!][!scala|python]"C"[/!]Mova três passos a frenteTerceira 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áspenúltima letra do alfabeto
[!java|c]'X'[/!][!scala|python]"X"[/!]Mova três passos para trásAntepenúltima letra do alfabeto
(qualquer outra coisa)Parar de dançar.

Indicações

Este exercício pode parecer um pouco complexo à primeira vista, mas ele vem para resumir a informação na tabela numa sequência de condicionais.

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.

[!java|c]

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].

[/!]

Dicas

Se você não entendeu por que o buggle não fez os passos esperados, tente adicionar 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.