The magazine of the Melbourne PC User Group

An Introduction to Programming with Karel the Robot
Trevor Gosbell

Computer programming is an absorbing and challenging hobby and a valuable occupational skill. It helps develop many useful intellectual abilities, including analytical thinking, creativity, and problem-solving. But most importantly, computer programming is fun.

Welcome to the first in a series of articles intended for people with a moderate level of computer experience but little or no knowledge of programming. Let's say you know what files and folders are, you can use a word processor, you don't need detailed instructions on how to install software, and if I say "Run Program X" you've got a pretty good idea where Program X is and how to get it going. That's all you need - no expertise required.

This is an introduction to computer programming, specifically object-oriented programming in the Java programming language. In the example programs and exercises you will program a robot to carry out various tasks. Although it is possible to do all of the programming exercises on paper (writing programs out and "running" them by hand), it is more fun to use a robot simulator on your computer. I will assume that you have installed the Karel J. Robot simulator - see "Cooking Up a Programming Environment" for more information.
 
In this article we will learn about the robot world, cover the basics of programming a robot, and get you started on your own programming tasks.

Get To Know Your Robot


Meet Karel the Robot. Karel and the other robots like it exist in a flat world of avenues (running north-south) and streets (running east-west), making a grid with intersections as illustrated in Figure 1. Note that the streets and avenues are numbered so it is possible to identify an intersection by the street and avenue number. An impenetrable wall runs along the robot world to the west and south, otherwise robots may wander the streets and avenues.



Figure 1

Robot Abilities

A robot is able move in the direction it is facing. Each time it moves, a robot moves from one intersection to the next - the length of exactly one block. For example, if a robot is facing north (towards the top of the screen) at the corner of 4th Avenue and 2nd Street and it is told to move, it will move to the corner of 4th Avenue and 3rd Street.

A robot can also turn 90 degrees at a time, allowing it to face the four major compass points: north, south, east, and west. But is is not able to turn to the points in between - for instance it can't face south-east. When it turns a robot stays at the same location. For example if a robot is facing north at the corner of 4th Avenue and 3rd Street and it is told to turn left, it will turn to face west but will stay standing at the corner of 4th Avenue and 3rd Street.

A robot can also manipulate objects called "beepers". Beepers are small plastic discs that emit a soft beep. If there are any beepers in the same location as the robot, it can detect the beeping. A robot can pick up a beeper if there is at least one at the intersection where it stands. A robot can put down a beeper if it is carrying at least one beeper.

Setting Tasks for a Robot

With these abilities available, we can program a robot to carry out tasks in the robot world. Let's have a look at a robot task written in the Java language. See Listing 1

Listing 1 -- a robot task

 1. Robot karel = new Robot(1, 2, East, 3);
 2. karel.move();
 3. karel.putBeeper();
 4. karel.move();
 5. karel.move();
 6. karel.move();
 7. karel.turnLeft();
 8. karel.putBeeper();
 9. karel.move();
10. karel.move();
11. karel.move();
12. karel.putBeeper();
13. karel.move();
14. karel.move();

Notice that each command ends with a semicolon. This is part of the syntax of Java and it means "the current command ends here, anything after this belongs to the next command".

Let's look at the task line by line.

The first line makes a robot and positions it in the robot world. We need to read it back to front as follows:

  • new Robot - means make a new robot
  • (1, 2, East, 3) - put the new robot at the corner of 1st Avenue and 2nd Street, make it face east, and give it 3 beepers to carry
  • Robot karel = - name the new robot "karel". The equals sign is used to assign the name karel to the new robot that we have requested. Note that the name karel can only refer to a robot because it has the "Robot" prefix. This means that in this task we can't make a non-robot object, say a bicycle, and call it karel - karel can only be a robot.
At line 2 we get our robot to move one space in the direction it is facing. Notice that we give the robot a command by using its name, putting in a dot, then adding an instruction. In this case it's like saying in English "Karel, move". In normal English, line 3 means "Karel, put down a beeper here."

In lines 4, 5, and 6 karel is told to move. At line 7 the robot is told to turn exactly 90 degrees to its left. It has not moved from where it was at the end of line 6, but it is now facing in a new direction.

Hopefully you can follow the pattern of the remaining commands. Before you go any further, try to work out what the robot does in this task. It will be easier if you sketch it out on a piece of paper.

Rev It Up

To run this task as a program, follow these steps:
  • Start up BlueJ
  • Load the project "example01" from your working folder (choose Project|Open Project... and move to your working folder). You should see a screen similar to Figure 2.
  • Right-click on the box labeled "Example01" and choose the option "new Example01()", which opens the box in Figure 3.
  • Change the "Name of Instance" field to "test" and click "OK". Figure 4 shows the new "test" box at the bottom of the screen.
  • Right-click on the "test" box and the second option is "void task()" - this is our robot's task, so click this and see what happens.


Figure 2


Figure 3


Figure 4


