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 a apenas uma instrução. Mas cuidado, isto se torna perigoso se sua cadeia de instruções if parece com isto:

if (isOverBaggle())    
     if (x == 5)
          left();
else // Do not write it this way, it's misleading!
     right(); 
[!c]stepForward();[/!][!java|scala]forward();[/!]

You think that right() refers to the first if and get executed when isOverBaggle() returns false, but in fact, it refers to the second one if and will be executed when isOverBaggle() returns true and x != 5. Yes, despite the indentation, the buggle understands the previous code as follows:

if (estáSobreBaggle())    
        if (x == 5)
            esquerda();
        else
            direita();
avançar();

In [!thelang] the computer connects a else branch to the closest if. If you find it ambiguous, you should add more braces than strictly necessary. Computers don't even look at the indentation in [!thelang]. The previous code could even be written as follows and lead to the same result.

if (estáSobreBaggle()) if (x == 5) esquerda(); else direita(); [!c]avançarUmPasso();[/!][!java|scala]avançar();[/!]

But for humans, you really want to indent your code correctly correctly. For example if you want a professor to review or even grade your code, if you want to reuse your own code later, or even if you need to debug it. That is right: you need to write readable code for your own comfort.

[/!]

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.

Você tem que se manter dançando enquanto houverem passos de dança para fazer, i.e., enquanto estivermos numa célula cujo conteúdo esteja contido na tabela. a forma mais fácil de fazer isto é usando uma variável booleana (terminou) como condição de término para o loop while. Ela deve ser iniciada como [!c]0[/!][!java|scala]false[/!][!python]False[/!], e trocada para [!c]1[/!][!java|scala]true[/!][!python]True[/!] assim que o buggle encontre uma célula com um valor não descrito na tabela. Assim, o loop pára e o programa termina.

[!java|c]

Outro detalhe é que detectar se strings são iguais é um pouco chato em Java. Então, usamos o char getIndication[!c]Bdr[/!]() ao invés do [!java]String[/!][!c]char*[/!] lerMensagem(). Este método, conhecido apenas pelos buggles deste exercício, retorna o primeiro caractere da mensagem escrita no chão (ou ' ' -- o caractere para espaço -- se não tem nada escrito). Ele habilita que se trabalhe com caracteres ao invés de strings, que é muito mais simples em [!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.