This worksheet focuses on threads and tkinter.
The main resources to refer to for this worksheet are:
(Lecture videos are not linked on worksheets, but are also useful to review while working on worksheets. Video links can be found in the course course Blackboard site.)
Red Light Green Light (RLGL), also known as Statues, is a playground game in which players attempt to cross from one side of a field to the other. However, to avoid disqualification, players must follow rules that limit their progress. The game is supervised by another participant, the "caller" or "curator", who stands at the end of the field that players are trying to reach.
When the caller yells out "Green Light" and turns away from field, players are allowed to move as they like (e.g. running toward the side where the caller stands). But when the caller yells "Red Light" and turns toward the field, every player must stand completely still. If the caller sees any player moving (e.g. due to failure to come to a complete stop before the caller turns), that player is disqualified from the round.
The caller alternates between "Red Light" and "Green Light" on whatever schedule they like, usually choosing a somewhat random sequence of delays so that players moving forward will be forced to stop unexpectedly. Players who reach the caller's side of the field without being disqualified win that round. The caller is informally evaluated on the basis of how many players are disqualified (with higher numbers meaning a better performance).
Make a Python program that plays RLGL, with the program functioning as the caller and the user being the only player.
Each time the user presses Enter, it corresponds to taking one step forward. Their current position is indicated by a simple text graphics depiction of the field, e.g.
The user (represented by @
) is close to the start:
start|-----@------------------------|goal
The user is near the goal:
start|---------------------------@--|goal
The line of text graphics representing the field is printed anew after each step. You can make the field as wide as you prefer, but I recommend something between 20 and 72 characters.
At random times, the program will print "RED LIGHT!" or "GREEN LIGHT!" on the screen, and the user must follow these cues. The time between messages will always be between 0.5 and 2.5 seconds. If the user presses Enter while red light is active, the game ends with a message indicating the user lost.
If the player reaches the goal, the program instead prints a congratulatory message.
Make a program with two threads. The main thread handles the user input (the function input()
will wait for the user to press enter) as well as printing the board. The other thread runs in the background and is only responsible for timing and printing the RL/GL messages.
The background thread object should be created so that it has an attribute .greenlight
that is a Boolean value, set to True
whenever "Green Light" is announced, and to False
when "Red Light" is announced. Its main .run()
method should just loop forever, flipping this attribute and printing messages with random delays.
The main thread should check the value of the .greenlight
attribute of the thread after each time the user presses Enter, and respond accordingly.
If time allows, add a feature where each announcement of a Red Light has a 0.25-second grace period before movement causes disqualification. If Enter is pressed during the grace period, the user does not move forward and does not lose the game. Green Light announcements should have no such grace period.
Here's a screencast showing a brief session of a game, including the optional grace period. (You'll notice the user presses enter after "Red Light" in one case, but the game allows it because it happened during the grace period.)
Make a tkinter GUI program that lets the user enter a decimal integer (e.g. 1546
) in a Entry
widget, and which displays the same number in a different base in another Entry
widget. The base to use should be specified using a slider (Scale
widget) which allows the selection of any base between 2
and 36
.
You can find a mockup of the GUI below, but you can use a more spartan interface if you like. For example, the labels on either side of the slider are optional.
Since base conversions are not the main point of this worksheet, I've provided a function below that takes an integer n
and base b
and returns a string that represents n
in base b
. (If you finish both exercises on this worksheet early, it would be a good idea to try to write your own function that does the same thing, without referring to this one while doing so.)
def decimal_to_base(n,b):
"""
Convert integer `n` to string in base `b`, where base-`b` digits
beyond the first 10 are given by uppercase letters a-z.
"""
DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# If n is a string or float, convert to int first.
if not isinstance(n,int):
n = int(n)
if n < 0:
raise ValueError("n must be greater than or equal to 0")
if b < 2 or b > 36:
raise ValueError("b must be between 2 and 36")
L = []
while (not L) or n > 0:
L.append(DIGITS[n%b])
n = n//b
return "".join(L[::-1])
Here's an animation showing usage of a finished GUI meeting the specs given above. In your solution, the labels and indicators next to the sliders are optional. Only a slider and two text entry boxes are required.