Trivia Game (Part 2)
September 22, 2010 2 Comments
ARTHUR: He is the keeper of the Bridge of Death. He asks each traveler five questions–
GALAHAD: Three questions.
ARTHUR: Three questions. He who answers the five questions–
GALAHAD: Three questions.
ARTHUR: Three questions may cross in safety.
ROBIN: What if you get a question wrong?
ARTHUR: Then you are cast into the Gorge of Eternal Peril.
(At scene 23)
In the previous tutorial we defined a function to ask a question. The question was sent to the function as an argument and had the type list. The question itself was stored in index number 0 of the list (that is, the first entry) and the correct answer was stored at index number 1 of the list. The homework for the last tutorial was to work out why this was bad. Did you work it out?
The problem with this is that, the correct answer is always at the same place. So if someone was playing the game, they would just answer ’0′ all the time and always get the right answer. So, we’re going to need to find some way of randomising the answers. However, when we randomise them we also need to remember which is the correct one.
It turns out that there’s already a function which will do some of this work for us. First we need to import the random module.
>>> import random
The random module has a function called randint() (which someone else, sometime ago kindly has already written for us, so we get it for free, in a sense). Calling random.randint(a,b) returns a random integer greater than or equal to a and less than or equal to b:
>>> random.randint(1,4) 3 >>> random.randint(1,4) 3 >>> random.randint(1,4) 2 >>> random.randint(1,4) 4
From here, it is not that hard to modify the function so that it puts the right answer in a random spot.
>>> def askQuestion(questionList): ... question = questionList ... answers = questionList[1:] ... numberOfAnswers = len(answers)-1 ... # get the number of answers ... # the "-1" is there because the list starts from 0 ... # so the first entry is at 0 (that is, 1-1), ... # so the last entry is at ... # the total number of entries minus one. ... correctAnswer = random.randint(0,numberOfAnswers) ... # choose one at random ... # now swap the random one for the correct answer ... spam = answers[correctAnswer] ... answers[correctAnswer]=answers ... answers = spam ... print question ... for i in range(len(answers)): ... print i,'. ',answers[i] ... answer = raw_input('Enter number of correct answer: ') ... if answer == str(correctAnswer): ... print 'Correct!' ... else: ... print 'Wrong' ...
In this print out I’ve also included some commentary after the character #. When Python finds a # it ignores everything which comes after it (these are called, unsurprisingly, “comments”). In these tutorials you don’t need to type in comments, they’re there to explain why things are happening the way they are. However, including comments in your code is very important because it helps you remember why you did what you did should you come back to your program at some later time.
The structure has changed a little bit from the previous tutorial. This time, we’ve split the original question list into a question and a shorter list of answers.
Exercise: go back to the strings tutorial and look at the [:] operator. See how it can be used on any list?
From there the comments explain what is happening. We choose a random number – but one which is less than or equal to the number of answers. Then we swap the correct answer (which is in answers) for this one. We know that it is in answers because it used to be in item 1 of questionList, but answers is everything from item 1 of questionList to the end of the list. So, it becomes the first entry, which has an index of 0 – you need to get used to the first entry being at 0 stuff.
We have used a temporary variable called spam to swap the values. We’ve called it “spam”, but any other variable name would have been acceptable. In Python programs “spam” is sometimes used as a name for a disposable variable – that is, one which we’re going to use for a short time and then won’t care about. For why, read this.
Exercise: why won’t this work:
answers[correctAnswer] = answers answers = answers[correctAnswer]
(aside: Python has a special syntax to allow swapping values of variables, but we haven’t used it here).
Finally, we’ve changed the test to see whether the answer is correctAnswer (that is the random number we chose, and therefore the location to which the correct answer has been moved), rather than ’0′ which it was before.
Exercise: What else have we done when checking whether answer is equal to correctAnswer? Why?
So, let’s test this on a sample question:
>>> for i in range(4): ... askQuestion(question1) ... What colour is Jango Fett's armour? 0 . Red 1 . Green 2 . Blue 3 . Pink, with lilac stripes and technicolour swirls Enter number of correct answer: 2 Correct! What colour is Jango Fett's armour? 0 . Pink, with lilac stripes and technicolour swirls 1 . Green 2 . Red 3 . Blue Enter number of correct answer: 3 Correct! What colour is Jango Fett's armour? 0 . Pink, with lilac stripes and technicolour swirls 1 . Green 2 . Red 3 . Blue Enter number of correct answer: 3 Correct! What colour is Jango Fett's armour? 0 . Red 1 . Green 2 . Blue 3 . Pink, with lilac stripes and technicolour swirls Enter number of correct answer: 2 Correct!
Do you see how the location of the correct answer changes each time the question is asked and that the code keeps track of where the right answer is? Also, notice that it’s also possible for the correct answer to stay at location 0. This is not a problem, as all that is important is that the correct answer is not always there. Finally, notice that we’ve used the range() function here to automate the asking of the askQuestion() function.