Buggle Dance Revolution (BDR)

Today is a great day: we will learn the buggles to play Dance Revolution, this game beloved of some students where the player has to move its feet on the carpet according to the instructions presented on the screen, and following the music. But before that, we have some details to study first.

[!java|scala]

Conditionals without curly braces

There is one detail we omitted about the conditional syntax: if a branch contains only one instruction, then the curly braces become optional. So, the two chunk of code are equivalent:

if (condition) {
    whatToDoIfTheConditionIsTrue();
} else {
    whatToDoElse();
}
if (condition) 
    whatToDoIfTheConditionIsTrue();
else
    whatToDoElse();

Actually, you can do the same for loops body that are reduced to one instruction only. But beware, this becomes dangerous if you chain the if instructions like this:

if (isOverBaggle())    
     if (x == 5)
          left();
else
     right();
forward();

In fact, it does not turn right when there is no baggle on the ground AND x equals 5, but when the buggle found a baggle on the ground and x equals anything but 5. Putting this otherwise, the buggle understands the previous code as if it were written the following way (note that the else were moved to the right):

if (isOverBaggle())    
        if (x == 5)
            left();
        else
            right();
forward();

The first lesson of this is that the indentation is very important to help humans understanding, even if it does not change the actual meaning of the code. We could have written the following code and obtain the same result. But if you want a human to read and review your code, you really want to indent it correctly. That's for example the case if you want a professor to read it (to grade it or to answer a question about it), or if you want to reuse your code later, or even if you need to debug your code yourself.

if (isOverBaggle()) if (x == 5) left(); else right(); forward();

The second lesson is that a else branch always connects to the closest if. This may be a bit troublesome in some case, and it may be easier to add more braces than strictly needed to remove any ambiguity.

[/!]

Chaining conditionals

You sometimes want to ask the buggle something similar to:

if it's raining, take an umbrella;
if not, and if it's a hot day, take a bottle of water;
if not and if it's July 4th, take an American flag

The trap is that we want at most one of these actions to be taken. That is to say, if it's raining a very hot July 4th, we don't want the buggle to get outside with an umbrella, some water and a flag, but simply with an umbrella. The following code is thus WRONG.

[!java|scala]if (rainy())
    takeUmbrella();
if (hot())
    takeWater();
if (todayIsJuly4th())
    takeFlag();[/!][!python]if rainy():
    takeUmbrella()
if hot():
    takeWater()
if todayIsJuly4th():
    takeFlag()[/!]

Indeed, since the conditions are evaluated one after the other, there is a risk that you go to the July 4th march on a rainy day. Instead, we should use something like this to ensure that once we found a true condition, we won't evaluate the next ones.

[!java|scala]if (rainy()) {
    takeUmbrella();
} else {
    if (hotDay()) {
        takeWater();
    } else {
        if (todayIsJuly4th()) {
            takeFlag();
        }
    }
}[/!][!python]if rainy():
    takeUmbrella()
else:
    if hotDay():
        takeWater()
    else:
        if todayIsJuly4th():
            takeFlag()[/!]

Unfortunately, such a cascade of conditionals is quite difficult to read. It is better to [!java|scala]omit the curly braces for the else statements. Some languages even introduce a specific construct for these else if, but not [!thelang].[/!] [!python]change the sub-blocks using the elif keyword to mark explicitly these "else if" branches.[/!]

[!java|scala]if (rainy()) { 
    takeUmbrella();
} else if (hotDay()) {
    takeWater();
} else if (todayIsJuly4th()) {
    takeFlag();
}[/!][!python]if rainy():
    takeUmbrella()
elif hotDay():
    takeWater()
elif todayIsJuly4th():
    takeFlag()[/!]

Graffiti in the Buggle World

Buggles can tag graffitis on the ground of their world. For that, they use the four following methods:

Exercise goal

The goal is then to organize a BDR game between the buggles by learning them to move according to the instructions written on the ground. These instructions are messages written on the ground, with the following signification:
Message What to do Mnemonic
[!java]'R'[/!][!scala|python]"R"[/!]Turn right and move one step forwardRight
[!java]'L'[/!][!scala|python]"L"[/!]Turn left and move one step forwardLeft
[!java]'I'[/!][!scala|python]"I"[/!]Turn back (U-turn) and move one step forwardInverse
[!java]'A'[/!][!scala|python]"A"[/!]Move one step forwardFirst letter of the alphabet
[!java]'B'[/!][!scala|python]"B"[/!]Move two steps forwardSecond letter of the alphabet
[!java]'C'[/!][!scala|python]"C"[/!]Move three steps forwardThird letter of the alphabet
[!java]'Z'[/!][!scala|python]"Z"[/!]Move one step backwardOne letter before the end of the alphabet
[!java]'Y'[/!][!scala|python]"Y"[/!]Move two steps backwardTwo letters before the end of the alphabet
[!java]'X'[/!][!scala|python]"X"[/!]Move three steps backwardThree letters before the end of the alphabet
(anything else)Stop dancing.

Indications

This exercise may seem a bit complex at the first glance, but it comes down to summarizing the information of the table in a sequence of conditionals.

You have to keep dancing as long as there is some dancing steps to do, i.e., as long as we are not in cell which content is not 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 [!java|scala]false[/!][!python]False[/!], and switched to [!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]

Another subtlety is that detecting if strings are equals is a bit annoying in Java. So, we use the char getIndication() instead of String 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 Java.

[/!]

Tips and Hints

If you fail to understand why the buggle does not execute the expected steps, try adding brushDown() in your method. This asks the buggle to put down a brush leaving a trail when it moves. It should help you understanding its trajectory, but do not forget to remove this call when you want to test whether your code is a valid solution to the exercise: you are asked to let the buggle dance, not to vandalize the dance floor.

When your program finally works, move on to the next exercise.