4)
random_equation(1)
random_equation(2)
random_equation(7)
random_equation(0) random_equation(
'8+8-8-9*10'
'6-10'
'8*6+5'
'10*2*4+3+4*5*6*10'
'9'
Initial Due Date: 2024-10-10 8:00AM
Final Due Date: 2024-10-24 4:15PM
For this assignment, 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 high-level 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. Right-click on the link, select “Save as…” or “Download 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 natural language 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 named 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 1-10 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:
'8+8-8-9*10'
'6-10'
'8*6+5'
'10*2*4+3+4*5*6*10'
'9'
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:
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 named 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
:
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).
10-9*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.
Python has a module named time
that has a variety of functionality for working with time, dates, etc. Here we will use the time
function within this modules. time
returns the number of seconds that have elapsed since January 1, 1970. For example at the time this assignment was written,
Elapsed time from an arbitrary date and time may not seem that useful. However, we can easily figure out how long a particular activity takes with that data. We first invoke time()
and record how many seconds have elapsed in a variable, then, at some later point after some time has elapsed, invoke time()
again and record the result in another variable. Thge difference between these two time readings is the elapsed time.
As with the previous function, I would suggest an incremental approach. There are many ways you could tackle this, but one would be:
input
function) and then print it out. Do this over and over again until the time has elapsed.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 (and thus the tests) 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
10-9*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, removing “dead code” that doesn’t do anything, removing testing code, 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 pa4_math_game.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.
Assessment | Requirements |
---|---|
Revision needed | Some but not all tests are passing. |
Meets Expectations | All tests pass, the required functions are implemented correctly and your implementation uses satisfactory style. |
Exemplary | All requirements for Meets Expectations, 2 creativity points, and your implementation is clear, concise, readily understood, and maintainable. |
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:
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.
As the programming assignments 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:
EOF when reading a line
often occurs when your program prompts the user for input that Gradescope doesn’t expect (and thus doesn’t provide when “playing” your game). Double check you are soliciting input in the right places.As always don’t hesitate to reach out with questions.