A window opens to display the robot world and another opens to display a "trace" of the program status. If your screen is like mine the trace window will overlap the robot world window, so just click on the title bar of the latter so you can watch the robot move. The end result is shown in Figure 5.

Have a look at the trace output and compare it with Listing 1. Notice that as each line in Listing 1 is executed the robot does something and the result of that action appears as an entry in the trace. This is an important point - computers do things very quickly but they only do one thing at a time, so each command builds on the result of the previous command.

Peek Under the Hood

Now that we've seen the robot in action, let's look at the code.

Close down the robot world and trace windows and return to the project window in BlueJ. Double-click on the "Example01" box and the edit window opens showing the code in Listing 2.

Listing 2 -- The whole program
import kareltherobot.*;

public class Example01 implements RobotTask
{
 public void task()
 {
  World.reset();
  World.setTrace(true);
  World.setVisible(true);
  Robot karel = new Robot(1, 2, East, 3);
  karel.move();
  karel.putBeeper();
  karel.move();
  karel.move();
  karel.move();
  karel.turnLeft();
  karel.putBeeper();
  karel.move();
  karel.move();
  karel.move();
  karel.putBeeper();
  karel.move();
  karel.move();
 }
}

This is the "source" code for the scenario we've just watched the robot acting out. Most of it will be familiar to you from the robot task instructions in Listing 1, but there is some new stuff there:
  • The first line isn't actually part of the program, rather it makes sure that all of the information about robots is available to the program. Details about how to make a robot and what a robot can do are stored in a special package called "kareltherobot", so we need to "import" it into our program.
  • The next line indicates that this is a program that describes a task that we want to give to a robot (a "RobotTask"). This is also where the program is named and (with more devastating originality) I have decided to call it "Example01".
  • The actual Example01 program starts on the next line with the left hand curly bracket {, and the end of the program is marked by the matching right hand curly bracket } on the last line.
  • The command public void task() indicates the start of the robot's task. The commands that make up the task are contained in another matching set of curly brackets {}.
  • The first three commands of the robot task do some housekeeping: World.reset() clears everything off the robot world (a bit like clearing all of the playing pieces off a game board before starting a new game), World.setVisible(true) displays the robot world, and World.setTrace(true) makes the trace window visible.
  • The remaining commands have already been discussed above.
Fiddle With the Engine

I get a bit frustrated by that trace window popping up in front of the robot world. So let's get rid of it.

Change the line World.setTrace(true); to read World.setTrace(false); and click the Compile button. Watch the status bar at the bottom of the window and the message "Class compiled - no syntax errors" should soon appear.

Return to the BlueJ project window and you'll notice that the "test" object is no longer available. Because the source code has changed, the "test" object is no longer valid. So to make a new one go through this dance again:
  • Right-click on "Example01" and choose the option "new Example01()".
  • Change the "Name of Instance" field to "test" and click "OK".
  • Right-click on the "test" box and select the "void task()" option.
Look Mum - no trace!

Indulge Your Inner Vandal

Let's do some deliberate damage and see how well the robot copes.

Double-click on the Example01 box to open the editor window. Now remove the semicolon from the end of the World.reset() command - remember that a semicolon is used to indicate where one command ends and another begins, so without one on the end of this command we have made a syntax error. Click Compile and notice the next line gets highlighted and the status bar says "';' expected". The compiler has noticed something fishy here and has put the highlight roughly near the trouble spot. Replace the semicolon and compile again - there should be no problems this time.
 


Figure 5


Figure 6


Figure 7

