After these races, it's time to party! For that, we will teach the buggles to play Dance Revolution, this game beloved of some students: The player has to move the 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|c]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 // 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 (isOverBaggle()) if (x == 5) left(); else right(); [!c]stepForward();[/!][!java|scala]forward();[/!]
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 (isOverBaggle()) if (x == 5) left(); else right(); [!c]stepForward();[/!][!java|scala]forward();[/!]
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.
[/!]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.
[!scala|c|java]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|c]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|c]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.[/!]
[!c|java|scala]if (rainy()) { takeUmbrella(); } else if (hotDay()) { takeWater(); } else if (todayIsJuly4th()) { takeFlag(); }[/!][!python]if rainy(): takeUmbrella() elif hotDay(): takeWater() elif todayIsJuly4th(): takeFlag()[/!]
Buggles can tag graffitis on the ground of their world. For that, they use the four following methods:
[!c]int[/!][!java]boolean[/!] isOverMessage()[!scala]:Boolean[/!]
:
returns [!c]1[/!][!java|scala]true[/!][!python]True[/!]
if and only if there is a
message on the ground.[!c]char*[/!][!java]String[/!] readMessage()[!scala]: String[/!]
:
returns the message written on the ground (or an empty string if nothing is written).[!java|c]void[/!] writeMessage([!c]char*[/!][!java]String [/!]msg[!scala]: String[/!])
:
writes the specified message down on the ground. If there is already a message on the
ground, the new content is added at the end of the existing message.[!java|c]void [/!]clearMessage()
: clears what is written on the ground.Message | What to do | Mnemonic |
[!java|c]'R'[/!][!scala|python]"R"[/!] | Turn right and move one step forward | Right |
[!java|c]'L'[/!][!scala|python]"L"[/!] | Turn left and move one step forward | Left |
[!java|c]'I'[/!][!scala|python]"I"[/!] | Turn back (U-turn) and move one step forward | Inverse |
[!java|c]'A'[/!][!scala|python]"A"[/!] | Move one step forward | First letter of the alphabet |
[!java|c]'B'[/!][!scala|python]"B"[/!] | Move two steps forward | Second letter of the alphabet |
[!java|c]'C'[/!][!scala|python]"C"[/!] | Move three steps forward | Third letter of the alphabet |
[!java|c]'Z'[/!][!scala|python]"Z"[/!] | Move one step backward | One letter before the end of the alphabet |
[!java|c]'Y'[/!][!scala|python]"Y"[/!] | Move two steps backward | Two letters before the end of the alphabet |
[!java|c]'X'[/!][!scala|python]"X"[/!] | Move three steps backward | Three letters before the end of the alphabet |
(anything else) | Stop dancing. |
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].
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.