KaraClock Complete
This is a complete overview of the KaraClock Exercises that lead to the implementation of the KaraClockDisplay-Example. The exercises are distributed through three Labs, as shown by the headlines here.
The material section contains an article about why I made this addition to the ClockDisplay example: ClockDisplay Example: Reflections and Improvements.
Open the Greenfoot-Kara project https://github.com/htw-imi-info1/kara-clock-lab
.
It contains several test worlds. Make sure you’ve instantiated the correct test world!
If you haven’t already done so, you need to install Greenfoot to open the scenarios. The main file is project.greenfoot
.
Lab 02
0. Count Leaves with act() loop and a field
(optional if you skip to 2. Count Leaves but also a good preparation for it)
Open
TestWorld4WithMyKara
. Make Kara move up to the tree and count the leaves found on it’s way. It should move up and count one step with each call to the act() method. It should stop (by callingGreenfoot.stop();
) either at the tree above or on the first free field.Add an accessor(getter) (public int getCount() or similar) to return the number of leaves counted so far.
1. Multi-Move
- copy the multiMove method we discussed in class from
chapter02/kara/kara-loop-examples
to DigitDisplayKara (the method definition is already there, you just need to fill it). Test it in TestWorld0 and TestWorld1. TestWorld1 contains a setup you don’t need to understand just now - just click “act” once and all Karas should be aligned in the middle like this:
Initial TestWorld1 | TestWorld1 after act() |
---|---|
- Extend Multi-Move to move backwards: Extend the multiMove(int steps)-method to allow Kara to move backwards if a negative number is passed as parameter. It should turnAround (a method with the same name might be handy), move the appropriate number of steps and turnAround again. Hint: You can get the absolute value of a number
steps
usingMath.abs(steps)
. Use TestWorld0 during the development; after you’re done test it in TestWorld2:
Initial TestWorld2 | TestWorld2 after act() |
---|---|
2. Move Up And Count
- Open TestWorld4. complete the method
public int moveUpAndCount()
inDigitDisplayKara
. It should move up and count the leaves. It should stop either at the tree above or on the first free field. It returns the number of leaves counted. Test your method by calling it from Kara’s context menu. - When you’re done, test your method in
TestWorld5
, which contains some edge cases like a full row and one with zero leaves.
TestWorld5 before | TestWorld5 output | TestWorld5 after act() |
---|---|---|
Lab 03
3. Count Leaves (and go back)
Open TestWorld4 again. Complete the method
public int count()
inDigitDisplayKara
. It should combine thepublic int moveUpAndCount()
andpublic int multiMove()
methods (that is, use them both by calling them) to walk up, count the leaves, return to the original position and return the number of leaves counted.When you’re done, test your method in
TestWorld6Count
, which contains some edge cases like a full row and one with zero leaves.
before | output | after act() |
---|---|---|
same as with TestWorld5: | exactly the same as before calling act! |
4. Increment Leaves
Open TestWorld4 again. Complete the method
public int increment()
inDigitDisplayKara
. It should callpublic int moveUpAndCount()
and then either a. add one more leaf, return to the original position usingpublic int multiMove()
and return the new leaf count (including the leaf just added) b. if the tree is reached (no more space, overflow!) return to the original position and collect all leaves on its way (hint: this is exactly like multiMove with one addition!) and return a 0 as the new leaf count.When you’re done, test your method in
TestWorld7Increment
, which contains some edge cases like a full row and one with zero leaves.
before | output | after act() |
---|---|---|
5. Decimal Number
Now, with a DigitDisplayKara that can count and increment its leaves, you can use it to build a number - where DigitDisplayKara has a placeValue (e.g. 1,10,100,1000 etc for Decimal Numbers).
Open the World
DecimalNumberWorld
- with the implemented methods, it should work! Experiment with calling act() and run().For the Curious: (optional) Duplicate
DecimalNumberWorld
to create a number with a different base - e.g.BinaryNumberWorld
for base 2. Change the BASE constant to 2 and try it out by calling act() and run().
Lab 04
6. Initialize DigitDisplayKara (set count of leaves)
In order to be able to set the clock to a given time, each digit needs to be able to initialize with a given number of leaves.
This could be achieved with the same number of ticks, but would take some time and would not be as elegant.
You can use the DecimalNumberWorld to test it. After completed, call DisplayKara’s setValue(1234567890);
to achieve the pattern in part 5.
7. The first Kara Clock
Now, with your completed DigitalDisplayKara, the first Kara Clock can be built.
Open ClockDisplayWorld1
- it contains three DigitDisplayKaras: one for minutes, one for ten minutes, and one for hours.
Experiment a bit with it!
Showing 24 hours is difficult though - 24 leaves would be too much, using two digits - one for 10 hours, one for single hours - would need to toggle the limit for the single hour DigitDisplayKara between 10 and 4.
If you want a real clock open ClockDisplayWorld12Hours
. It starts a thread and calls tick() every second, you can start and stop it using the
respective methods in ClockDisplayKara
8. The 12 Hour Clock with am/pm
To show all 24 hours, a 12 hours am/pm is a good solution for the Kara-Clock!
The first step of changing it to a proper 12h clock with am/pm display has
already been made in ClockDisplayWorld12Hours
. It uses a special HoursDisplayKara
for the hours, which shows a “12” instead of the “0”. Find the getDisplayText(int count)
to see how this is implemented. You can use this as a guide to create
an AmPmDisplayKara that is also a subclass of DigitDisplayKara and only overrides the public String getDisplayText(int count)
(note that this is only used to set the text below the lower tree line.)
Use ClockDisplayWorldAmPm
(which is a copy of ClockDisplayWorld12Hours
) to implement this.
Find and read its prepareColumns()
method to understand how the clock display is built and what you need
to do to add another digit.
Technically, the ClockDisplayWorld is just a number with different rollOverLimits for each digit. The place value has to be the product of the previous (mostly right) digit and its place value:
am/pm | hours | ten minutes | minutes | |
---|---|---|---|---|
limit | 2 | 12 | 6 | 10 |
placeValue | 12*60 | 6*10 | 10*1 | 1 |
Your task is to add the am/pm display.
It is just another digit with a place value of 12 hours, and should show am/pm instead of 0 and 1. Also, it has a special (quite illogical) position at the end, eg. 12:00 am.
To enable the DisplayKara to find and walk to the next DigitDisplayKara, each digit stores the number of steps (which may be
negative as it is simply passed to multiMove() ) in its field stepsToNextDigit
which can be set with the constructor:
public DigitDisplayKara(int rollOverLimit, long placeValue, int stepsToNextDigit)