Change the command karel.turnLeft(); to karel.turnRight(); and click Compile. This time the editor highlights the trouble spot exactly and the status line says "cannot resolve symbol - method turnRight". The compiler doesn't recognise the word "turnRight". That seems very odd, but it's correct - there is no command to make the robot turn to the right! So this is another syntax error. (By the way, why don't robots need a turnRight() command? See "A harder task" below for a clue.)

Restore the karel.turnLeft() command, then in the command Robot karel = new Robot(1, 2, East, 3); change "East" to "North". Try to compile it - hey, no errors! Close the editor window, make a new Example01 object in the main window, then right-click and select void task(). This time the robot starts moving north, places two beepers and - smacks into a wall! The trace window appears and says that an "Error shutoff" has occurred.

Why did the compiler let this error through? Remember that computers are incredibly stupid - they can't work out what you're trying to do. As long as the syntax of your commands are legal, your program will compile. This is not an error of syntax - all of the commands are legal and the grammar is correct. The error was in the meaning of the commands. Such errors are commonly known as run-time errors because they only appear when you run the program. Compilers can not detect run-time errors.

Open up the editor again and alter the same line so that it reads Robot karel = new Robot(1, 2, East, 1);. This time the robot is facing east so it won't run into a wall and everything should be fine. What else could go wrong? To find out, compile and run it.

The robot has run out of beepers so it can't put down any when it is told to - another run-time error. To generalise, run-time errors occur when a legal command can't be completed. So if you tell the robot to move when it's facing a wall, the move command can't be completed. If you tell the robot to pick up a beeper but there isn't one available at its current location, then the pick up command can't be completed.

Some Tasks For You

Getting a different view
What would you need to change in Example01 to hide the robot world and only make the trace window visible? Try it and see if you're right. Is it possible to make the program work with no output at all?

Extending the robot task
In the Example01 program the robot places beepers on three corners of a square. Adjust the program so that the robot marks all four corners of the square with beepers (Figure 6).

A harder task
Adjust the Example01 program so that the robot makes a diagonal line of beepers that starts at the corner of 1st Avenue and 1st Street and ends at the corner of 4th Avenue and 4th Street (Figure 7).

Hint
To do this the robot will need to turn both left and right but robots have no turnRight() command. What happens if you get the robot to turnLeft() more than once?

Wrap up

This article:

  • introduced Karel the Robot and the robot world
  • outlined the four abilities of robots: move(), turnLeft(), putBeeper(), and pickBeeper()
  • showed how to program a task for the robot to perform
  • showed how to compile and run a robot program
  • explained the difference between syntax errors and run-time errors
In the next installment, we will cover how to teach new commands to the robot.
 
Cooking Up A Programming Environment

The Ingredients
To follow along with the programming exercises, you will need four things:

1. Java Standard Edition

Java is a programming language that is made freely available by the Sun Corporation. It's usually best to get the latest possible version, which at the time of writing is 1.4.2. It can be downloaded from http://java.sun.com/j2se/1.4.2/download.html. Java weighs-in at well over 40 megabytes so this month it has also been made available on the October Monthly CD (see pages 44-45).
System requirements are available at http://java.sun.com/j2se/1.4.2/install-windows.html. Note that Windows 95 is not supported by Java version 1.4.2, so if that's your platform you'll need to grab an earlier version from the http://java.sun.com/.

2. BlueJ

BlueJ is a programming editor developed at Monash University to help people learn to program. It can be downloaded from http://www.bluej.org/download/download.html and it can also be found on the October Monthly CD.

3. Karel J Robot

Karel J Robot is the robot simulator that we will be programming. Downloaded it from http://csis.pace.edu/~bergin/KarelJava2ed/karelpremier.zip.

4. Examples

A zip file containing the examples from the article is available from my Web site at http://member.melbpc.org.au/~tgosbell/.
 
The Method
Add your ingredients in order. First install Java, by running j2sdk-1_4_2_01-windows-i586.exe. Extra installation instructions are available at http://java.sun.com/j2se/1.4.2/install-windows.html if necessary. Take note of where you choose to install the program (maybe C:\j2se1.4.2\) - remember this and we'll refer to it as the Java Folder.

Next install BlueJ
- run bluejsetup-130.exe. Extra installation instructions are available at http://www.bluej.org/download/install.html. The installer will ask where you want BlueJ to reside (maybe C:\bluej\) - make a note again, and we'll call this the BlueJ Folder. The BlueJ installer may also ask for the name of your Java Folder.

Unzip karelpremier.zip into a folder that we'll call (with breathtaking originality) the Karel Folder.


Figure 1


Finally unzip karel-example01.zip into a folder, which we'll call the Working Folder.

Now start up BlueJ and you will be presented with the BlueJ Project Window (Figure 1). Celebrate - it works! On the menu choose Tools| Preferences, then choose the Libraries tab in the Preferences window. Click "Add", navigate to the Karel Folder and select the file "KarelJRobot.jar". Your entry should show up as in Figure 2. You will now need to exit and restart BlueJ and you are ready to start programming.


Figure 2


About Compiling

The authors of "The Structure and Interpretation of Computer Programs" http://mitpress.mit.edu/sicp/ say that "programs must be written for people to read, and only incidentally for machines to execute." At first you may find this incredibly hard to believe because very few computer programs look like attractive bedtime reading.

But it's true - programming languages exist for our convenience. Computers can't run programs in the form that we write them, programs must first be translated into machine language. Machine code looks like a random sequence of "0"s and "1"s, which is why it is often called binary code.

Programming languages exist to make programming more efficient - one command in a programming language may correspond to dozens of commands in machine code. Think how much longer it would take to program all those extra commands - and how many more mistakes you'd make - if you had to write every single command in machine language. Which is easier to read and write - the sequence of "0"s and "1"s or Java? At least Java looks remotely like English.

The process of converting a program written in a programming language (the "source code") into the equivalent program in machine language (the "binary" or "object code") is usually called "compiling" and the program that does the work is called a "compiler". The first step in compiling is to check that the syntax of the source code is all correct because the compiler can only translate source code that it "understands". If there are no errors in the source code, the translation takes place and a new binary file is produced.

At last we have a binary version of the file, which the computer is able to execute.

Don't forget that whenever a change is made to the source code, it must be compiled again or the binary file will not reflect the most recent modifications. That explains why we seem to do a lot of compiling in this article!
 

Reprinted from the October 2003 issue of PC Update, the magazine of Melbourne PC User Group, Australia

[ About Melbourne PC User Group ]