The magazine of the Melbourne PC User Group
Karel and Company — More Robots
Trevor Gosbell |
|
|
Trevor Gosbell presents Part 3 of his very popular and easy to follow
“Programming with Karel” |
Welcome to part three of Programming with Karel. In this episode we will start
controlling more than one robot and have a look at how robot names work. But
first I'll make a comment.
Just Making A Comment Here
Now that we're getting familiar with how the robot world works, let's start to
do things in a more orderly fashion. Listing 1 is a solution to the
double-decker squares problem from the previous article (see Figure 1).
There is
a new part of the syntax introduced here - the double slash '//' that marks a
"comment". In Java anything from a double slash '//' to the end of the line is
simply ignored by the compiler. Remember that computer program source code is
mainly for people to read, so the double slash allows you to make free-form
remarks in the code to help make a program easier to understand. A helpful
feature of BlueJ is that comments appear in a different colour, so it's easy to
tell what's comment and what's code. Handy, isn't it?
But Listing 1 is a bit disappointing after our last instalment where we gave so
much attention to removing unnecessary repetition. Now that we need to move the
robot into position for the second square we end up with more repetition!
Really, this is most annoying.
It's time to get some teamwork going.
|

Figure 1. |
Listing 1.
import kareltherobot.*;
public class Example03 implements RobotTask
{
public void task()
{
World.reset();
World.setTrace(false);
World.setVisible(true);
// make a new robot
SquareMaker karel = new
SquareMaker(1, 2, East, 8);
// make the first square
karel.move();
karel.makeSquare();
// move into position
// for the next square
karel.turnLeft();
karel.turnLeft();
karel.turnLeft();
karel.move();
karel.turnLeft();
karel.turnLeft();
karel.turnLeft();
// start the second square
karel.makeSquare();
karel.move();
}
} |
Fun with dick and jane
Listing 2 shows a team of two robots making the two squares. The first,
jane,
starts at the corner of 1st and 3rd, makes a square then moves aside one space.
The other,
dick, starts at 5th and 3rd but otherwise does the same job as jane.
That's all there is to making multiple robots. Knowing this, you could now make
as many robots as you like simply by thinking up a unique name and calling new
SquareMaker(); for each one.
Listing 2.
import kareltherobot.*;
public class Example03 implements RobotTask
{
public void task()
{
World.reset();
World.setTrace(false);
World.setVisible(true);
// make a new SquareMaker
SquareMaker jane = new
SquareMaker(1, 3, East, 4);
// jane makes the first square
jane.makeSquare();
jane.move();
// make another new SquareMaker
SquareMaker dick = new
SquareMaker(5, 3, East, 4);
// dick makes the second square
dick.makeSquare();
dick.move();
}
} |
And here we learn the first new thing about robot names - you can call your
robots practically anything. In fact, the name of a robot doesn't need to be a
real name or even a real word. There are a few simple rules about robot names,
but for the moment we'll just use ordinary human names.
Reduce, reuse, recycle
There is something else you need to know about robot names. Unlike your name
which is yours to keep, robot names are more like stick-on labels that can be
transferred between robots as required. Listing 3 will help to illustrate.
Listing 3.
import kareltherobot.*;
public class Example03 implements RobotTask
{
public void task()
{
World.reset();
World.setTrace(false);
World.setVisible(true);
// make a name called jane
SquareMaker jane = null;
// make a SquareMaker robot
// and call it jane
jane = new SquareMaker(1, 3, East, 4);
// jane makes the first square
jane.makeSquare();
jane.move();
// make another SquareMaker
// and call it jane also
jane = new SquareMaker(5, 3, East, 4);
// the new robot, also called
// jane, makes the second square
jane.makeSquare();
jane.move();
}
} |
Notice some subtle differences. Firstly, we make
jane
as a
SquareMaker-style name, but we don't give it a
SquareMaker
robot straight away:
// make a name called jane
SquareMaker jane = null;
Use the word null to show that jane isn't a name for anything in particular
(yet).
Next we use the name
jane
to
refer to something - a brand new
SquareMaker
robot:
// make a SquareMaker robot
// and call it jane
jane = new SquareMaker(1, 3, East, 4);
See the difference? In previous examples we did both steps on one line, that is
make a name and give that name to a new robot. Something like this:
SquareMaker jane = new SquareMaker(1, 3, East, 4);
Then it's all the same as before until we get to the second robot - and dick
doesn't make an appearance:
// make another SquareMaker
// and call it jane also
jane = new SquareMaker(5, 3, East, 4);
It looks like jane can do it all alone. But note carefully: although the name is
the same, there are still two separate robots here.
Beer and Robots
Have you ever been to a crowded party or BBQ where there's heaps of people you
don't know? Or worse, heaps of people you do know but can't remember their
names? In these circumstances, I use my old fallback: "Mate". As in, "Mate, can
you pass me a beer?" It's not a bad strategy - I don't need to know the real
name of the man by the fridge because "Mate" does the job quite nicely. It
doesn't even need to be the same person. If I come back later and there's
someone different by the fridge, "Mate, can you pass me a beer?" will still
work!
A very similar thing is happening with our robots, except the question is
jane.makeSquare();. Just like getting a beer at a BBQ, it doesn't matter that
the second time we ask the question jane refers to a different robot.
| Beer drinking may be the perfect pastime, but in this case it doesn't make a
perfect metaphor: When I go back to the fridge a third time, the man who gave me
my first beer has returned. I can repeat "Mate, can you pass me a beer?" and
(provided that he's not getting sick of me), he'll pass me another beer. But
with the robots, once I've used the name
jane
to refer to the second robot, I
can't use it to refer to the first robot anymore. I can't go back to the first
robot and say
jane.makeSquare();
because
jane
now refers to the second robot. In
fact, once I've moved the name
jane
onto the second robot I can no longer refer
to the first robot at all. Figure 2 shows how the name
jane
refers to different
things as the program progresses. |

Figure 2. |
Cup-and-Ball
In fact, that last statement is not entirely true - it is possible to refer to
the first robot again, provided that it still has a name. Let's have a look at
how robot names can be swapped around. The following explanation will make more
sense if you compile Listing 4 and watch it carefully while it runs.
Listing 4.
import kareltherobot.*;
public class Example03 implements RobotTask
{
public void task()
{
World.reset();
World.setTrace(false);
World.setVisible(true);
// make two new robot names
SquareMaker jane = null;
SquareMaker dick = null;
// make robot 1
// and call it jane
jane = new SquareMaker(1, 3, East, 4);
// make dick refer to robot 1
dick = jane;
// dick makes the first square
dick.makeSquare();
// make robot 2
// and call it jane
jane = new SquareMaker(5, 3, East, 4);
// use jane to make
// the second square
jane.makeSquare();
jane.move();
jane.move();
// make jane refer
// to robot 1 again
jane = dick;
// use jane to tell
// robot 1 what to do
jane.move();
jane.move();
}
} |
This time we start out with two unallocated robot names, jane and dick. As in
the previous example, we make a new robot and use the jane name to refer to it.
Then we get to
dick = jane;
By now you've probably got used to the idea that the equals sign is used to give
a name (on the left) to a robot (on the right). Although there are robot names
on both sides, this line works in exactly the same way - it gives the name on
the left (dick) to the robot on the right. And the robot on the right is the
same robot to which the label jane is given - the one that is facing east at the
corner of 1st and 3rd, holding four beepers. This line makes both labels -
jane
and
dick
- point to the same robot.
We prove that both names refer to the one robot in the next line, where we tell
dick to make the square - and it does just that.
Then we make a new robot and give it the name
jane.
The situation now is that
jane
refers to the second robot while
dick
still refers to the first robot. So
the next three instructions to
jane
are carried out on the second robot:
jane.makeSquare();
jane.move();
jane.move();
This is exactly what we want to happen.
Following the discussion above about
dick = jane;
we can confidently predict the result of
jane = dick;
This time the robot name on the left is
jane
and that name is being given to the
robot on the right - the robot refered to by
dick, that is the first robot. So
jane
and
dick
are both
labels for the same robot again. Knowing this, we are sure that the last two
instructions
jane.move();
jane.move();
act on the first robot, not the second.
If you've been able to follow this cup-and-ball routine, you'll notice that the
second robot no longer has a name allocated to it, so it can't be recovered and
referred to again (see Figure 3). So the key point here is: if you need to send
instructions to a robot then it must have at least one name left that refers to
it.
A Task for You
In Listing 4, when we gave the command
jane = dick;
we transferred the name
jane
from robot 2 back to robot 1, leaving robot 2 without a name and beyond reach.
Can you think of a way of swapping the robots that
jane
and
dick
refer to
without leaving any robots "orphaned"? In other words, start with
jane
referring
to robot 1 and
dick
referring to robot 2 but end with
jane
referring to robot 2
and
dick
referring to robot 1. |

Figure 3. |
Wrap up
In this episode we have covered the following points:
- how to make and control several robots at once.
- robots can have more than one name.
- a robot name can only refer to one robot at a time.
- it is possible to make a robot name refer to different robots at different
times.
- it is not possible to give instructions to a robot that doesn't have at least
one name.
Next Time
In the next episode we will branch out beyond boring squares and start to work
with other shapes.
Reprinted from the December 2003 issue of PC Update, the magazine of Melbourne PC User Group, Australia
|