forloop is a pretty useful command.
But, you can make it even more useful if you nest one loop command inside another.
When you nest loops, it means that the inner loop will run N times for each time the outer loop does a cycle.
Try typing this code into Komodo Edit and see what it does.
You have to click the OK button a lot of times before you finish the two loops.
You can figure out how many times the innermost part of a loop will be
executed. It will be the product of all the times you go through each
loop. In the example above, that's 5 "X" loops and 3 "Y" loops. So there
3 x 5 passes for 15 tk_messageBox commands.
There's a couple of rules for using nested loops.
Now, in fact, neither of these rules is absolute, but if you break them, you better know just what you're doing and why.
For starters, lets look at the number guessing game where you use numbers from 0 to 100 and put 10 guesses on each row.
You can do that with a single loop, like the code just below this.
Dividing the contents of the variable
count by 10 returns
the row to put each button on. If you divide one whole number by
another whole number in Tcl/Tk, it returns a whole number back to
you. This is the quotient without any remainder or fractional part.
$count is less than 10,
$count / 10 will
be 0. When
$count is between 10 and 19,
10 will be 1, and so forth.
expr command's % operator divides one number by
another and gives you the remainder instead of the quotient.
If you divide 23 by 10, the quotient is 2 with a remainder of 3. So
expr 23 %10 returns 3.
The remainder of
1 % 10 is
1, the remainder
12 % 10 is
2, and so forth.
This makes a display that looks like this:
We can create the same buttons with a pair of nested loops: one loop for the rows and one for the columns.
This is a little longer than the previous code, but it's also a little
simpler. Being able to split the rows and columns into two spots means
we don't need to think about the
% operator any more.
But, it takes a lot of time to type in all of these
commands to change the value of our loop variables.
Computer programmers don't like to waste a lot of time, so there are shorter ways to things that are very common. One very common thing for computer programs to do is to add a number to the value stored in a variable.
So, there's a command to increment a variable. It's called
You use this command by telling
incr what variable you want
to add a value to, and the value to add. If you leave out the value to
add, Tcl/Tk assumes you want to add 1. The value
1 is called
a default. When you don't put some arguments onto a command line,
you get a default value .
We can rewrite the previous loop using the
and it will look like this:
It's not a big change, but it makes the program easier to read.
Using the nested loops makes it a little simpler to create the buttons on the game board.
When you've got 10 numbers in a row, the "Too High", and "Too Low" clues make sense. When the buttons are in a grid, those clues don't make so much sense. It would make more sense to say "LEFT", "RIGHT", "UP" or "DOWN". And then it's not a number guessing game, it's a position guessing game.
Instead of having a single secret number, we can change the game to have two secret numbers - a secret row and a secret column. When the player clicks too far to the left, they get told to go right, if they click to high, they get told to go down, etc.
It would be easy to write the loops like the next code. There's a problem with this. Look at it for a moment and see if you can see what the problem is. Here's a hint - the code will run just fine - it just won't do the right thing.
You might try typing it into Komodo Edit to see what it does.
You probably noticed that when you select a position to the left and
up, the code sets the
message variable to "Left", and then
overwrites that value and sets the
message variable to "Up".
When you play the game, you need to go up and down until you find the correct row, then left and right to the correct column.
That's not a fun way to play the game. We can make it better.
Just like it's pretty common to want to add one value to the contents of a variable, it's common to want to add a new string onto the end of the contents of a variable.
The command to append one string onto the end of another is
append command needs
to know the variable to append new values to, and the values to append.
incr, there is no default value for the
To make a variable with the string
first second in it,
you might do something like this:
Notice that we've got a space after the first quote in the
append command will append every single character
that you give it to the string in your variable. It won't add any new
characters (like a space) or skip any. If you left out the space,
the new contents of
message would be
Here's the code for a position guessing game using the
commands. Notice the first
if command. We'll discuss that
right after you look at this example.
if command in that example has two tests. One to
$secretX and one to
These tests are combined using the
&& symbols. The
&& means both of the tests have to be true for the
if command to accept that the test is true.
&& symbols are called boolean operators.
Boolean operators are just like the normal arithmetic operators you're familiar with like +, - and so forth.
But while arithmetic operators work with lots of numbers, the boolean operators only work with 2 values: TRUE and FALSE. We sometimes represent FALSE as a 0, and TRUE as any non-zero number, and sometimes as the words TRUE and FALSE, and sometimes we use the words yes for TRUE and no for FALSE.
The two boolean operators we use for building
|AND||$a && $b||Every argument must be true.|
|OR||$a || $b||At least one argument must be true.|
You can group sets of boolean expressions Just like you can group parts of an arithmetic expression with parentheses.
For instance, if you want to make sure that the addition is done before the
multipliction in an arithmetic expression, you'd write
(1 + 2) x 3.
With boolean algebra, you group the tests in the order you want them done.
This test below is from the
if command above. Tcl/Tk
evaluates it in 3 steps:
($x == $secretX) && ($y == $secretY)
checks to see if
$x is the same as
$secretX. If it
is, Tcl/Tk replaces that part of the command with a TRUE.
(TRUE) && ($y == $secretY)
$x is not the same as
$secretX, then we're
done. A single FALSE means that the
&& can't be TRUE.
$x is the same as
$secretX, Tcl/Tk will
$y is the same as
$secretY, and then will
replace that part of the command as necessary.
$y is the same as
$secretY, the new command will
look like this:
(TRUE) && (TRUE)
Finally, Tcl/Tk compares the results to see if they are all TRUE. In this example, they are both TRUE, so the boolean expression is TRUE.
If both of these tests are TRUE, then the
if command will
look at the action associated with it.
Take another look at the
button in the command above.
The button text is
Guess $x $y. The
$y will be replaced by the values of the x and y variables,
so the actual text will be things like Guess 2 3.
I put the
$y into the button command
so you can see how the buttons are arranged on the screen.
Do you need that text? What would happen if you had no
argument for the
button command, or if you just used a question
mark, or your name? Try changing these on the button and see what happens.
Try playing with the nested loops in Komodo Edit. Change the program to be use a 15x15 grid instead of 10x10.
The important parts of this lesson are:
incrto add a negative number to the contents of a variable to do a subtractraction.
In the next lesson, we'll learn some more things about
snack and make this program talk to us instead of using