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 no ecrã e seguir a música. Mas antes disto, temos alguns detalhes para estudar primeiro.

[!java|scala|c]

Condicionais sem colchetes

Existe um detalhe que 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 (condição) {
    oQueFazerSeACondiçãoÉVerdadeira();
} else {
    oQueFazerCasoContrário();
}
if (condição) 
    oQueFazerSeACondiçãoÉVerdadeira();
else
    oQueFazerCasoContrário();

Na verdade, pode fazer o mesmo em corpos de loop que se reduzem a apenas uma instrução. Mas cuidado, isto torna-se perigoso se cadeiar as instruções if como a seguir:

if (isOverBaggle())    
     if (x == 5)
          left();
else // Não escreva desta forma, é enganoso!
     right(); 
[!c]stepForward();[/!][!java|scala]forward();[/!]

Pensa que right() se refere ao primeiro if e será executado quando isOverBaggle() retorna false, mas, na verdade, refere-se ao segundo if e será executado quando isOverBaggle() retorna true e x != 5. Sim, apesar da indentação, o buggle entende o código anterior da seguinte forma:

if (isOverBaggle())    
        if (x == 5)
            left();
        else
            right();
[!c]stepForward();[/!][!java|scala]forward();[/!]

Em [!thelang] o computador conecta um ramo else ao if mais próximo. Se o achar ambíguo, deve adicionar mais aspas do que estritamente necessário. Os computadores nem sequer olham para a indentação em [!thelang]. O código anterior pode até ser escrito da seguinte forma e levar ao mesmo resultado.

if (isOverBaggle()) if (x == 5) left(); else right(); [!c]stepForward();[/!][!java|scala]forward();[/!]

Mas para humanos, realmente é melhor indentar o seu código corretamente. Por exemplo, se quer que um professor reveja ou mesmo avalie o seu código, se quer reutilizar o seu próprio código mais tarde, ou mesmo se precisa depurá-lo. Isso é certo: precisa escrever um código legível para o seu próprio conforto.

[/!]

Encadear condicionais

Algumas vezes quer perguntar o buggle algo similar a:

se está a chover, leve um guarda-chuva;
se não e se está quente, leve uma garrafa de água;
se não e se hoje é 4 de Julho, leve uma bandeira dos estados unidos

A armadilha é que queremos que pelo menos uma destas ações sejam feitas. É como dizer, se está a chover 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 (chuvoso())
    pegueGuarda-Chuva();
if (quente())
    pegueAgua();
if (hoje4Julho())
    pegueBandeira();[/!][!python]if aChover():
    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 vá sair no die 4 de Julho num dia chuvoso. Na verdade, devemos usar algo como isto para garantir que uma vez que encontremos a condição verdadeira, não passemos às próximas.

[!java|scala|c]if (chuvoso()) {
    levarGuardaChuva();
} else {
    if (diaQuente()) {
        levarAgua();
    } else {
        if (jogoDaCopa()) {
            levarBandeira();
        }
    }
}[/!][!python]if chuvoso():
    levarGuardaChuva()
else:
    if diaQuente():
        levarAgua()
    else:
        if jogoDaCopa():
            levarBandeira()[/!]

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 a usar a palavra-chave elif para marcar explicitamente estes ramos "else if".[/!]

[!c|java|scala]if (chuvoso()) { 
    levarGuardaChuva();
} else if (diaQuente()) {
    levarAgua();
} else if (jogoDaCopa()) {
    levarBandeira();
}[/!][!python]if chuvoso():
    levarGuardaChuva()
elif diaQuente():
    levarAgua()
elif jogoDaCopa():
    levarBandeira()[/!]

Grafitagem no mundo dos Buggles

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

Objetivo do exercício

O objetivo é então organizar um jogo de BDR entre os buggles a ensinar 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 a resumir a informação na tabela numa sequência de condicionais.

Tem que se manter a dançar enquanto houverem passos de dança para fazer, p.ex., enquanto estivermos numa célula cujo conteúdo esteja contido na tabela. a forma mais fácil de fazer isto é a usar 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 detetar se cadeias são iguais é um pouco chato em Java. Então, usamos o char getIndication[!c]Bdr[/!]() ao invés do [!java]String[/!][!c]char*[/!] readMessage(). 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 ativa que se trabalhe com caracteres ao invés de cadeias, que é muito mais simples em [!thelang].

[/!]

Dicas

Se não entendeu por que o buggle não fez os passos esperados, tente adicionar brushDown() no seu método. Isto pede ao buggle para abaixar um pincel a deixar um rastro por onde passar. Isto pode ajudá-lo a entender a trajetória dele, mas não se esqueça de remover esta chamada quando quiser testar se o seu código é uma solução válida para o exercício: pode fazer o buggle dançar, mas não pichar a pista de dança.

Quando seu programa finalmente funcionar, vá ao próximo exercício.