|
BFOIT
Introduction
Predicates |
|
Think about how the TurtleGraphics applet (or TG application) performs your programs. Instructions are executed from left to right on each line. Lines are executed one after another down the page. When the instruction to be executed is a procedure invocation, say to some procedure that you wrote, TurtleGraphics remembers where it is, performs the instructions in the procedure, then comes back and picks up where it left off. All of the instructions in your program get executed.
What if you only want some of your instructions to be interpreted when certain things are true?
In this lesson, you will learn
Boolean values are used in computer programs to control what the program does.
Let's look at a few primitive (built-in) operators that TurtleTalk has and some examples of how you can use them.
predicate n. 1 a: something that is affirmed or
denied of the subject in a proposition of logic
b: a term designating a property or relation
- Webster's New Collegiate Dictionary
So, in other words, a predicate is something that it either true or false - our boolean values. In TurtleTalk, predicates are operators that produce a boolean value as their output. Here are the first three predicates you'll need.
| Procedure | Inputs | Description | Example |
|
EQUAL? EQUALP |
value1 value2 | Outputs "true if value1 is equal to value2, "false otherwise. | EQUAL? 15 0 |
|
GREATER? GREATERP |
value1 value2 | Outputs "true if value1 is greater than value2, "false otherwise. | GREATER? 10 5 |
|
LESS? LESSP |
value1 value2 | Outputs "true if value1 is less than value2, "false otherwise. | LESS? 1 4 |
| if | <predicate> | <List-of-Instructions> |
And, the syntax of a <List-of-Instructions> is:
| [ | <TurtleTalk-Instructions> | ] |
|
|
| Figure 9.1 | |
The program draws four sets of rays projecting out from a center point. It starts out with a few very thick rays of random length but guaranteed to be the longest. Each other set progressively draws more, but shorter and thinner, rays. Here's the core part of the program. It's missing the definitions of the randomColor, randomRange, and ray procedures. randomColor outputs a random number in the legal range for color numbers. randomInRange is the procedure you wrote as an exercise back in the Output Command lesson. The ray procedure has an input that is the length of a line to draw; it just moves the turtle forward this amount and then back the amount.
to randomRay :minLen :maxLen
setc randomColor
ray randomInRange :minLen :maxLen
end
to splat :nRay :minLen :maxLen :width
setpensize :width
repeat :nRay [randomRay :minLen :maxLen right quotient 360 :nRay]
end
to main
hideturtle
splat 10 110 150 40
splat 20 80 110 20
splat 40 50 80 7
splat 80 1 0 50
end
Look closely at the images. What's ruining them is that the background color, white, is getting chosen. In the first image, the large, thick rays are missing at 180 degrees, 252 degrees, and 324 degrees. What we need is a random color, excluding the background color - white.
I can use an if command to check for a random output that is equal to the color number for white. When the comparison is true, I can substitute another color I like. Here is a procedure, an operator, which accepts two color numbers as inputs. The first is a random color number. The second input is a color number to substitute for white. It outputs the input color as long as it's not white. If the first input, the random color number matches white, it outputs the second input.
to white
output 7
end
to randomColorXWhite :color1 :color2
if equal? :color1 white [ output :color2 ]
output :color1
end
Here is the TG applet, type in a version of splat that generates patterns
that do not include white.
| TurtleGraphics Applet |
|
| Figure 9.2 |
Our first pass at the interface consists of a strip of six colored boxes, a big empty frame, and a rectangle with the label "Clear Box" in it. The first thing our program will do is draw all of these things. Doing stuff like this is commonly called initialization of the program.
The program then waits for mouseclick events. When the mouse is clicked within one of the colored boxes, the program fills in the big frame with the color clicked-on. Figure 9.3 shows what happens when the mouse is clicked within the red box.
|
| Figure 9.3 |
Writing an init Procedure
So, this program is similar to
the LabelPoints exercise in the previous lesson. In particular,
it doesn't need a main procedure. I write a main
procedure when my programs have a well-defined series of steps that are
performed - without a graphical user interface (GUI). When a GUI
determines what the program does, the program needs a set of procedures
to initialize the GUI, to draw everything. But, once this is done,
the program will wait for events generated by a user and respond to each
of them in some way. Generally, this means that the program needs
a mouseclick procedure to respond to the events created when a
mouse button is clicked in TurtleSpace
- the graphics area.
For these lessons, I'm always going to use the name "init" for the procedure that initializes a program - that gets it ready for servicing events. For this exercise, init needs to draw a strip of colored boxes, a "Clear Box" button, and a big empty frame.
mouseclick needs to check to see if the location where the mouse was clicked is in any of the colored boxes or the "Clear Box" button. If so, the large frame is filled in with the appropriate color. So, what's a common operation that's needed? How about writing an operation named "mouseInRect?" which returns true if the mouse was clicked in a specified area of TurtleSpace?
One of the most important things in writing this program is to make sure the procedure you write to draw a box or a rectangle is similar to the procedure that checks to see if the mouse is in it. What do I mean?
It will be much easier to get the program right if your procedure which draws a frame is defined with the same inputs as your procedure which draws a solid colored box, which is defined with the same inputs as your mouseInRect? procedure. Here are my suggested procedure skeletons.
to drawFrame :x :y :width :height
;draw a rectangle with lower left corner at :x, :y
end
to drawSolidRect :x :y :width :height
;draw a colored-in rectangle with lower left corner at :x, :y
end
to mouseInRect? :x :y :width :height
;output true if the mouse is within the rectangle who's lower
;left corner is at :x, :y or false if it's outside the rectangle
end
By doing this, when you draw a red box, you use the same inputs when you invoke drawSolidRect as you do when you invoke mouseInRect? to check to see if the mouse is in the red box.
;if the mouse's X coordinate is equal to or greater-than the :x input ;and the mouse's Y coordinate is equal to or greater-than the :y input ;and the mouse's X coordinate is less-than the sum of :x and :width ;and the mouse's Y coordinate is less-than the sum of :y and :height ;output "trueNow, we could write TurtleTalk source code for this. TurtleTalk does have an AND operator (I just haven't covered it yet). But, think about how complicated this expression would be. The complexity could be reduced by using a hierarchy of operators you can write. But, there's an easier way. Let's take the opposite approach to the comparisons in out body! What do I mean? Here's part of the source code.
to mouseInRect? :x :y :width :height
if less? mousex :x [output "false]
if less? mousey :y [output "false]
;if for mouse being to the right of the rectangle - outputs false
;if for mouse being above the rectangle - outputs false
output "true
end
In this case, we have four separate comparisons to see if the mouse
is outside the rectangle and if it is we return false.
If all of the comparisons turn out wrong, I output "true
since the mouse must be in the rectangle!
Built-in Operators For Combining/Manipulating Boolean Values
But just in case you really wanted to use the and boolean operator,
I'll show you how I'd build mouseInRect? with it. Since I've
been programming for a long time, it immediately occured to me that I
needed an operator that will be useful here and in other programs.
So, first I wrote an operator I named numberInRange?.
to numberInRange? :number :min :max
if greater? :number :min [output "false]
if less? :number :min [output "false]
output "true
end
I tested it and once I was convinced it was working I made a first pass at
a version of mouseInRect? that used it.
to mouseInRect? :x :y :width :height ;if and numberinRange? mousex :x sum :x difference :width 1 ; numberInRange? mousey :y sum :y difference :height 1 ; output true output "false endIn this case, the if invocation is just too long and complicated. I decided to write two more operators, one for the mousex comparison and one for the mousey comparison. Here they are.
to mousexInWidth? :x :width if numberInRange? mousex :x sum :x difference :width 1 [output "true] output "false end to mouseyInHeight? :y :height if numberInRange? mousey :y sum :y difference :height 1 [output "true] output "false endAnd with these operators, I re-entered a better version of mouseInRect?.
to mouseInRect? :x :y :width :height if and mousexInWidth? :x :width mouseyInHeight? :y :height [output "true] output "false end
| Operator | Inputs | Description | Example | |||||||||||||||
| AND | trueFalse1 trueFalse2 |
Outputs true if trueFalse1 AND trueFalse2 are true,
false otherwise.
|
AND true true | |||||||||||||||
| NOT | trueFalse | Outputs false if trueFalse is true, else true if trueFalse is false - the opposite trueFalse value. | NOT true | |||||||||||||||
| OR | trueFalse1 trueFalse2 |
Outputs true if trueFalse1 OR trueFalse2
is true, false otherwise.
|
OR false false |
Exercise: MouseQuadrants
Here is an illustration of the standard coordinate system.
Write a program that draws the X and Y axes and, when the mouse is clicked on your image, displays the name of the quadrant where the mouse was when it was clicked. As an example, if the mouse is clicked above the X axis and to the right of the Y axis, you should display "Quadrant I"
| New TurtleTalk Procedures Used In This Lesson | ||||||||||||||||||
| Name | Input | Description | Example | |||||||||||||||
| AND | trueFalse1 trueFalse2 |
Outputs true if trueFalse1 AND trueFalse2 are true,
false otherwise.
|
AND true true | |||||||||||||||
|
EQUAL? EQUALP |
value1 value2 | Outputs "true if value1 is equal to value2, "false otherwise. | EQUAL? 15 0 | |||||||||||||||
|
GREATER? GREATERP |
value1 value2 | Outputs "true if value1 is greater than value2, "false otherwise. | GREATER? 10 5 | |||||||||||||||
| IF |
trueFalse instructionList |
If the trueFalse input is true, the instructionList input is performed. If trueFalse is false, nothing is done. | IF LESS? MOUSEX 0 [ ... ] | |||||||||||||||
|
LESS? LESSP |
value1 value2 | Outputs "true if value1 is less than value2, "false otherwise. | LESS? 1 4 | |||||||||||||||
| NOT | trueFalse | Outputs false if trueFalse is true, else true if trueFalse is false - the opposite trueFalse value. | NOT true | |||||||||||||||
| OR | trueFalse1 trueFalse2 |
Outputs true if trueFalse1 OR trueFalse2
is true, false otherwise.
|
OR false false | |||||||||||||||