Previous |
| Next |
There are lots of games that can always be won, and the challenge is to win them more quickly.
The last few games are ones that you can always win. The computer will tell you where to guess next, and if you follow the instructions, you'll eventually find the secret square.
We can make the game a little more interesting by keeping track of the player's best score. Now the game is a challenge to see if you can beat your best score. (Of course, the best score will be "1", but that's just a lucky guess.)
If you wrote and played the 10-button guessing game from lesson 12, you probably noticed that sometimes you got the right answer in a couple guesses, and sometimes it took more.
You could keep track of your best score with a piece of paper while you play the game, but that seems kind of silly. Why can't we make the computer remember the score and show us what the best score was.
The answer, of course, is "What a coincidence, that's what this lesson is about."
Keeping track of the score can be done with two global variables - one to track the current score, and one to save the best previous score.
Using the global variables for the current score the best score might be obvious, but we also need to show those score to the user.
There's a Tcl/Tk widget that will do this for us - it's the
label
widget that we used back in
lesson 6 and
lesson 8.
Labels are like buttons, except that they don't use a -command
argument.
You create a label just like you create a button. The first word is the
Tcl/Tk command to create a label (label
), next comes the
name of this label - a unique word that starts with a period and a
lower case letter, and then a set bunch of option/value pairs.
Here's some code to make and display a label the way we did it in lessons 6 and 8.
|
Every graphic widget in Tcl/Tk has a slightly different set of options
that it supports. For instance, buttons have a -command
option,
but labels don't have a -command
option.
We've used the label's -text
option. The labels also
have a special -textvariable
option. When we use this
option, we tell Tcl/Tk the name of a variable, and this label will
always show the value of that variable. When we use the
set
command to change the variable, Tcl/Tk will show the
new value.
Try typing this code into Komodo to see what it does. When you click the
button, it changes the value of the myVariable
variable,
and that changes what's displayed in the label.
|
Lets make a new game. We'll start out fairly simple, and then add a couple bells and whistles to make it better.
The game looks like this:
You play it by clicking buttons. Each button has a number associated with it. Each time you click a button, that number is added to your total score. You get to click 10 buttons, and the goal is to get the highest total score.
Here's the global scope code that sets things up. It sets the
best
score variable to 0, creates pairs of labels to tell
you what the best score, current turn and current score are, and
finally makes up some buttons.
Take a close look at the button creation command. We'll look at that line right after the code.
|
You probably noticed that there is no -command
for the buttons
in this code. That's unusual, isn't it?
Yeah, it's little unusual, but not completely strange.
When we create a graphic widget like a button or label in Tcl/Tk, we're
really creating an object, like the sound objects we made with
snack
.
In computer terms, an object is a command and some data all
wrapped into a single unit. For instance, the sounds we've used have a
command (like backgroundMusic
) and a set of data to send
to the speakers when the program says backgroundMusic
play
.
The Tcl/Tk widgets are the same sort of thing. We create a new
button named .b
, and there is a bunch of information
associated with the new button (like the text to display and command
to run when it's clicked). Tcl/Tk also creates a command named .b
,
and we can use that new command to change the information stored
in the button .b
We do this by calling the .b
command with special command
options, just like we play a sound by calling the sound command with
the command option play
.
One of the command arguments that works on all widgets is
configure
. What the configure
argument does
is to tell a button to change the value of an option/value pair.
For instance, we can tell Tcl/Tk what command to use on a button when
we create it, or we can configure
the -command
option later like this:
|
We can use the configure
command to change what the buttons
do after we've made them.
Here's the startGame
procedure that sets the
score
and turns
variables and then configures
the buttons with a command.
The -command
option runs another procedures called
playTurn
. The playTurn
procedure takes a
single argument - a number to add to the score.
|
The playTurn
procedure adds the number associated with
a button to your total score. If that's more than the previous best
score, it updates the best
variable. It also
counts the number of turns you've taken and stops the game
when you've made 10 guesses.
Here's what the code looks like. Take a look at the lines around the the tk_messageBox. We'll discuss that right after this code.
|
The tk_messageBox
command will return the value of the
button that the user clicks. When we use a yesno
type of
message box, it will return a yes or no. The code above
is putting up the tk_messageBox
, waiting for the user to
click a button, and then returning the yes or no depending
on the button they clicked.
The if
command is interesting. We looked at this in lesson 7 and used the if
command to
compare numeric values with code like
if {$guess == $secret}
.
We can also use the if
command to compare
strings.
Instead of the number comparison operators like ==
,
<
and >
, we use short strings to
tell the if
command how to compare the two strings.
eq | True if the strings are the same (EQual). |
ne | True if the strings are not the same (Not Equal). |
So, the tk_messageBox
code in the example says to
display the message box, and return the word in the button the
user clicks. Then compare that word to "no". If the word was "no",
exit, otherwise, we keep playing.
This game is just a guessing game. Sometimes you guess a better score than other times. A good game requires skill as well as luck.
This would be a better game if we could show the values for each button for a few seconds so the player can find the big numbers and then change all the numbers to question marks before the players click.
We can do this with the configure command. Just like we can configure the
-command
option, we can also configure the -text
option.
But we need two more commands to make this work right.
The first command we need is after
. This command makes
Tcl/Tk pause for a given number of milliseconds (there are 1000
milliseconds in a second). When we use the after
command
the program stops and the user can look at the screen.
The other command is update idle
. This command tells Tcl/Tk
to update the display now, instead of waiting until it's not
doing anything else. Normally, Tcl/Tk only updates the display when
it's not busy calculating numbers, building buttons, or something like
that.
This code will make some labels. It pauses for 1 second before making the next label. Try typing it into Komodo to see how it works.
|
Now we can make a game that requires some skill as well as luck.
To make the game look and play a bit better, I used a couple new options to the button command.
-state
| Makes the button normal or disabled.
A disabled button doesn't respond to clicks.
|
-disabbledforeground
| Defines the color to use for the text in a button when it is disabled. By default a disabled button is gray. |
Here's the code for a the full game:
|
A better game would tell you when you've managed to make a new best
score. This should happen after you've done your last turn. Add another
global variable named newHighScore
that gets initialized to
zero in startGame
.
Then modify the playTurn
procedure
to set thie variable to 1 when the best
variable is changed.
Finally, change the message in the reply box to tell you that you got
a new high score (if you did) before asking if you want to play another
game.
You might also try adding some sounds like background music, or cheers when a player gets a new high score.
Here's the important things in this lesson:
configure
the widget
after it was created.
after
command will pause a Tcl/Tk script.
update idle
command tells Tcl/Tk to modify the
display now instead of waiting until it has finished what it's
doing.
Simple games like these can store all the data they need in simple variables, as part of a command, or in the graphic widgets. More complex (ie, fun) games need more complex data, and better ways to save it.
The next lesson will start looking at bette ways to keep track of the data in your computer programs.
Previous | Next |