So far, our types are int, string and float. This whole section is adding a new one called Boolean for true/false variables (boolean is the math word for “true/false math.”) They’re really very simple, and we could have seen them back in the if chapters.
I waited this long since we didn’t really need them so far. Plus, now that we know lots of other things, we can go back and see more tricks using bools. For example, functions returning bools, or using them to untangle some messy nested ifs.
The official name for the type is bool. Like int, it’s all lower-case. Since it’s a type, you can declare variables with it: bool a;.
bool literals are true and false. Those are built-in computer words, like numbers, meaning you can say a=true;. Those are all there are, which is sort of a new thing. An int can be any of a billion different numbers, strings can be any word in the dictionary, plus lots more. bools can only ever be true or false. Exs:
It takes a little to get used to true and false. They aren’t strings and they aren’t variables. If it helps, true is stored as a 1 and false as a 0. But they officially count as type bool. For fun, some more examples, mostly errors:
The “math” you can do to a bool should be familiar: you can use && and || in the exact way we did before. Can also use not(!) (explanation point) to flip true/false(this is also the same as before.) Some examples that do nothing useful except show rules:
These look funny for two reasons: 1) we never used these outside of an if before,
and 2) we always got true/false using compares (ex: x==0, y>0.) But, the computer
doesn’t care. Where-ever math is, the computer solves it. If something is false
because we computed it, or because we just typed in false, that’s all the same to the
computer.
The answers to comparisons are bools, which means you can assign them. These set bool variables based on compares (they still don’t do anything useful):
Those are easy if you cover up the first parts. We’ve seen n>0 and n>=1 && n<=10 plenty of times. We know how to convert them into true/false. If it helps, draw a little if( ) in pencil around them.
If n is 12, isPositive=n>0; sets it to true.
These next two use == compares, which looks extra weird mixed with assignment =. The trick is the same: figure the true/false answer, then assign:
If w is "duck", then isCat will be false. If n is 77, isLucky will be true.
Before, I said the rule for the test in an if was it had to be something true or false. The actual rule is it has to be a bool. Things like n>0 or x==1 || x==6 are officially boolean expressions and give a bool result.
But if’s don’t especially like fancy expressions. Like everything else, you can give them an actual bool value (true or false,) or a bool variable, or a bool expression (what we’ve been doing.)
The simplest examples are using literals. These are useless, but they are legal:
These are confusing because they’re so simple. The first one is like if(1==1), but
even simpler. The second is like if(1>2), but even simpler.
A more useful trick is using bool variables inside ifs. Some examples using a bool named isReady:
The first one if(isReady) is the most common way to use bools and ifs. The if runs when isReady is true. The if-else below is nothing special. I just wanted to show that any kind of if can use a bool variable in the test.
The line with “B”, if(isReady==true) is the same thing, and is also legal. It just works out that the ==true isn’t needed. Most people leave it out. For example, if((n>0)==true) is legal, but not needed. Use ==true whenever you think it looks nicer.
The last two lines are the same – they run when isReady is false.
if(isReady==false) should be obvious. if(!isReady) is a little more common.
Most people read it as “if not isReady”. Sometimes if(b==false) looks nicer, and
sometimes if(!b) does. I use both about equally.
bools with && and || are nothing special. Assume we have bool a,b,c;. Here are some legal examples using and/or combinations:
We can also mix bool variables and regular compares:
One use for bools is to compute and save an if-test, or part of one, then use it later. Sometimes that saves you from computing the same thing twice, and sometimes it makes the if easier to read.
Here’s an example of an if spread out over a few lines:
This is the same idea as using a temporary variable for math. The second version pre-computes n>=100 and saves it. We couldn’t save a true/false before, but now we can. Then if(big) uses the saved value. A longer example of the same thing:
The trick works with parts of if-tests. In this example, there are a lot of ways to win, and I use a temporary bool to save each one:
If we tried to write this as one big if, we’d have to spread it across lines
anyway. This way we get to use helpful variable names, making it easier to
read.
Precomputing tests can simplify my “which xy quadrant” example from back in the if chapter. Here’s a nicer rewrite using bool variables (remember, positive x & y is quadrant 1, and so on):
This used xIsPos twice, so we saved some typing there. It only used
yIsPos once, but I think it still looks nice, computing both together on
top.
Here’s a very long example using bools to precompute possible answers. We’re making a game that rolls three dice, and you get points for things like 3-of-a-kind, a pair, a straight (like 234 or 345,) or a wrap-around straight (561 or 612). The first part rolls the dice and sorts them. Sorting three numbers has nothing to do with bools, but is fun:
Sorting like this is very, very sneaky, but it’s a neat example of ifs. If you want, try it with combinations of a,b,c= 321, 213, 312 ... . But all you have to know for the rest is that this really does sort them.
Now for the interesting part. I’ll use a bool to hold each “fact.” I don’t want to worry right now about how many points a pair or straight is worth. For this part, I just want to compute & save each fact:
I think that looks really nice: the left side with triples, pair …makes it easy to see we’re computing “do we have any of these special rolls?” And having each one on a line by itself, after the name, makes it easy to see which math is computing which thing (imagine instead all that math was in a very long if. Ugg.)
The math is also somewhat interesting, because they’re sorted. Some comments: triples doesn’t need to compare a and c. pair, can also skip comparing a and c (we can’t have 323.) pair also checks triples==false so we don’t double-count 333 as a triple and pair.
straight seems obvious, but I still had to check it three times to be sure it said
“b is one more than a, c is one more than b.” For wrapStraight, I just
listed both possibilities (561 or 612.) Cheesy, but not too long and easy to
read.
To make this next part really interesting, pretend there are three versions of the game where different rolls give different points (I just made up some rules and what amounts you win.) This checks the game version, then uses the bools to figure results:
Because we computed triples and so on ahead of time, and gave them nice
names, the lines in this part are easy to read. if(triples) winChips=30; says
exactly what it does.
For real, I only do this for long, ugly ifs. This dice game is an example of when I would, but probably nothing simpler.
Now that bool is a type, functions can return them. Their main use is for putting a function inside of an if. Suppose there’s some long compare that we use a lot – why wouldn’t we want to write a function for it?
A good one is checking whether two numbers are close together. We already know how to do that with if’s. We only need to wrap a function around them. I’ll name it isCloseEnough:
As a simple use, b=isCloseEnough(5,9); makes b false. But the best uses are inside of an if:
The inside of the if jumps to the function, runs it, and returns true if they were close together. It’s a normal function call. Then the if continues. There aren’t any new rules here, but it’s certainly a new trick.
Notice how it ends with two close-parens. I left some space, but most people
smush them together.
Two more sample uses:
A fun trick is to add print("comparing "+a+" and "+b); as the first line in
isCloseEnough. In the last example, you’d see it print maybe “comparing 1 and 0”
then “comparing 2 and 0.”
You could also use if(isCloseEnough(x,0)==true), but don’t need to. If you
want to check whether two things aren’t close, can use if( isCloseEnough(n1,n2)
== false) or if(!isCloseEnough(n1,n2) ).
bool functions aren’t limited to standard math. A really nice use of a bool-returning function is to simplify some of our personal tests.
Suppose we’re using 0-6 for day of the week, where Sunday is 0. Here are some functions that “know” the days, and use them:
Even though these are short, you can see how nice this trick is by comparing with and without a function:
In the second one, it’s really obvious that you’re checking for the weekend. The
first is also easier to write the wrong way – maybe you forget whether Sunday is 0 or
1.
You can assign a bool function result to a variable. It might be helpful if you reuse that value a lot:
A bool parameter can be used to add an option to a function. For example, my very old resetToLeft function might have an option to give y a random value:
resetToLeft(false); has y centered, at 0. resetToLeft(true); tells it to roll a
random value for y. A harder one: resetToLeft(laps>=10); randomizes y starting
at the 10th lap. As usual, it works out the math first. laps>=10 is either true of
false.
We often use this with default parameters. If we rarely randomize we’d write void resetToLeft(bool randomY=false). That lets us use resetToLeft(); most places, with a true stuck in for the few times we need to randomize.
Like any other variable, bools can be created to remember things. They can’t count,
but they are good for remembering “did that happen yet?” things. We usually call
that a flag.
In this example, I want to take the wrap-around moving Cube code, and make it “bend” halfway across by rolling a random y-speed. My first attempt has a bug: when we get halfway across, it rerolls ySpd, but does it every step, making us twitch as we move:
The problem is, it rolls a random speed for y when it passes midway, at 0, But during the next move, it doesn’t remember that it’s already done it, so does it again, and again.
We can use an extra bool to remember we’ve already done it. I’ll name it bent. False means we haven’t bent yet, true means we have:
The first if says “if we’re past the middle and haven’t bent yet.” Then inside,
bent=true; makes sure we don’t do it again. When we restart a lap, we reset bent
back to false, allowing a bend for this new lap.
When someone says “use a flag,” this is all they’re saying – declare an extra bool variable. Setting it true or false is called setting or resetting the flag. The term comes from curbside mailbox flags (the ones you set to up when you put outgoing mail into them).
Sometimes it’s nice to compute a bool a bit little at a time. Suppose we want to check whether n1 through n4 are all positive:
Notice how it starts true, and any one failure makes it false. The other pattern than works, for certain problems, it starting false, and if even one person is happy, it become true.
Of course, we could have written it in one big or:
if(n1<=0 && n2<=0 && n3<=0 && n4<=0) allArePositive=false;
Here’s one where we have to do a little more math for each check. We want to see a movie, but any one thing can prevent that:
Notice it follows the same pattern. We start false, and each test might set it to
true.
This wouldn’t fit very well into an if, but we could have used a trick from the previous section, making a bool for each, then a big if checking them all:
Sometimes you want to temporarily enable or disable an if. Putting a true or false is a cheap way to do that. For example, you’re testing a mini-game and want to disable a 10 second time-out:
You can also use if(true) as a placeholder when you’re writing the program. Suppose you have plans for being out-of-ammo (but aren’t even close to writing it yet.) You might do this in the firing code:
All that does is give you a code-reminder, and maybe makes it a little easier to
add the real ammo-test later. I only use this trick when I’m sure I’ll be adding
something, and I know this is where it should go, and I want to mark the
spot.
Pulling a test into a bool can help with debugging. Suppose we have if(x*y<z/q) (I just made up some random, complicated-looking equation) and it’s working funny. We’d like to simplify it for testing. First we rewrite it like this:
No change, so far. But now we can change it by adding a new line. This temporarily tests x*y<10:
When you change a program for testing, it can often be difficult to remember everything you did and to change it all back. Any little thing like this can help.