Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
55 views14 pages

CS101 Lecture Notes

CS101 Intro to Programming in Python Lecture Notes

Uploaded by

nxsaomsk
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
55 views14 pages

CS101 Lecture Notes

CS101 Intro to Programming in Python Lecture Notes

Uploaded by

nxsaomsk
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Learning Programming with Robots∗

Edited by Otfried Cheong and JinYeong Bak1


February 29, 2016

1 Robot world A robot will appear at the intersection of avenue 1


and street 1:
We will learn programming by solving problems
faced by a robot living in a small grid-like world.
Our robot is capable of only four basic actions:
moving one step forward, turning left, picking up
and putting down beepers. Through the magic of
programming, you will learn to have him combine
those four basic actions in order to perform very
complicated tasks.
Before we learn how to do all this, let’s have a
look at the robot’s world. Open an exercise page,
and type in this code:
We can now start giving instructions to the
from cs1robots import * robot. In Python, you give instructions to a robot
create_world() by writing the robot’s name, a dot, and the com-
mand:
A new window will open showing a new robot world
hubo.move()
at OUTPUT section, like this:

And immediately hubo will move one step forward:

Let’s try a different instruction:

hubo.turn_left()

This robot world consists of 10 vertical avenues Our robot will turn to face northwards:
and 10 horizontal streets. The robot can be placed
at any intersection of an avenue with a street. So
let’s add a robot, by typing in the following line:

hubo = Robot()

∗ These lecture notes are edited versions of the RUR-

PLE lessons by André Roberge, which can be found at


http://rur-ple.sourceforge.net/.
1 He updates this note for Python 3 and elice platform.

Email: [email protected]

1
You can now control your robot by entering com-
mands one by one—the robot executes each com- from cs1robots import *
mand as soon as you have entered it. create_world()
hubo = Robot()
hubo.set_trace("blue")
2 First program
hubo.set_pause(2)
But controlling a robot by typing in commands on ...
a keyboard is not programming. “Programming” a
robot means to design a whole sequence of instruc- The number in parentheses is the length of the
tions (an algorithm) for the robot, which is then break in seconds.
executed automatically by the robot to solve some
task.
Let’s try this: Type the following text in code 3 Bugs!
section: What happens when you mistype a command:
from cs1robots import *
hubo.Move()
create_world()
hubo = Robot()
hubo.move() (Yes, Python distinguishes lower-case and upper-
hubo.turn_left() case letters.) Make sure you try it to see exactly
hubo.move() what happens. In the future, if you see the same
hubo.turn_left() kind of complaint, it might help you discover what’s
hubo.move() wrong with your program. In other words, you will
hubo.turn_left() find how to recognize one kind of bug.
hubo.move() The following program demonstrates a different
hubo.turn_left() bug:

from cs1robots import *


Let Python interpreter run this code. A robot create_world()
world window will open in OUTPUT section, and hubo = Robot()
you will see the robot walking around a little hubo.move()
square. However, everything will happen quite fast, hubo.turn_left()
and it will be hard to see what is going on. hubo.turn_left()
The first thing we can do is to turn on a trace for hubo.turn_left()
our robot, as follows: hubo.move()
from cs1robots import *
create_world() What happens? Robots, like humans, cannot walk
hubo = Robot() through walls. If you make him hit a wall, your
hubo.set_trace("blue") program terminates.
...
4 Write programs for humans
This is much better already, as we can see precisely
what the robot did: Beginning programmers tend to think about pro-
gramming as talking to the computer, and feel
happy as long as the computer understands them.
You should, however, strive to write programs that
make it easy for other people to read your program
and understand what it does. This takes a lot of
practice and usually requires a fair bit of thinking.
In the end, such programs are more likely to be cor-
rect, and can be maintained much more easily. (In
practice, programs are never finished—there always
are new features that need to be added or behavior
that needs to be changed.)
If you also want to be able to observe the robot’s We can use a trick of writing notes meant for
movement in more detail, we can ask him to make other humans only (and not for the computer) in-
a little break after each move: side the program. We call these notes comments.

2
There are a few ways to write comments in a pro-
gram. If a line starts with a hash symbol #, then
this line is a comment and will be ignored by the
Python interpreter:

# My first program

5 Turning left and turning right


