TI Codes: TI-84 Plus Technology
Encourage students who have some programming experience to build on their knowledge with activities that take them a little deeper into coding.
Guessing Game
Write a Simple Guessing Game
The guessing game includes several components:
1. Variable N and randInt() used to pick the number to guess.
2. A Repeat loop that repeatedly asks for a guess until the player guesses correctly.
3. The Prompt command used to get a guess from the player.
4. If conditionals and Disp used to tell the player if their guess is too high or too low.
5. Variable M and Disp used to track and report how many guesses the player made.
Guessing Game
How it Works
How the Guessing Game Works
The diagram below is a flowchart of how the program works. If you haven’t seen a flowchart before, you read it by following the arrows around the diagram, beginning at START and ending at Stop. If you spend a minute comparing this diagram to the code for [PRGM]GUESS, you’ll see that each block corresponds to 1-3 lines of the program
Step 1
Line-by-line, here’s how it works:
:randInt(1,50)➔N
Pick a random number between 1 and 50, and store that to variable N. Each time the program gets a new guess from the player, it will compare it to N to check if it’s correct.
:0➔M
Store the number of guesses made so far to variable M. Each time the player makes another guess, the program will add 1 to M, then display M at the very end of the program.
Step 2
:Repeat G=N
Repeat the code between this Repeat command and the corresponding End command until G=N. In this program, G is the guess from the user, and N is the target number, so the loop ends when the guess is equal to the number the player is trying to guess. One special quirk of Repeat: it only checks the condition (G=N) after it has completed an entire run through the loop. Therefore, we don’t have to initialize G by storing a value like 0 to it before the loop starts. If we were using a While loop, we would have to initialize G, because While checks the condition before it starts running the loop.
:Prompt G
Ask the player for a value for G, then store the number the player types into variable G
Step 3
:If G>N
:Disp "TOO HIGH"
If the guess G is larger than the target number N, display TOO HIGH so the player knows to guess lower. The If command will run the next line of the program if the condition (G>N) is true; otherwise, it will skip it.
:If<><>
:Disp "TOO LOW"
Similarly, if the guess G is smaller than the target number N, display TOO LOW. If G=N, the loop won’t have finished yet, but neither Disp command will run, because G is not greater than N, and G is also not less than N.
:M+1➔M
Add 1 to the number of guesses made.
Step 4
:End
End the loop and check the Repeat condition. If the condition G=N is false, run the loop again, starting at Repeat. If it’s true, continue with the following code after the End.
:Disp "CORRECT AFTER:"
:Disp M
:Disp "GUESSES"
Display three lines, including the number of guesses made. You could optimize this into a single Disp line with commas
Step 5
Going Further: Expand Your Game
- Let the player choose the smallest and/or largest possible number to guess. The game in this lesson picked a number between 1 and 50.
- Display the range in which the player should be guessing, here 1 to 50.
- Keep track of the high score (the lowest number of guesses made). You could keep track of other statistics as well, like the average number of guesses or the worst score (the highest number of guesses). To store information in more permanent locations than the numeric variables A-Z, take a look at the information on custom lists.
- Use Input instead of Prompt to ask for a guess.
- Find a way to [CLEAR] the screen before the game begins.
You can, of course, also use your imagination to think of other features you want to add to the game. Good luck!
Step 6
Event Loops
Moving a Letter around the Homescreen
The program that we’ll be creating in this lesson is quite short, but brings together a number of important programming concepts. We’ll be building a program around an event loop: a section of code executed over and over again that waits for and reacts to events. In this program, the events we’ll be looking for will be keypresses, and our program will respond to these events by moving a letter around the calculator’s homescreen. Event loops in computer programs might wait for a time or date, a mouse click, a key on the keyboard, or even arriving packets from the network.
Step 1
Event Loops and getKey
The following diagram shows the basic structure of an event loop-based program. It executes code to set up the loop, like initializing variables, then it continually repeats the event loop until some escape condition occurs.
Step 2
There are three major components of an event loop:
- An escape condition that defines when the event loop stops repeating. In a computer program, an escape condition might be something like exiting from the program or pressing [ESC]. In our program, we’ll check for the [CLEAR] key, and our escape condition could be expressed as “end the event loop if [CLEAR] is pressed”.
- Non-event code. In this program, we won’t have any non-event code. However, in other programs, this is code that runs regardless of whether events occur or not.
Check for (and react to) events. In this program, our events are keys being pressed. If we want to check for and react to keypresses, though, we’ll need to be able to execute or skip sections of code based on whether a key is pressed.
Step 3
To construct our event loop, we’ll need conditional statements and getKey.
getKey is a TI-Basic command that your programs can use to detect if a key has been pressed. If the user pressed a key since the last time getKey was called, getKey will return a number between 11 and 105, indicating which key was pressed (see the diagram below). If no key was pressed, it returns 0. Unlike Input and Output, the getKey command doesn’t pause your program, so you can create more complex programs and games.
Step 4
Step 5
Moving a Letter around the Homescreen
Let’s explore the MOVECHAR program. The MOVECHAR program is one of the simplest possible examples of an event loop-based program, repeatedly listening for keypress events and acting on them. The flowchart represents the MOVECHAR program. The event loop itself loops from “Redraw M” to “Check for keypresses” and then back around to “Redraw M”. The escape condition that we discussed earlier was the condition to leave the event loop; here, you can see that the only way to leave the loop is to press [CLEAR].
Note that if you’re using the TI-83 Plus or TI-84 Plus, the only differences are in the values used for the edges of the homescreen and the starting point, due to differences in the sizes of each calculator’s homescreen.
Step 6
Line-by-line, here’s how the code works:
:13➔A
:5➔B
Initialize the x- and y-coordinates of the letter that will be drawn. We don’t use the X and Y variables, because the calculator’s operating system sometimes modifies the Y variable if you use graphscreen commands. In this program, A is the x-coordinate, and B is the y-coordinate. Column 13, row 5 is roughly the center of the color calculator’s homescreen.
Step 7
:ClrHome
[CLEAR] the homescreen.
:Repeat K=45
Repeat all of the code between Repeat and End (the event loop) until the variable K equals 45 (the keycode for [CLEAR]).
Step 8
:Output(B,A,"M”)
Draw the letter M at row B, column A on the homescreen. If there was already an M on the screen at the same coordinates, it simply draws over it, so the screen doesn’t change.
:getKey➔K
Get the keycode for any key pressed since the last time getKey was called, and store it in the variable K. This returns immediately, instead of waiting for a key to be pressed: if no key was pressed, it stores 0 to K
Step 9
: If K≠0
If a key was pressed, we want to erase the letter already on the screen, because we might be moving it. If we didn’t erase it, we’d leave a trail of Ms around the homescreen.
:Output(B,A,"_”
Draw a space over the M that was on the homescreen, effectively erasing it. This line of code is only executed if K is not zero.
:If K=24 and A>1
:A-1➔A
Step 10
Step 11
:If K=26 and A<>
:A+1➔A
:If K=25 and B>1
:B-1➔B
:If K=34 and B<>
:B+1➔B
Step 12
Handle the right, up, and down arrows. Each conditional statement checks that both an arrow key has been pressed, and that the letter isn’t already at the corresponding edge of the screen.
:End
Loop back up to the Repeat command, unless K=45. If K is 45, the loop will end, and because this is the last line of the program, the program will end as well.
Step 13
Going Further: Expand MOVECHAR
With this simple event loop program that listens for and reacts to keys, you can build many fun programs and especially games.
- An easy place to start would be to make something other than an M move around the screen. Perhaps a different letter? Or a group of letters in a shape?
- Handle diagonal movement so that the letter can move in 8 directions instead of just 4. Because getKey can’t register multiple arrow keys held together, you could use the 1–9 keys as arrows instead (where 2 is down, 7 is up-left, and so on).
- If you’re familiar with drawing text on the graphscreen, try moving this program to the graphscreen. Which commands do you need to change, and which stay the same? What are the new bounds you need to use to keep the text from going off the screen?
- Try turning the MOVECHAR program into a space shooter game: the M can become your spaceship, and you might be trying to shoot asteroids before they reach you. How can you implement a weapon, and keep track of where the asteroids are and the score?
You can, of course, also use your imagination to think of features you want to add. Good luck!
Step 14
Snake
Writing a “Snake” Game
Create the Snake program on your calculator as prgmSNAKE. If you have a color-screen calculator like the TI-84 Plus CE or TI-84 Plus C Silver Edition, you can enter it exactly as shown. For the the TI-84 Plus and TI-84 Plus Silver Edition, calculators, you need to account for the fact that the homescreen is smaller
Step 1
Line-by-line, here’s how the code works:
:ClrHome
Clear the homescreen.
13➔A
:5➔B
:10➔X
:1➔P
:34➔D
Initialize all the variables to be used:
Step 2
- A is the x-coordinate of the snake’s head, and B is the y coordinate of its head. Row 5, column 13 is roughly the center of the TI-84 Plus CE’s homescreen.
- X is the length of the snake, here, 10 segments. If you wanted to make this a real snake game, you’d have to start with a small X, and increase it as the snake ate food.
- P is a pointer to the element holding the snake’s tail. L1(P) is the y coordinate of the snake’s tail, and L2(P) is the x-coordinate of the snake’s tail. As the snake moves, P moves as well, so that it always points to the end of the snake (without having to move the data in L1 and L2 forward).
- D is the direction in which the snake is heading. To reuse code you’ve seen before, we use the keycodes for up, down, left, and right (25, 34, 24, and 26, respectively) to represent the direction the snake is going.
Step 3
:X➔dim(L1)
:X➔dim(L2)
Create two lists, each X elements long, for our circular buffers of snake segment coordinates.
Step 4
:Fill(B,L1)
:Fill(A,L2)
Fill the two lists with the starting coordinates. This way, all 10 segments of the snake will start out on a single spot on the homescreen, and as the game starts, the snake will appear to grow out of that spot to its full length. Making the snake start already drawn at its full length would be more complicated.
Step 5
:Repeat K=45
As in Lesson 2, repeat the main event loop until [CLEAR] is pressed.
:Output(L1(P),L2(P)," ”)
Erase the tail of the snake. Because we’re using circular buffers, we change P to always point to the elements of L1 and L2 holding the snake’s current tail. L1(P) is the y-coordinate (the row) of the tail’s last segment, and L2(P) is the -coordinate (the column) of the last segment.
Step 6
:Output(B,A,"0")
Draw the new head. A and B always hold the coordinates of the snake’s head, and "O" just happens to look good as a snake segment. You could use any character you want instead.
:B➔L1(P)
:A➔L2(P)
Store the current head coordinates into the circular buffers. Because P+1 will point to the tail on the next iteration, P will point to the head, so we store these over the old tail coordinates at P.
Step 7
:P+1-X(P=X)➔P
Update P to point to the next element of the lists. If P is less than X, then P=X is false (0), and this simplifies to P+1➔P. If P is already pointing to the last element of the circular buffers, which means P=X, then P=X is true (1), and this simplifies to P+1-X➔P, or X+1-X➔P, or 1➔P. Thus, when P reaches the end of the lists, it will wrap around to the beginning again.
Step 8
:getKey➔K
:If max(K={24,25,26,34})
:K➔D
Handle keypresses. As always, we store the keypress in K, so that the Repeat K=45 condition can tell if [CLEAR] has been pressed. The conditional statement is a shorthand for If K=24 or K=25 or K=26 or K=34. K={24,25,26,34 produces a 4-element list, holding the elements {K=24,K=25,K=26,K=34}: that is, a series of 1s and 0s. The max() command returns the largest value in a list, so if K is equal to any of those four numbers, there will be a 1 in the resulting list, and the maximum will be 1. If K is not equal to any of those four keycodes, the list will be filled with 0s, and the maximum of the list will be 0. Therefore, the conditional will only be true if K is equal to one of those four keycodes. Moreover, if K holds an arrow key’s keycode, update D to contain a new direction for the snake to go.
Step 9
:A+(D=26)-(D=24)➔A
:B+(D=34)-(D=25)➔B
Use the direction variable D to update the coordinates of the head. If D=26 or D=24, then the snake’s head is moving horizontally. Update A (the -coordinate) accordingly. Try plugging D=26 and D=24 into the first line to see how this works. The second line updates B, the -coordinate of the head, if D=34 or D=25, which means the head is moving up or down.
Step 10
:A+26((A=0)-(A=27))➔A
:B+10((B=0)-(B=11))➔B
The preceding two lines could make the head of the snake go off the edges of the screen. If we try to draw a character off the edge of the screen, the program will end with an ERR:DOMAIN, so we need to fix it. These two lines wrap the head around the edges of the screen. For example, if it reaches the top of the screen, it will reappear at the bottom instead.
:End
Loop back up to the Repeat command, unless K=45. If K is 45, the loop will end, and because this is the last line of the program, the program will end as well.
Step 11
Going Further: Build a Complete “Snake” Game
The SNAKE game as presented contains everything you need to start building a “Snake” game. The three biggest missing pieces are: (1) a growing snake, (2) scoring, and (3) food to eat. Here’s what you could do to make a complete “Snake” game out of this basic version:
- First, you’ll need a second variable to handle a head pointer. In this version, we used P as both the head and tail pointer, because the circular buffer was always completely full.
- Next, you’ll need to have circular buffers which are bigger than the starting size of the snake, because the snake will need to be able to grow. This will lead you to some interesting design decisions: should you start with lists as large as the snake could possibly grow? Or should you expand the lists when the snake is in danger of outgrowing the buffers?
- Next, you’ll need some food for the snake to eat. How will you make sure that you don’t put the food on top of the snake? Some approaches store the contents of the homescreen in a matrix, so you can easily test which spots on the homescreen are occupied.
Step 12
- You’ll need to detect if the snake is about to (or has just) eaten the food, so that you can increment the score and the snake’s length, and place a new piece of food.
- You can go even further and add things like walls and differently-shaped levels. If you do this, you might want to strongly consider the matrix approach to easily detect when the snake has hit a wall (or its own tail).
You can, of course, also use your imagination to think of features you want to add. Good luck!
You can learn more about programming for the TI-84 Plus family of graphing calculators in “Programming the TI-83 Plus/TI-84 Plus,” by Christopher Mitchell, Ph.D.
