|
|
BFOIT |
|
Start writing your program in pieces. Each piece is written as a procedure which you define. Your procedures are simply lists of instructions. In techie terms, you are using abstraction to make your source code easier to understand and thus easier to write correctly and easier to enhance.
As you think about the steps or as you are typing in instructions, you will recognize similarities or patterns in your code. When you discover a pattern with the same instructions being used over and over again, you can reduce the amount of code by using iteration - you learned about this (the repeat command) in the last lesson. Using iteration makes your program smaller, and so, easier to understand,
But, iteration only lets you eliminate duplicated instructions, identical source code. In this lesson, you will learn how to define procedures that have inputs, also known as parameters. These inputs (their names) are used in the body of the procedure in place of specific (actual) values. When you invoke the procedure, you provide a specific (actual) value to use in place of the input, everywhere its name is in the body of the procedure.
Procedures with inputs allow you to reduce multiple, similar, patterns of instruction sequences to a single instruction. Confused? It will become clearer as this lesson progresses...
|
| Figure 6.1 |
Now, start with the top row of boxes. Write a program which draws the series of growing boxes. Your program should consist of a procedure for each box. Then, write a procedure with the name "main" which contains invocations of these procedures. Finally, invoke "main" to display the row of boxes.
If you need to refresh your memory regarding procedures, review procedure definitions and procedure definition vs invocation.
to box25
repeat 4 [forward 25 right 90]
end
to box50
repeat 4 [forward 50 right 90]
end
to main
penup setx -250 sety 12 pendown
box25
penup setx -200 pendown
box50
...
end
Since the procedures draw different sizes of boxes, I've given them different names. But, the only difference in the instructions that make-up the body of these procedures is the number of steps that the turtle is told to move forward.
Think about this scenario. Logo doesn't have an infinite set of forward commands, e.g., "fd25," "fd50," "fd75," etc... There are not commands for all possible right instructions, e.g., "rt30," "rt45," "rt90," etc... There are commands "forward" and "right" which expect an input that specifies the number of steps to move, or the number of degrees to rotate.
We obviously need the capability to define procedures that can be used in a similar manner. We need the ability to define a procedure named box that expects to get a number when it's invoked. The number will determine the size of each side of the box we draw.
What we need is called an input.
Defining a Procedure With an Input
Here is what we want...
to box :size
repeat 4 [forward :size right 90]
end
This procedure definition has an input. Similar to the way you name the procedure itself, you give the input a name, an identifier. In this example, I've chosen the name size. The colon (":") preceding the name (pronounced "dots") tells the interpreter that this word is an input and that it should use what's in it.
What do I mean, in it? Well, an input is one kind of a thing that's called a variable. Variables are containers. Inputs get a value put in them when the procedure they are part of is invoked.
Up until now, all of the programs you've written have been composed of commands with literals as arguments. Literals are constants like the number "4" in the repeat instruction in the example above. Every time box is invoked, the <List-of-Instructions> input to the repeat command is performed 4 times.
But now, the input to the forward command is a variable - the input named size. The number of steps that the turtle moves forward is equal to the input provided in an invocation of box. The turtle moves a variable number of steps everytime the Logo interpreter performs the box procedure.
Here's the TG applet. Type in the example definition of box from above and then invoke it a couple of time with different values as arguments, e.g.,
box 10
box 25
box 100
Then, see what the following repeat instruction does...
repeat 4 [ box 25 box 50 box 75 left 90 ]
| TurtleGraphics Applet |
Does this make sense?
If it's even the least bit fuzzy, before moving on, check out the way procedure definition with an input was explained in the book: "Thinking About [TLC] Logo" by clicking on this link.
So, you've reduced the number of procedures for drawing your boxes from five to one.
box25, box50, box75, box100, and box125 ---> box :size
Very nice.
But, if we look at the commands remaining which draw the line of boxes, you should see a pattern. Here is my modified main procedure which draws the line of boxes.
to main
penup setx -250 sety 12 pendown
box 25
penup setx -200 pendown
box 50
penup setx -125 pendown
box 75
penup setx -25 pendown
box 100
penup setx 100 pendown
box 125
end
I instruct the turtle to pick up the pen, move to the location of the lower-left corner of a box, and then put the pen back down.
Oh - I guess I snuck a couple of new commands in on you. You haven't seen setx or sety (unless you've visited Appendix B). The setx and sety commands move the turtle to specific coordinates in TurtleSpace. They take an integer as an input, which is the point to go to.
Back to the problem at hand... Why not move all of the remaining similar instructions into a procedure?
Procedures are allowed to have more than one input. The repeat command has two, a count and an instruction-list.
Write a new procedure named boxAt which has three inputs: the x and y coordinates of the lower-left corner of the box and the size of the box. It should contain the instructions in main that are pretty much the same - the ones that move the turtle to where the box will be drawn. Then, it should invoke box to draw the box.
Why do you think we should not simply modify the box procedure so that it has the three inputs?
Anyhow, once you have made your changes, test what you came up with by trying the following procedure invocations.
boxAt -250 12 25
boxAt -200 12 50
boxAt -125 12 75
boxAt -25 12 100
boxAt 100 12 125
Stop reading until you've tried coming up with something.
An important thing to get correct (and learn from this exercise) is the order in which your inputs are provided when you invoke the procedure. The actual values for the x and y coordinates and the size must be provided in a matching order with the inputs in the procedure definition. Specifically, if your definition of boxAt started out:
to boxAt :size :x :y
the test invocations I asked you to try would not do what I wanted them to. The test invocations expect :size to come last.
But, other than this gotcha, multiple inputs are as easy to use as single inputs.
Here is a small program which draws three cubes. Watch how the program is executed, step by step. Especially watch how how the inputs change when the procedures are invoked. As an example, when diamond is invoked, its :steps variable is replaced with a number.
The Turtle's Pen (Pixel Graphics)
I'm not going to give you the solution for the Boxes program you
are writing, but I'll help you get one step closer. In this
section, I'll tell you a little more about how the turtle draws.
Since our turtle lives inside a computer, the space it draws on is your computer's display. For you to get the turtle to draw more interesting things, like the solid colored boxes in this lesson's exercise (Figure 6.1), you need to know a little more about computer displays.
A computer display is made up of a bunch of dots, called pixels, (an abbreviation for picture elements). The pixels are objects arranged in rows and columns, each spaced an equal distance from the others. Each pixel has a value assigned to it which is its color. Back in the first lesson, you got to interact with an applet that demonstrates color values.
So, Figure 2.1 is a nice, abstract, view of our turtle's world, but here is a more accurate picture:
|
|
| Figure 6.2 |
To display a thin vertical line, the color values of a column of pixels are set to the desired color of the line. If you want a thicker vertical line, you set the color values of the pixels of a group of consecutive columns to the desired color. Figure 6.3 shows a red line that's a single pixel wide and an orange line that's three pixels wide. The orange line is actually a very thin rectangle.
|
|
| Figure 6.3 |
There are no Logo commands that let you modify pixels, but the pen that the turtle carries changes pixels as it passes over them. You control the color the pixels get set to with the setpencolor command. You also can control the width of the line that the turtle draws with the setpensize command.
So, the colored boxes that you need to draw to complete this lesson's main exercise are nothing but rectangles of pixels. How you set them is up to you. Remember back in the lesson where I introduced iteration? We drew points that were actually boxes. There's another way to create a solid colored box using lots of single-pixel-wide lines. It's now up to you to figure out how to do it.
If you are having trouble getting started, refer back to the steps for writing programs that were described in the lesson which introduced procedures. Start by writing everything you know about what needs to be done. Convert this into pseudocode and then into procedures that you write which draw the series of solid colored boxes.
Once you've tested them and they are working, modify your Boxes program such that its boxAt procedure invokes your new rectAt procedure and its coloredBoxAt procedure invokes your new fillRectAt procedure.
|
| Figure 6.4 |
Modify your program to add shadows to all of your colored boxes.
|
| Figure 6.5 |
Write procedures arc, bird, fish, and waves and then invoke them from a main procedure. Then invoke main to draw your seascape.
| New Logo Primitive Procedures Used In This Lesson | |||
| Name | Input | Description | Example |
| SETX | number | Moves the turtle horizontally to the specified absolute window position. | SETX 100 |
| SETY | number | Moves the turtle vertically to the specified absolute window position. | SETY 100 |