It becomes quite tedious to write and read this
We already saw that our robot can turn left, as longcode. This is because we repeat ourselves; in other
as it is by exactly 90 degrees. There is no other words, the same sequence of instructions appears
steering mechanism—our robots are rather cheap. in many different places in the program. One basic
rule of programming is: Do not repeat yourself !
In Python, one can give a simple name to a se-
Task: (Square) Write a program that makes hubo ries of instructions. For example, we can define a
walk around a bigger square of size two, like this: turn_right command:
from cs1robots import *
create_world()
hubo = Robot()
hubo.turn_left()

def turn_right():
hubo.turn_left()
hubo.turn_left()
hubo.turn_left()

hubo.move()
So how can we make the robot turn right instead turn_right()
of left? The only possible way to do this is by exe- hubo.move()
cuting three left-turns. The following program let’s turn_right()
our robot walk around a square in clock-wise direc- hubo.move()
tion: turn_right()
hubo.move()
from cs1robots import *
create_world() A function definition starts with the Python key-
hubo = Robot() word def, the name of the function, a pair of paren-
hubo.turn_left() theses, and a colon. The body of the function are
hubo.move() the instructions that are executed when the func-
# make a right turn tion is called. Each line in the body has to be in-
hubo.turn_left() dented by the exact same amount (it doesn’t matter
hubo.turn_left() how much—I always use two spaces).
hubo.turn_left() A keyword like def is a special word that can be
hubo.move() used in Python only to define a new function (it is
# make a right turn for instance not allowed to define a function named
hubo.turn_left() “def”).
hubo.turn_left()
hubo.turn_left() Task: (StepBack) Write a function step_back
hubo.move() that makes hubo go backward one step, so that
# make a right turn
hubo.move()
hubo.turn_left()
step_back()
hubo.turn_left()
hubo.turn_left()
hubo.move() will leave the robot at exactly the same position
and orientation it started with:

3
Note that we had to tell Python to create a robot
that already carries one beeper. (Try what happens
without this.)

Task: (ZigZag1) Write a program that makes


your robot visit the entire world in a zigzag fashion: 7 Worlds
So far, our robot has lived in a rather boring, empty
world. We can let him play in more interesting
worlds containing walls and beepers, by loading
such a world instead of the create_world() call:

from cs1robots import *


load_world("worlds/hurdles1.wld")
hubo = Robot()

Task: (Hurdles1) Hubo has entered a hurdles


race, with obstaces as in the world file hurdles1.wld.
Write a program that have him follow the path in-
dicated below in his way to the finish line. He has
finished when he has picked up the beeper.
Use functions to avoid repetitions and to make
your code as clear as possible.

6 Beepers
Beepers are small objects (drawn fairly big on the Avoid repetition by defining useful functions.
screen) that make a small beeping sound when they Maybe you would rather like to build a more
are turned on. A robot can only hear a beeper if interesting world. You can do that using the
he is standing right on top of them, on the same edit_world() function:
corner. He can pick them up and carry them in his
pockets, or he can put them down. from cs1robots import *
You can instruct the robot to pick up a beeper create_world(avenues=20, streets=5)
through the pick_beeper() command, or to put edit_world()
some down, through the drop_beeper() command. save_world("myworld.wld")
If you ask a robot to pick up beepers where there
are none, or to put down beepers if he doesn’t carry The edit_world function places your world in an
any, you will get an error message and your program editable state. You can click on the world to add
will terminate. and remove walls. If you click with the left mouse
The following small program will drop a beeper button on an intersection, a beeper is placed there.
at the intersection of avenue 3 and street 1: You can remove beepers with the right mouse but-
from cs1robots import * ton. Press the Return key when you are done edit-
create_world() ing. Your program will then continue and save your
hubo = Robot(beepers=1) world.
hubo.set_trace("blue")
hubo.move() 8 Top-down design
hubo.move()
hubo.drop_beeper() Let’s solve the following problem: Hubo delivers
hubo.move() newspapers in his local neighborhood. Have him
hubo.move() climb the stairs to the front door of a house, drop
the newspaper (represented by a beeper) on the top

4
step, and return to his starting point as illustrated Task: (Harvest1) It’s harvest time! Have the
below. The world file is newspaper.wld : robot pick up all the carrots (represented by beep-
ers) in this garden. The world file is harvest1.wld.
Use top-down design.

