For this lab, you are going to be implementing a timed game where the user answers as many simple math questions as possible in a given time period.
Before you start working, make sure that you understand at a highlevel how the game is supposed to be played. We’re going to build up the final version of this program one piece at a time. As you build each piece, make sure you understand where it fits into the larger program and make sure it’s working correctly before moving on.
Download the starter file. Rightclick on the link, select “Save as…”, and save the file for this assignment. Then open the saved file with Thonny. Add your code in the places specified by the comments.
The first thing you will need is the ability to generate a random equation. Our
random equations will contain the operators +
, 
, and *
. The following
pseudocode describes one way to generate a random equation. Pseudocode is a way
to describe an algorithm in detail without getting bogged down in language
syntax (recall “syntax vs. semantics”). It is a compromise between English and
code.
generate a random number between 1 and 10 to start the equation
for each operator that you want to add on:
pick a random operator from +, , * and add it to the equation
pick a random number between 1 and 10 and add it to the equation
Using this approach, we can generate a random equation with as many operators as we would like.
Write a function called random_equation
that has a single parameter, the
number of operators to generate in the random equation, and returns a string
representing a random math equation involving the numbers 110 and operators
+
, 
, *
(note that we don’t allow for 0 because it make multiplication
too easy, and we don’t allow division because it produces floating point
results that can be impossible to guess). Your function should work for zero
operators (see example below). Here are a few example runs:
>>> random_equation(4)
'5  6  7 * 6 * 4'
>>> random_equation(1)
'3 * 7'
>>> random_equation(2)
'8  5 * 2'
>>> random_equation(7)
'8 + 7 + 4  7  2 * 3 * 2 * 4'
>>> random_equation(0)
'4'
Hints: You’ll likely need to use some sort of loop structure to get the
repetition (i.e., for
or while
). Think about which one is more appropriate
here. Also, notice that our equation is a string, so we’ll be building up a
string similar to how we did in the last assignment by appending additional
pieces.
Now that you have an equation, you will need to have some way of repeatedly prompting the user for an answer until that answer is correct. Before writing any more code, read through this whole section since there are some hints/advice at the end.
There is a function named eval
built into Python that evaluates any
expression represented as a string and returns the value represented by that
expression. We’re going to use this function to figure out what the answer is
to our random equation. For example:
>>> eq = random_equation(4)
>>> eq
'7 * 5  2  4 * 8'
>>> x = eval(eq)
>>> x
1
Notice that the value that eval
returns is an int, which we would expect. If
you’re curious, eval
can be used to evaluate more complicated string
expressions that include function calls, etc. Experiment with this if you’re curious!
Write a function called query_equation
that takes as a parameter a string
representing an equation (e.g., the return value from your random_equation
function). This function should prompt the user with the equation and then wait
for an answer from the user. If the user gets it wrong, then it will output a
message to the user indicating this and then prompt the user again with the
equation (eval
will be useful in figuring out if the user’s answer is
correct). The function should continue to prompt the user until they get the
answer right. When the user does finally get it right, the function should
print “Correct!”. The message the user gets if they answer incorrectly should
depend on how close there are:
There are many ways you can tackle this function, but I suggest an incremental approach:
Here is a quick example with query_equation
:
>>> eq = random_equation(2)
>>> eq
'5 + 9 + 7'
>>> query_equation(eq)
5 + 9 + 7 = 25
Keep trying.
5 + 9 + 7 = 22
Close. Try again.
5 + 9 + 7 = 20
Close. Try again.
5 + 9 + 7 = 21
Correct!
We now have all of the pieces we need to put together our final program. Write
a function named play_game
that has two parameters, the game duration in
seconds and the number of operators. The function should use the time
function in the time
module to time the user. As long as the elapsed time
hasn’t exceeded the specified game duration, you should present the user with
a new random equation and then keep track of how many they get correct (you should
be thinking about some kind of loop structure). When time runs out, you should
print out how many the user got correct and how long the game was actually
played for exactly as shown below (including punctuation).
109*7 = 53
Correct!
You got 1 correct in 10.424232006072998 seconds.
This function should NOT be a lot of code, but should utilize the two previous
functions that you’ve written. The key responsibility of this function is
timing and keeping track of how many the player has gotten correct. Recall from
the prelab that we can measure how much time has elapsed by first recording a
starting time and then measuring the difference between the current time
returned by time()
and the initial start time.
As with the previous function, I would suggest an incremental approach. There are many ways you could tackle this, but one would be:
A note about timing: Because we are doing the timing outside of the
query_equation
function, time will NOT expire until the user gets the answer
right. That is the actual time elapsed for the game will be longer than the
specified duration (and could be quite a bit longer). This is OK and how I
expect your implementation to work. That is keep presenting new questions to
the player as long as time has not “expired”. While there are mechanisms to
cutoff the game the moment time expires, doing so is outside the scope of this
course.
A note about testing: Your game report
You got 1 correct in 10.424232006072998 seconds.
must match this format exactly, including the same words. Keep in mind that while “correct” and “right” are synonyms in this context, Python doesn’t know that.
When your play_game
function is working, you can finish things up: Complete
your program by adding functionality to the main function, which gets called from the if __name__ == "__main__"
conditional that executes automatically when your program is run (we will learn
more about that statement later in the semester). You should ask the user if they want to
play a game. If they say “yes”, then you should prompt the user to see how long
they want to play for (in seconds) and then the game should start. If the user
does not say “yes”, just give the user a nice goodbye message.
A short instance of the game would look like:
Do you want to play a game [yes/no]? yes
How long do you want to play for [seconds]? 10
109*7 = 53
Correct!
You got 1 correct in 10.424232006072998 seconds.
At a minimum your submission should have:
random_equation
with one parameter, the number of
operators, which returns a string with a random math equation with that
number of operators (as described in the guide).query_equation
with one parameter, a string representing
an equation (e.g., the return value from your random_equation
function),
which queries the user for the correct answer until they get it right.
query_equation
should not return anything.play_game
with two parameters, the game duration in
seconds and the number of operators, which presents the user new equations
to answer (via query_equation
) until time elapses. play_game
should
print the number of correct answers and the actual time elapsed (not the
specified duration) exactly as shown in the guide.main
with no parameters, which prompts the user and launches the game as described in the guide: ask the user if they want to play a game; if no, give a goodbye message; if yes, ask how long, and then call play_game
with the amount of time as an argument.Make sure your implementation passes all Gradescope tests before adding creativity additions. When implementing your creativity additions, do not change the parameters to
the functions. In order to continue satisfying all Gradescope tests, you may need or want to make new copies of your functions, e.g., query_equation_creativity
and play_game_creativity
so that your enhancements do not change the expected output, parameters and/or return values of the required functions. If you add additional information to the game summary do so outside of the required play_game
function, i.e., make sure to print the number of correct answers and the time elapsed from within play_game as shown in the guide, as the automated tests are looking for a line with that exact format. Do not add any additional questions (i.e. with input
) to the required query_equation
or play_game
functions other than specified. Any other input should occur outside of those functions. For example, if you want to add an option for the user to play again, implement that loop in the main
function not in play_game
.
When you’re done you should have at least four functions (maybe more). Make sure that your program is properly commented:
In addition, make sure that you’ve used good coding style (including meaningful variable names, constants where relevant, vertical white space, etc.). There are numerous good candidates for constants in this lab including the range of numbers to include in the random equations, the allowed operators, etc.
Submit your program via Gradescope. Your program program file must be named lab4_math_wiz.py. You can submit multiple times, with only the most recent submission (before the due date) graded. Note that the tests performed by Gradescope are limited. Passing all of the visible tests does not guarantee that your submission correctly satisfies all of the requirements of the assignment.
Features  Points 

random_equation 

Correctly formed equations  4 
All 3 operators randomly  1 
Number varies based on input  1 
query_equation 

Print correct/incorrect correctly  2 
Loops until correct  3 
Close answers get different feedback  1 
play_game 

Generates random equation and queries user  1 
Loops until time expired  3 
Prints out game summary  1 
main 

Correctly handles user input for game starting  2 
Gets game duration  1 
Code design and style  5 
Creativity points  2 
Total  27 
As the labs get more complicated the Gradescope tests also get more complicated. A lot can go wrong in your programs and often the error message can be opaque. A couple of suggestions to help navigate Gradescope error messages:
The example shows an actual time elapsed (10.4s) that is greater than the specified duration (10s). This is expected. We can only check how much time has elapsed when the player successfully answers a question and so time may have “expired” while they were in the process of answering an equation, i.e. they started before time “expired”, but did not finish until afterwards. I want to point your attention this note in the lab: