Python Mini-Projects - a Maths Quiz Game | Matthew Funcke | Skillshare

Python Mini-Projects - a Maths Quiz Game

Matthew Funcke

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
6 Lessons (26m)
    • 1. Intro

      1:35
    • 2. Evaluating Equations

      3:41
    • 3. Side Note - Understanding Alternatives

      2:26
    • 4. Generating Questions

      9:28
    • 5. The Game Loop

      7:15
    • 6. Summary and Feedback

      1:18
54 students are watching this class

About This Class

In this course we'll show you step by step how to create a quiz game in Python. The goal is to show you how various programming concepts can be brought together to create a fully functional real-world application.

We won't deep dive into any single topic - very basic Python knowledge is assumed - but rather we explain and demonstrate things like:

  • How to flesh out a method's logic.
  • How to┬áhandle unexpected input.
  • Keeping┬ácode nicely separated.
  • How to bring stand-alone methods together to create something useful.

As we progress through the lessons, we'll lay out optional homework. These tasks will generally take the form of improvements to a lesson's code, or alternative implementation techniques.

Transcripts

1. Intro: Welcome to Python. Many projects Maths Quiz game addition in this course will be creating a tiny console game . The test the players. Mass ability. This mini project course is broken up into method sized chunks. Literally. Most lessons center on a single method. You'll learn how to create randomized maths questions. Calculate the answer to those questions. Build a game loop that gives a good user experience and, most importantly, how to use various fundamental piping structures. So who's this course for? Well, actually, a couple of different people First, if you have a basic knowledge of pious and python and would like to see the language being put to practical use, this course is for you. It's an excellent way of seeing how problems can be broken down and how to solve them using python. If you don't know any Piketon, but you're already familiar with another language. Java Sea Sharp Taps script. It doesn't really matter. Then your target audience number two. If you fall into this category, you'll get rapid exposure to Patton's unusual syntax. As someone who's had exposure to over 14 programming languages in the last decade, that makes me feel a little old I speak from experience when I say that looking at someone else's code in your new language and modifying it to suit your needs is one of the fastest ways to pick up that language. This is because you get to see so many aspects that traditional learning resource is often just don't show to beginners. This is also a good course for anyone that already knows Pathan but would like a rapid refresher, so let the programming begin. 2. Evaluating Equations: in this intra lesson toe have to create a math quiz game using Python. We're going to be creating the core, the whole project. This is a method called calculate Answer, and what is going to do is given a problem. It's going to give you back. The answer will use this method throughout the entire project, and it's really important that we get it right. We're going to start out by creating a simple skeleton method, just a demo, that our environment is up and working. We expected to return no, as that's the default value and python. It does that, so it's set to move on. Next. Let's add parameters. A method like this is going to accept all components of a basic math question. Ah, left hand side, the right hand side and an operator such as plus or minus, it's put in a dummy return statement. We've hard coded the operator for now to keep things simple and to show that changing the arguments values actually has an effect. In order to keep track of progress going forward, these prints statements will let us know which operations are behaving as expected in a later lesson. Will swap these out for real test cases rather than just prints. Notice how they all give the same answer. For now. Let's fix that with a simple if statement later on, you could add Ellis, but it isn't actually necessary. A simple string comparison inside oven. If Operator is enough for now, the 1st 2 outputs of behaving as expected, the same logic can be used all the way down. I need to remember to change each conditional, and each return operator and the output seem to be correct. But what happens when given some sort of invalid input? Let's say a smiley face or something equally weird defaulting to addition doesn't make much sense. So let's give it the same logic as its siblings just going to duplicate this chunk of code . That leaves the question of what is the correct way of handling bad inputs. We could simply return a constant such a zero, but then no one will know that something went wrong. When it does, we could also display an air message, but that makes the output ugly and it can be ignored. The best way to handle something like this is to raise an exception it forces uses to acknowledge that they have a bug and either fix it or explicitly handle it with a try catch . Now we want to run this code to double check that are exception is in fact being raised where it should be. And here it is as homework for this lesson. Try adding an extra equation. Type, for example, on exponents or power of operator. Also spot the unhand Aled issue around division and implement an explicit error message for when it happens. So that concludes the first lesson of creating a maths quiz game using Python. Hopefully, we didn't go too fast, and if we did drop me a message and I'll see what we can do to help you. So a quick revision of what was covered three main points we wrote a value returning method that calculates the answers to a math question. We used ifs in order to decide what various operators did, and finally we learned how to raise an exception so that undesirable behaviors could be handled quickly. So in the next lesson, we will be writing the system method to calculate. Answer. I e. Generate question. As always, feel free to leave questions or feedback, and I'll do my best to address them 3. Side Note - Understanding Alternatives: and now a quick tangent before moving on to the next portion of the quiz program, I wanted to demonstrate that there's almost always another way to code something. While one way isn't always better than another, each version usually has its own distinct pros and cons. I'll explain some of these advantages and disadvantages using two examples. Another benefit of sidebars like this is that you'll be able to get exposure to features of the language that you maybe didn't know existed. So for alternative number one reviews the combination of Lambda Functions and dictionaries in order to remove the excess of if statements. If you don't know what either of those are, that's perfectly fine. And if you do know what they are and how to combine them like this already, then why you watching this video? You heard a college senior level. This function approach is nice for several reasons, in my opinion, because it's easy to read, trivial to extend and non restrictive regarding custom operators. For example, you could use the letter l or literally any other string to represent a logarithms. If you want to experiment with this version, I've shared a link in the description. Alternative Number two is a totally different beast. Evil is something that most languages don't have is a built in feature. Javascript and Python are the only two exceptions I can think off. Hand ive out is essentially a call to the partner interpreter that says something like this . Take this string, pretend it's code, and then give me back whatever it ends up. Pass Evil is safe in this example, but only because we checked against the list of legal operators before doing anything. If we didn't have that check, then arbitrarily complex code could be injected here, which poses a real security risk. Because of this, summon environments outright disabled evil, which makes it something to avoid when possible for compatibility reasons. Another limitation with this approach is that the equation format is rigidly connected toe whatever python deems sent tactically legal, so that log example from before couldn't be used here. The one big pro of using evil is how very, very short and readable it is with that hopefully informative tangent. Out of the way, let's continue on to the next portion of the quizzes logic 4. Generating Questions: hello and welcome to the second main lessening, creating a patent maths quiz game. So far, we've learned how to compute the result of a given question. But that isn't really much use all by itself. After all, if you make your questions my hand, you wouldn't really need a calculator because you could just work dances out as you go along. In this lesson, we're going to cover generating random questions using Python's Rand in Method and towards the end will also briefly show how the existing calculate answer method from the last lesson and the newly created generate question method from this lesson can be made to communicate with each other, becoming something useful where there was once on the ephemeral theory way, more on that second part in the next next lesson, let's begin. As always, the first thing to do is create the outline of our target method. At the moment, there aren't any obvious arguments, so we'll leave that blank now. The main purpose of the method what have returns is something we need to discuss further. I briefly mentioned before that generate question. Is the system method to calculate answer. Perhaps a more apt comparison is that of producer and consumer calculate. Answer consumes the outputs from generate question. This means that the return values here should mirror the structure off. What calculate answer is expecting to receive in this particular version? Calculate Answer is expecting three arguments to numbers and an operator. As always, there are alternative solutions, such as passing around question objects. But this is good enough for our simple use case. That's the skeleton of our method complete. Now let's remove all this hard coded ugliness. Fixing the numbers with something more random is the easier type of replacement. So let's start there. This new import means rather than bringing in the whole random library, we only want access to the random interview generating method that it contains i e. Rand into. This is a nice way to reduce clatter in larger programs, as you no longer need to say Random dot ran into every time you want to create a new random number, Brandon and expects to arguments and upper and lower bound 0 to 10 sounds like a good starting point for these. When we were on this, noticed that the first return value is now changing every time this was the expected behavior. So let's duplicate the logic for the right hand side number. Randomize ing the operator is where things make it confusing. Remember, an operator is one of a very limited set of characters, and therefore the random library won't have anything to help us, at least not directly as a starting point. We can explicitly list are set of known operators as a string. Next, ask yourself. How would we pick exactly one operator from this collection? The simplest answer is the street is to treat. The string is a list and use value indexing notice if we change this value or index the returned operated changes with it. To make things more random, let's replace the constant index with something more dynamic. Using similar logic is before we now have a random operator index value. Before we run this, see if you can spot the problem. Pause. Now. If you want to try for yourself, the answer will become clear. If we run this code a few times, there crashed. The reason that crashed is because we weren't careful with the operator Index boundaries. Unlike most languages, python has an inclusive up abound on its random number generator rather than an exclusive one. I bring this up because it can lead to subtle bugs that are super hard to replicate and Deepak. The easiest solution is to just subtract one from the upper bound. The possible numbers generated now will be 012 or three, but never for meaning will never go out of bounds. Let's have a look at a larger sample output from our new method. It's mostly looking good, but here's another potential problem. We have a division operator here and a right hand side value of zero. This is a problem because it results in division by zero. We could solve this by simply bounding Are questions toe one rather than zero, however, that artificially limits what our program can do. Instead, let's put a check here so we can resolve the problem rather than just hiding it. The use case we want to look out for is division by zero, which only occurs if these two separate conditions are both met. Identifying where the problem occurs is step one. Next, we need to decide how to actually fix it. We can't just raise an exception after all, that's not actually a fix. We could add one to the right hand side, but that introduces a slight preference for questions where the right hand side is one. We could reroll the number entirely, and this is actually the best answer. The only problem with the version you're seeing now is that there still a chance after this new if is done, that we get zero again. To prevent that from happening will replace the if with a while loop using the same condition. Now we can guarantee that RHS will have a safe value. Awesome to verify that that's the case. Let's add a checked our output loop for potential division by zero. Rather than doing a visual check. You could also make use of the returned values, bypassing them into our previous method of calculate. Answer. If nothing happens when calculate answer uses our values, you know they must be safe. Ah, bonus benefit of checking like this is that we can see our two methods interacting before we give out homework. Let's quickly recap line by line. Here we have our collection of known operators in this version, a simple string. Here we generate a random index that can safely be used in the aforementioned string. Next, we combined the two previous lines and get back off final operators value. These two lines are just generating random inter jizz for use as the numeric components of our two questions. Here we have the loop that checks for and prevents division by zero questions by regenerating the right hand side number. And finally we returned everything we generated so far. Ready for external consumption. Okay, homework time. You'll notice. There are a lot of hard coded numbers here. This means that only a very limited range of questions can be generated. I want you to add two new arguments lower bound and up about that. Allow whomever calls our method to specify an alternative set of bounds. For example, you may have some students that need to learn about negative numbers. Having a lower and upper bound off minus 10 to 10 rather than 0 to 10 would allow them to do just that. Remember, there are a least three different lines where these neat new arguments would need to be used. The next piece of homework is a bit more tricky. I want you to allow for multi character operators such as Log or Pathan's double star power of operator. My hand for this one is that the current operators string should maybe be a different index herbal collection. I know the demo towards the end to the part about how to show and test the output was done a bit fast, but that was for a good reason. I swear so. First of all, it wasn't really the focus of this lesson. The focus was meant to be how to reliably generate safe to use random questions. But more importantly, almost all of that logic is going to be present in the next video when we bring everything that we've done so far together to create the main game loop. So that means the more detailed explanations are still to come. There are two main takeaways from this lesson. How to use the random method to generate random numbers and select operators at random, and how to use loops to prevent undesirable values from creeping in and causing problems later. Don't forget, if you're stuck with something, leave a comment or send a message, and I'll do my best to help see you next time 5. The Game Loop: a slightly different stop from usual this time, as we're about to write the main game loop, we don't have to create a dedicated method for it like we usually would, although a lot of the larger can be extracted toe help method for homework if you want to. Instead of worrying about argument and return types and fleshing out method specific logic , well taken approach more akin to repeatedly asking, What would I want to do or see next? If I was the player, the first thing I'd want is a player is a question to be shown to me in order to show question, we have to generate one first here. We invoke generate question from the last lesson and storage result in a question variable for later use. Now we have a question it needs to be shown to the user. Ah, print statement with some string formatting to make things nice and pretty is good enough for now. When we were on this, we see the question displayed neatly. Nice. Now ask yourself again, What would I want to do or see next? If I was a player, I would say the next thing is let me answer your question for this. The input method is the only real option for a consul program. Now we've given the player question and restoring their response. A quick tangent here. Notice that we both display the question and then prompt the user a second time for their input. This looks clunky. Can't we combine both of thes things in tow? One. And the answer is absolutely and you should. So in order to do that, we can just cut the question string pasted into the input call. And then when we run it Voila, Anita user experience without repeated input prompts. The next step in a game like this would be to give the player feedback on whether they were right or not to give that feedback. We need two things that we don't have yet. We need to know the correct answer, and we need a means of comparing the correct answer with the players. Answer. Which we already have from the previous step. Time to call our other help method calculate. Answer. We have the correct answer here in this variable. So now we need a means of comparing the two different types of answers. Let's start with the naive approach of directly comparing the two when we were when we run this despite giving a correct answer, it says we were wrong. Why would it do that? The answer is actually quite simple. Input is returning a string, but calculate answer is returning a number. So even if the two values looks similar, as you can see here, they're very different in the eyes of your computer. If we cost the one side of this comparison to a string, suddenly we get back. True, we can use the same casting technique in our previous comparison, and now when we put in a correct answer, we get told us much. There is still a slight issue with this simple comparison. What happens when you give the user question like nine divided by seven? How accurate does a player have to be? As a question like this is a bit beyond, the scope of this simple project will implement a solution at the end of the video. That way, those of you that want to try and work out a solution for yourselves contrite his homework and those of you that just want to see an answer won't be left with 1/2 working project for now. When the player is wrong, we could make a point of showing them the complete correct answer. That way there are least know if it's a precision issue or if they were actually wrong back to the main game, what would the play want to see next? Well, a single question isn't much fun. So if I were playing, I'd want to see another question. This is probably the easiest step of all. We just wrap everything we've made so far into a loop for now will demo it, using just to it orations. And it's asking more than one question. So it's working. Final thing I'd want to see is my score. For that, we'll need two things. How many questions were there in total? And how many of those did I get? Correct. Total questions is easy to add to what we already have. We just add a constant at the beginning and make sure it gets used by the loop for determining how many questions ask. I noticed that if we change our new variable, the total number of questions asked changes to match the second piece of information for displaying the score. How many times was to play correct? Requires onion, tiny bit more effort to start with the use. It doesn't have any correct answers, so we add a zero doubt variable at the top. Then there's only one time that this value changes, and that's here. I e. When the two aunts is match with those two pieces of information, we can write a print line like this one where we show the user their raw school. And then we can also add a percentage at the end so they don't have to work it out for themselves. And that's it. Well, almost. Let's add the more flexible method of comparing answers that I promised a little while ago . I'm going to speed this section up so you don't have to watch it all being written out. In the meantime, a quick explanation. If we subtract one answer from the other, regardless of which one is larger or correct, and then make the result positive. We have the absolute difference between those two numbers, but how do we know when that difference is too large? Well, we had a tolerance term and comparative. It's that here some demo outputs to show that it's working as expected. Notice how the order doesn't matter. The 1st 2 are far too different from each other to be considered correct, and the second to are just within that tolerance range. So they returned true. Notice how we can also change the tolerance, and suddenly you require a lot more or less accuracy. With that help a method done. We just need to replace the old comparison. Let's run it with our new changes and give it to deliberately close but not quite right answer. And there it is, a more tolerant quiz game. So homework time. Let's start with the simple stuff. First, I want you to change the program so the user can choose how many questions they want to answer at the beginning, or give them the option to exit early so that their only scored on what they've done so far or do both. If you really want to. And for those of you that are itching for more of a challenge, you can try and change this game loop so that rather than a consul game, you have a gooey game you can use TK Enter or any other u I module you like don't feel bad for not doing this one. However. I personally don't enjoy you. I work in python at all. And that's that, Ah, fully functional math quiz game written from scratch and python that you could literally use to test any persons arithmetic knowledge. 6. Summary and Feedback: So now that the program is done, let's quickly revise the main structures of the project. Our game can solve math questions using calculate, answer. Generate random questions using Generate Question the side of a given arteries accurate enough, using the is accurate enough method and mix all of the above into a single game loop with riel player interactions. You can submit your own versions of the game as a course project. Tell us about what changes you made and why, or how you approach the different homework questions. If you really know your stuff, have a good making the whole project more object oriented or just for fun. Play a round of code golf and try to shrink the project into as few lines as possible. Thanks for watching. We hope you enjoyed this many protect. With that in mind, we're constantly trying to improve our courses so your feedback is invaluable. Please feel free to leave comments or send messages about what you liked on what you think we done better. For example, should I go faster or slower? Would you like more or less detailed explanations? Was the project to simple etcetera? We're also interested in knowing what sort of many projects you'd like to see next and until next time, keep coding