If we just type in commands to accomplish this


task, we would end up with a sequence of more than
50 commands. This requires a fair bit of typing—
and the more typing one does, the more errors can
occur!
A better way to approach such a problem is to
start with an outline:
• Climb (up) four stairs.
• Drop the newspaper. 9 Repetitions
• Turn around.
We learnt the rule: Do not repeat yourself ! We
• Climb (down) four stairs.
used functions for sequences of instructions that our
Let’s write this outline in a Pythonic form: robot needs to use repeatedly. But if we look at this
function:
climb_up_four_stairs()
hubo.drop_beeper() def turn_right():
turn_around() hubo.turn_left()
climb_down_four_stairs() hubo.turn_left()
hubo.turn_left()

This is easy to read, and instead of one large prob-


lem we now need to solve a few small problems: It still contains a lot of repetition: The same in-
How to climb up four stairs? We can decompose struction is used three times. We can rewrite this
these smaller problems even further: using a for-loop:

def climb_up_one_stair(): def turn_right():


hubo.turn_left() for i in range(3):
hubo.move() hubo.turn_left()
turn_right()
hubo.move() We will see later what this means exactly,
hubo.move() but for the moment it’s enough to know that
hubo.turn_left() will be repeated exactly three
def climb_up_four_stairs(): times.
climb_up_one_stair()
climb_up_one_stair()
Task: (Hurdles2) Redo the Hurdles1 task above
climb_up_one_stair()
using for-loops.
climb_up_one_stair()

Task: (Harvest2) Redo the Harvest1 task above


This approach to solving a given problem is called
using for-loops.
top-down design, because we started at the top of
the problem, with an outline for a solution, and
then focused on each part of the solution one-by- Task: (Harvest3) Some problem as Harvest2, but
one. for the harvest2.wld world file:

5
• The series of instructions to follow in that case
is indented, just like we had in the case of func-
tion definitions.
Let’s look at a simple example. Suppose we want
the robot to take 9 steps, picking up any beepers
that are there along the way. (We suppose that
there can be at most one beeper at a given spot.)
For example, the starting position might be like the
following:

10 If only the robot could decide. . . and we want the final position to be:
How would we solve the harvesting problem on a
world like this? (The world file is harvest3.wld.)

So, we want to:


• Take a step forward;
• Check to see if there is a beeper;
• Pick up the beeper if there is one; otherwise
ignore and keep going;
repeating the above steps 9 times. Here is how we
can do this:

def move_and_pick():
hubo.move()
if hubo.on_beeper():
It would be nice if we could just run the progrem hubo.pick_beeper()
we wrote in task Harvest2. But it doesn’t work,
because calling pick_beeper() when there is no for i in range(9):
beeper causes an error. move_and_pick()
If only hubo could check if there is a beeper, and
pick it up only when a beeper is really there. . .
The Python keyword if does exactly this: Task: (Harvest4) Modify your program for the
Harvest2 task so that it works for the world har-
if hubo.on_beeper(): vest3.wld. Note that the new program should also
hubo.pick_beeper() automatically work for the original harvest1.wld
world. Try it!
Let’s look at the meaning of the above code: To be able to harvest in the fall, you have to
• The instruction if implies that some condi- put seeds in the ground in the spring. Can we
tion, whose value is true or false, is going to write a program that will put seed potatoes in the
follow; ground, but skip any spot where there already is
• hubo.on_beeper() is a condition (or test) a potato? In other words, starting with the world
which is true if hubo is on top of a beeper and harvest3.wld, we should end up with the world of
false otherwise; harvest1.wld !
• The colon (:) precedes the series of instructions To do this, hubo needs to drop a beeper if there
that the robot must follow if the condition is is no beeper at the current location. The following
true; code will do this:

6
if not hubo.on_beeper(): from cs1robots import *
hubo.drop_beeper() create_world(avenues=5, streets=5)

The Python word not inverts the sense hubo = Robot()


of the condition: If hubo.on_beeper() hubo.set_trace("blue")
is true, then not hubo.on_beeper() is
false. If hubo.on_beeper() is false, then def move_or_turn():
not hubo.on_beeper() is true. This is the if hubo.front_is_clear():
simplest example of a Python expression. hubo.move()
else:
Task: (Plant1) Write a program that will plant hubo.turn_left()
potatoes so that the field will look like harvest1.wld
at the end. It should skip any spot where there for i in range(20):
already is a potato. (Note that you have to cre- move_or_turn()
ate your robot with sufficiently many beepers by
using hubo = Robot(beepers=36). Try your pro- On a small world this gives the following end result:
gram with an empty world and with the worlds har-
vest1.wld and harvest3.wld.

11 What else?
In addition to being able to find out if he is standing
next to one or more beepers, a robot can see if there
is a wall in front of him, blocking his way. He can
also turn his head to his left or his right and see if
there is a wall there. You can ask him to have a
look with the following tests:
We can make this more interesting by doing a
hubo.front_is_clear() “dance” if we can move forward, and dropping a
hubo.left_is_clear() beeper if we have to turn. The following program
hubo.right_is_clear() does just that, going only partly around the world:

Let’s use the first one to have the robot explore his from cs1robots import *
world. We will have him follow the boundary of create_world(avenues=5, streets=5)
his world by asking him to move forward, if there
is no wall in front of him, and turn left otherwise. hubo = Robot(beepers=100)
The following simple program is the basis of what hubo.set_trace("blue")
is needed:
def dance():
if hubo.front_is_clear(): for i in range(4):
hubo.move() hubo.turn_left()
else:
hubo.turn_left() def move_or_turn():
if hubo.front_is_clear():
We learnt a new Python keyword here: else. It dance()
introduces an alternative sequence of instructions. hubo.move()
In this example, if there is no wall in front of hubo, else:
then hubo.front_is_clear() is true, and the se- hubo.turn_left()
quence after the if line is executed. If there is hubo.drop_beeper()
a wall, then hubo.front_is_clear() is false, and
the sequence after the else line is executed. Do for i in range(18):
not forget the colon after else, and watch out for move_or_turn()
the correct indentation!
Let’s repeat this simple conditional instruction Notice how the instructions dance() and
many times to go around the world: hubo.move() are aligned after the if statement

7
and indented from it, indicating that they belong
in the same block of instructions. The instructions def move_or_turn():
hubo.turn_left() and hubo.drop_beeper() if hubo.front_is_clear():
are similarly aligned, indented from the else dance()
statement to which they belong. The result of hubo.move()
running the program is indicated below. else:
hubo.turn_left()
hubo.drop_beeper()

Now, hubo.drop_beeper() no longer belongs to


the definition of the function move_or_turn at all,
as it is not indented to be aligned with other in-
structions within the definition. It is a single in-
struction, the first in fact that the robot must fol-
low, before executing the move_or_turn() function
18 times. The result is the following:

Now, what happens if we do not align


the instruction hubo.drop_beeper() with
hubo.turn_left(), but align it instead with
the else statement, as indicated below?

def move_or_turn():
if hubo.front_is_clear():
dance()
hubo.move()
else:
hubo.turn_left() So, as you can see, much information is given
hubo.drop_beeper() through blank spaces (that is, the indentation of the
instructions within blocks). Through practice, you
will learn to use this to your advantage and realise
Now, the definition of move_or_turn() includes a
that Python allows you to write very readable code
choice resulting in either a dance and a move for-
by indenting instructions.
ward, or a left turn, followed every time by the in-
Our robot has become quite good at jumping
struction hubo.drop_beeper(). The result of run-
hurdles. He now enters races of different lengths:
ning this program is indicated below:
short sprints and long races. He knows that he has
reached the finish line when he is next to a beeper.
Below, you will find three such race courses; the
world files are hurdles1.wld, hurdles2.wld, and hur-
dles3.wld :

As you can see, after every step forward, a beeper


has been put down. Each corner now has two beep-
ers: one from the previous move to reach the corner,
and one for the left turn after reaching the corner.
Now, suppose we align the hubo.drop_beeper()
instruction with the def statement as indicated be-
low?

8
Task: (Hurdles3) Assume that there are no races The keyword pass which we introduced here is
longer than 20 units. Define a function that looks Python’s way of saying “do nothing.” It is neces-
somewhat like the following: sary, because it is not possible to write an empty se-
quence of instructions (an empty block ) in Python.
def move_jump_or_finish(): If we have more than three choices, all we need
# test for end of race to do is add other elif statements
if not hubo.on_beeper():
# is there a hurdle? def move_jump_or_finish():
if hubo.front_is_clear(): # test for end of race
hubo.move() if hubo.on_beeper():
else: pass # race is over - do nothing
jump_one_hurdle() # is there a hurdle?
elif hubo.front_is_clear():
hubo.move()
with an appropriate jump_one_hurdle() function, elif hubo.right_is_clear(): # never
so that, other than definitions, the only instruction pass
we need is: else:
jump_one_hurdle()
for i in range(20):
move_jump_or_finish()
Since we follow the bottom wall,
hubo.right_is_clear() is always false, so
Note that, in the above definition, the code is get- the pass instruction is always ignored. Note that
ting more and more indented as we introduce addi- if we had used hubo.left_is_clear() instead, we
tional tests. would have gotten stuck forever as soon as we had
reached the first hurdle. Try it for yourself!
12 If, else, if, else. . .
13 For a while. . .
The previous hurdles task required you to write
an if/else within another one, all this because we When we want to repeat some instructions until a
wanted to give three choices to the robot: finish, certain condition is satisfied, Python gives us a sim-
move or jump. You may have noticed that this pler way to write this using a new keyword: while.
forced us to indent the code further and further. Let me show you first how this would look using
Imagine what would happen if we wanted to give pseudocode:
10 mutually exclusive choices; the resulting code
would become hard to read. To help us in such While not on beeper,
situations, Python offers a keyword that represents ... keep moving;
the combination of an else statement followed by otherwise,
an if clause. That keyword is elif, which we can ... stop.
think of as an abbreviation for else if. With this
new keyword, the above code can be written as: You should agree that this expresses the same idea
as before. Using Python code, here is how we would
def move_jump_or_finish(): actually write it:
# test for end of race
if hubo.on_beeper(): while not hubo.on_beeper():
pass # race is over - do nothing hubo.move()
# is there a hurdle?
elif hubo.front_is_clear(): No more need for a for-loop with a fixed number of
hubo.move() repetitions.
else:
jump_one_hurdle() Task: (Hurdles4) Use a while loop to rewrite the
hurdles3 program so that you don’t have to use a
We can now better see, as they are indented the for-loop of fixed length. In other words, the core of
same way, that there are three possible choices. The your program should look like the following:
else condition is executed only if all the previous while not hubo.on_beeper():
conditions are false, so there is no condition associ- move_or_jump()
ated with it.

9
Task: (Harvest5) Modify your program for the think that we are done. So we need to make one
Harvest4 task so that it also works when there is move after dropping the beeper:
more than one carrot on one place, as in world file
harvest4.wld below. All carrots must be harvested, hubo.drop_beeper()
and it should also work for the previous worlds har- hubo.move()
vest1.wld and harvest3.wld. while not hubo.on_beeper():
if hubo.front_is_clear():
hubo.move()
else:
hubo.turn_left()

This works well on an empty world, but here is an


example where it does not work:

Task: (ZigZag2) Rewrite your program for


ZigZag1 so that the robot can visit an empty world
of any size in zigzag fashion. Make sure that it
works for even and odd numbers of streets and av-
enues. (You can assume that there are at least two
streets and at least two avenues.)

14 Around the world in 80 days The problem is that we assumed that we only
had to move forward or turn left to go around the
Let’s start by considering a simple problem: go world; we never took into account situations where
around the world once, assuming there is no ob- we would have wanted to make a right turn. What
stacle on the way. We have done this before, when we need to do is first to check on the right side to see
we introduced the front_is_clear() test. Here’s if there is still a wall; if not, we have to make a right
the outline of a solution which supposes that we turn. Here’s a modified program that attempts to
carry at least one beeper at the beginning: do just that:
1. Put down a beeper to mark the starting point.
2. Move forward until facing a wall. def turn_right():
3. Turn left when facing a wall. for i in range(3):
4. Repeat steps 2 and 3 until we find the beeper hubo.turn_left()
we had put down.
5. Finish when finding the beeper. hubo.drop_beeper()
The key step is 4, where we have a repeating in- hubo.move()
struction with a test. Let’s now translate the entire while not hubo.on_beeper():
solution in proper code: if hubo.right_is_clear():
turn_right()
hubo.drop_beeper() elif hubo.front_is_clear():
while not hubo.on_beeper(): hubo.move()
if hubo.front_is_clear(): else:
hubo.move() hubo.turn_left()
else:
hubo.turn_left() This still doesn’t work. The robot gets in an infinite
loop when there is no wall around him. (That’s
This does not work—the program terminates im- right: the while keyword makes it possible to write
mediately after dropping the beeper. The problem programs that never terminate.)
is that we drop the beeper, and then immedately We need to have him move after turning right:

10
15 Clarifying our intent
hubo.drop_beeper()
We seem to have designed a program that works
hubo.move()
in all situations we are likely to encounter. This
while not hubo.on_beeper():
program is to allow the robot to explore his world,
if hubo.right_is_clear():
going around once. While the program is rather
turn_right()
short, and its structure should be clear at this point,
hubo.move()
it might not be so obvious to someone who just
elif hubo.front_is_clear():
happened to see it for the first time.
hubo.move()
We discussed before that our goal should be to
else:
write programs so that they can be understood
hubo.turn_left()
by a human. It’s probably a good idea either to
add comments and/or to introduce more meaning-
But this still does not always work: ful words. Let’s start by adding comments, some-
what more verbose than we think we might need.

# Define function for turning right


def turn_right():
for i in range(3):
hubo.turn_left()

# Mark the starting point with a beeper


hubo.drop_beeper()

# Find a clear direction and start moving


while not hubo.front_is_clear():
hubo.turn_left()
hubo.move()
Do you see why? We were too hasty in moving # We know we have gone around the world
forward after putting down a beeper. We need to # when we come back to the beeper.
check if there is a wall preventing us from moving while not hubo.on_beeper():
first. Here’s a solution to the problem: if hubo.right_is_clear():
# Keep to the right
hubo.drop_beeper() turn_right()
if not hubo.front_is_clear(): hubo.move()
hubo.turn_left() elif hubo.front_is_clear():
hubo.move() # move following the right wall
while not hubo.on_beeper(): hubo.move()
# continue as before else:
# follow the wall
Can you imagine situations where this does not hubo.turn_left()
work? Well, here is one (try it!):
While this sort of clarifies our intent for each in-
struction, it is not really that helpful in summariz-
ing the method (also known as the algorithm) used
in solving the problem. Therefore, these comments
might not be as helpful to another reader as we
might have wished. Reading over the comments,
we note that the program has two parts:
1. mark the starting point;
2. follow the right wall until we come back to the
start.
Let’s rewrite this program so that these two parts
To make it work, we need to replace the if we become clearer, and writing the comments differ-
just added by a while. Try it! ently.

11
# This program lets the robot go
# around his world counterclockwise,
# stopping when he comes back to his
starting point.

def turn_right():
Even better, the same modified program can find
for i in range(3):
the exit to a maze (world file maze1.wld ):
hubo.turn_left()

def mark_starting_point_and_move():
hubo.drop_beeper()
while not hubo.front_is_clear():
hubo.turn_left()
hubo.move()

def follow_right_wall():
if hubo.right_is_clear():
# Keep to the right
turn_right()
hubo.move()
elif hubo.front_is_clear():
# move following the right wall
hubo.move()
else:
# follow the wall
17 Stepwise refinement
hubo.turn_left() We started with a simple problem to solve (going
around a rectangular world) and, by improving lit-
# end of definitions, begin solution tle by little (also called stepwise refinement), we
manage to write a program that could be used to
mark_starting_point_and_move() solve many other apparently unrelated problems.
At each step, we kept the changes small, and made
while not hubo.on_beeper(): sure we had a working solution, before considering
follow_right_wall() more complex problems. We also used more de-
scriptive names for parts of the algorithm which
Isn’t this clearer? This will also make it much easier made the program easier to read and, hopefully, to
for us to change (“maintain”) the program if we understand. This is a strategy you should use when
want to change its behaviour in the future. writing your own programs:
Steps to follow when writing a program:
16 Hurdles and mazes • start simple;
• introduce small changes, one at a time;
Change the program you just wrote to remove the • make sure that each of the changes you have
drop_beeper() instruction. After saving it, try introduced do not invalidate the work you have
this slightly modified program with the following done before;
hurdle race (world file hurdles3.wld ): • add appropriate comments that don’t simply
repeat what each instruction does; and
• choose descriptive names.

18 It’s raining!
Surprise! Other than finishing facing in an un- It was a beautifully sunny day. Hubo is playing
usual direction, the program we just wrote can solve outside with his friends. Suddenly, it started to
the hurdle problem. It also works with the uneven rain and he remembered that the windows in his
hurdle (world file hurdles4.wld ) illustrated below— house were all open. So he went back to his house
which the program we wrote before for jumping and stopped in front of the door, unsure of how to
over hurdles could not handle! proceed.

12
Verify to see if the program you wrote to help
Ami close the windows in her house can be used by
Hubo to do the same for his house. If not, change
Task: (Rain1) Help Hubo close the windows of it so that it works for both Ami and Hubo.
his house. A closed window has a beeper in front
of it. When Hubo finishes his task, he will stand in
the doorway, watching the rain fall, waiting for it 19 After the storm
to stop before he can go back and play outside, as The wind blew really hard last night. There is lit-
illustrated below. ter everywhere outside Hubo’s house. His parents
asked him to go and clean up the driveway, as well
as the path leading to the curb. They both are in
a straight line, with garbage at random places as
illustrated below.

Task: (Trash1) Hubo should collect all the litter,


and put it in the garbage can, situated north of his
starting point. The final situation should look like:
The world file is rain1.wld ; make sure Hubo car-
ries more than enough beepers to accomplish his
task.

Task: (Rain2) Ami, Hubo’s friend, lives in a big-


ger house. Ami was playing outside with Hubo
when it started raining. Help Ami close the win- To put all the trash in one pile, you will need to
dows in her house. The starting position is: use the test hubo.carries_beepers() Try some-
thing like:

while hubo.carries_beepers():
# do something

Make sure your program works for both world files:


trash1.wld and trash2.wld.

Task: (Trash2) Hubo’s parents are so proud of his


work, that they ask him to pick up all the garbage
that got blown away in their backyard during the
windstorm. Have him pick up all the garbage and
The corresponding world file is rain2.wld. bring it back with him to his starting position. Try
When Ami is finished, she too will be standing to generalize from the program you just wrote to
in the doorway of her house as illustrated below. clean up the driveway.

13
Create your own world file, corresponding to a The result looks like this:
situation like the one illustrated below. Your solu-
tion should not depend on the exact location of the
garbage, nor should it depend on the yard size!

We have two robots now—the light blue one is


hubo, the green one is ami (available colors: gray,
green, yellow, purple, blue, and light blue).
Each robot is a Python object, and by call-
ing methods of the object using the dot-notation
you can inquire about the state of the object
(as in ami.on_beeper()), or ask the object to
perform some action and change its state (as in
hubo.turn_left()).

22 Functions with parameters


Earlier, we defined a function turn_right(). It
20 The robot’s compass still works—it will make hubo turn right. But now
Our robot has a built-in compass, which allows him we have two robots—how do we make ami turn
to tell if he is facing in the north direction or not. right? Should we define a new function? And then
You can use this test in an if or while statement: again another one for every robot we make?
What we need now is a function that can work
if hubo.facing_north(): for any robot:
# do something
def turn_right(robot):
for i in range(3):
Task: (Return) Write a program that will allow robot.turn_left()
Hubo to return to his usual starting position (av-
enue 1, street 1, facing east), starting from any po- The word robot here is a function parameter.
sition and orientation in an empty world. You can When we call the function, we have to provide a
create robots with a given position and orientation: robot as a function argument:

hubo = Robot(orientation="W", turn_right(ami)


avenue=3, street=5) turn_right(hubo)

The function call turn_right(ami) executes the


21 Hubo’s family function turn_right with the parameter robot set
Let’s have a look at the following code: to refer to the robot ami.

from cs1robots import * Task: (Trash3) Rewrite your program for task
create_world() Trash2 so that Hubo and Ami work together. They
hubo = Robot("light_blue") both start at the normal starting position, and
hubo.turn_left() should work simultaneously to collect the garbage.
hubo.move() You can decide how to split the work: For instance,
for i in range(3): Ami could do the northern half of the yard, and
hubo.turn_left() Hubo the southern half. Or they can walk next to
ami = Robot("green") each other, picking up garbage in neighboring rows.
ami.move()
hubo.move()

14

You might also like