Multiple choice quiz in python using random function and lists - python

I'm trying to make a multiple choice quiz using python. It seemed like something simple to make at first but now i'm scratching my head a lot trying to figure out how to do certain things.
I am using two lists; one for the questions and one for the answers. I would like to make it so that a random question is chosen from the questions list, as well as 2 random items from the answers list (wrong answers) and finally the correct answer (which has the same index as the randomly selected question).
I've got as far as selecting a random question and two random wrong answers
My first problem is getting the program to display the correct answer.
The second problem is how to check whether the user enters the correct answer or not.
I would appreciate any feedback for my code. I'm very new to this so go a little easy please!
I hope my stuff is readable (sorry it's a bit long)
thanks in advance
import random
print ("Welcome to your giongo quiz\n")
x=0
while True:
def begin(): # would you like to begin? yes/no... leaves if no
wanna_begin = input("Would you like to begin?: ").lower()
if wanna_begin == ("yes"):
print ("Ok let's go!\n")
get_username()#gets the user name
elif wanna_begin != ("no") and wanna_begin != ("yes"):
print ("I don't understand, please enter yes or no:")
return begin()
elif wanna_begin == ("no"):
print ("Ok seeya!")
break
def get_username(): #get's username, checks whether it's the right length, says hello
username = input("Please choose a username (1-10 caracters):")
if len(username)>10 or len(username)<1:
print("Username too long or too short, try again")
return get_username()
else:
print ("Hello", username, ", let's get started\n\n")
return randomq(questions)
##########
questions = ["waku waku", "goro goro", "kushu", "bukubuku", "wai-wai", "poro", "kipashi", "juru", "pero"]
answers = ["excited", "cat purring", "sneezing", "bubbling", "children playing", "teardrops falling", "crunch", "slurp", "licking"]
score = 0
if len(questions) > 0: #I put this here because if i left it in ONly inside the function, it didnt work...
random_item = random.randint(0, len(questions)-1)
asked_question = questions.pop(random_item)
###########
def randomq(questions):
if len(questions) > 0:
random_item = random.randint(0, len(questions)-1)
asked_question = questions.pop(random_item)
print ("what does this onomatopea correspond to?\n\n%s" % asked_question, ":\n" )
return choices(answers, random_item)
else:
print("You have answered all the questions")
#return final_score
def choices(answers, random_item):
random_item = random.randint(0, len(questions)-1)
a1 = answers.pop(random_item)
a2 = answers.pop(random_item)
possible_ans = [a1, a2, asked_question"""must find way for this to be right answer"""]
random.shuffle(possible_ans)
n = 1
for i in possible_ans:
print (n, "-", i)
n +=1
choice = input("Enter your choice :")
"""return check_answer(asked_question, choice)"""
a = questions.index(asked_question)
b = answers.index(choice)
if a == b:
return True
return False
begin()

You could structure the data in a simpler way, using dictionaries. Each item is a pair of a key and a value, for more info refer to this.
For example your data will look like this (each question is associated with an answer):
data = {'question1': 'answer1', 'question2': 'answer2'}
Then we can loop through this dictionary to print the answers after we randomly choose a question. Here's some sudo code for help:
# Choose a random question
# Print all the answers in the dictionary
for key, value in data.iteritems(): #its data.items() in Python 3.x
print value
# If the choice matches the answer
pop the question from the dictionary and do whatever you want to do
# Else, ask again
For more information about iterating through a dictionary refer to this.

You can use another list(for example correct_answer or such) to record the correct answer for each question. Then instead of using a1 = answers.pop(random_item) to choose a wrong answer, use
while True:
if answer[random.randint(0, len(answers)-1)] != correct_answer[question]:
break
a1 = answers.pop(id)
to avoid choosing the correct answer as an incorrect one.
EDIT
As your correct answer is already in the answers, you should not pop items when choosing some incorrect answers, otherwise it will break the indices.
You can choose two wrong answers and a correct answer like this.
correct = question_index
while True:
wrong1 = random.randint(0, len(answers)-1)
if wrong1 != correct:
break
while True:
wrong2 = random.randint(0, len(answers)-1)
if wrong1 != wrong2 and wrong1 != correct:
break

Related

multiple choice quiz , how to deal with unwanted answer? | python

So, i have been learning from a video on youtube about basic multiple choice quiz with few possilble answers like a, b, c.
but, if the user enters r or 44 the code just wont count it as a right answer.
I want the code to print the user the question again. Ive tried to write something but now it is moving on to the next question only if the user enters the right question.
def test_run2(questions):
score = 0
for question in questions:
while True:
user_answer = input(question.prompt)
user_answer.lower()
if user_answer == "a" or "b" or "c":
if user_answer == question.answer:
score = score + 1
break
# For each of your questions
running = True
while running:
print("") # Put question in here
if answer in possibleAnswers:
# Check if correct or wrong, etc.
running = False
else:
print("Please provide a valid answer")
# Repeat again for next question
Note that this is just a snippet, you need to add the other sections of your code to it where applicable.

I need to figure out how to make my program repeat. (Python coding class)

I am a beginner student in a python coding class. I have the majority of the done and the program itself works, however I need to figure out a way to make the program ask if wants a subtraction or an adding problem, and if the user would like another question. I asked my teacher for assistance and he hasn't gotten back to me, so I'm simply trying to figure out and understand what exactly I need to do.
import random
x = int(input("Please enter an integer: "))
if x < 0:
x = 0
print('Negative changed to zero')
elif x == 0:
print('Zero')
elif x == 1:
print('Single')
else:
print('More')
maximum = 10 ** x;
maximum += 1
firstnum = random.randrange(1,maximum) # return an int from 1 to 100
secondnum = random.randrange(1, maximum)
compsum = firstnum + secondnum # adds the 2 random numbers together
# print (compsum) # print for troubleshooting
print("What is the sum of", firstnum, " +", secondnum, "?") # presents problem to user
added = int(input("Your answer is: ")) # gets user input
if added == compsum: # compares user input to real answer
print("You are correct!!!")
else:
print ("Sorry, you are incorrect")
You'll want to do something like this:
def foo():
print("Doing good work...")
while True:
foo()
if input("Want to do more good work? [y/n] ").strip().lower() == 'n':
break
I've seen this construct (i.e., using a break) used more often than using a sentinel in Python, but either will work. The sentinel version looks like this:
do_good_work = True
while do_good_work:
foo()
do_good_work = input("Want to do more good work? [y/n] ").strip().lower() != 'n'
You'll want to do more error checking than me in your code, too.
Asking users for input is straightforward, you just need to use the python built-in input() function. You then compare the stored answer to some possible outcomes. In your case this would work fine:
print('Would you like to test your adding or subtracting skills?')
user_choice = input('Answer A for adding or S for subtracting: ')
if user_choice.upper() == 'A':
# ask adding question
elif user_choice.upper() == 'S':
# ask substracting question
else:
print('Sorry I did not understand your choice')
For repeating the code While loops are your choice, they will repeatedly execute a statement in them while the starting condition is true.
while True: # Condition is always satisfied code will run forever
# put your program logic here
if input('Would you like another test? [Y/N]').upper() == 'N':
break # Break statement exits the loop
The result of using input() function is always a string. We use a .upper() method on it which converts it to UPPERCASE. If you write it like this, it doesn't matter whether someone will answer N or n the loop will still terminate.
If you want the possibility to have another question asked use a while loop and ask the user for an input. If you want the user to input whether (s)he want an addition or substraction you already used the tools to ask for such an input. Just ask the user for a string.

How can I create a quiz in Python using a dictionary rather than a large number of if/else statements?

I'm making a quiz of yes/no questions where answering yes/no depending on the question rewards a different amount of points, which after each question will be added to a total and displayed at the end.
However, there are around 50 questions in the quiz, and this would mean a mountain of if/else statements. Is there a way I can use a dictionary and a loop or something similar to significantly reduce the length of the program?
edit This repeated many times is what I'm trying to avoid. I'm thinking of adding a variable i and adding 1 to it after each question, and looking up the index of the next question. But is this only possible with a list?
print "The following are y/n questions."
total = 0
q1 = raw_input("Do you exercise daily? ")
if q1 == "y":
total += 1
else:
total = total
print total
Create a list of dictionaries. Each element is a question and the points for yes and no. You can then easily iterate over the list.
qa = [{"question": "Do you exercise?", "yes": 10, "no": 0},
"question": "Do you smoke?", "yes": -10, "no": 0},
...
]
for item in qa.items():
answer = raw_input("Do you exercise daily? ")
score = item.get(answer)
total = total + score
Of course, you'll need to add some additional code to handle the case where the user doesn't answer literally "yes" or "no", but that doesn't affect this solution. The point is, you create an object that represents a question, and the possible answers with scores, and then you iterate over a list of those objects.
You could even go a step further and create a custom class. You could do it like this, for example:
class Question(object):
def __init__(self, question, yes=0, no=0):
self.question = question
self.yes = yes
self.no = no
questions = [Question("Do you exercise?", yes=10, no=0),
Question("Do you smoke?", yes=0, no=-10),
...
]
for question in questions:
answer = raw_input(question.question)
...
At the lowest level, with your given example, all you really need is a list of questions to ask and then just loop over this
print "The following are y/n questions."
total = 0
questions = ["Do you exercise daily? ", "Is this a second question?"]
for question in questions:
q1 = raw_input(question)
if q1 == "y":
total += 1
print total
Of course this can be expanded to include a proper object class and so on..
I was thinking of using this approach, however, how would I tie different points values to each question? One question may be worth six, while another may be worth four. Could I make a second list containing the point values?
You make a question class and then make the list a list of these answers
class Question()
def __init__(self, text, correct_answer_value)
this.text = text
this.value = correct_answer_value
print "The following are y/n questions."
total = 0
questions = [Question("Do you exercise daily? ",1), Question("Is this a second question?",2)]
for question in questions:
q1 = raw_input(question.text)
if q1 == "y":
total += question.value
print total
# Firstly, declare your questions. Create it with their answer and associated score.
questions = {}
questions[1] = {}
questions[1]["question"] = "Is the sky blue? Y/N"
questions[1]["answer"] = True
questions[1]["score"] = 50
# We can add more questions
questions[2] = {}
questions[2]["question"] = "Is Python a programming language? Y/N"
questions[2]["answer"] = True
questions[2]["score"] = 150
# Set the initial score at 0
score = 0
# Loop over the questions
for key in questions:
user_answer = None
# We ask the question till the user answer Yes or Not
while user_answer not in ["Y","N"]:
user_answer = raw_input(questions[key]["question"])
# If the user said Yes we keep True, if he said No we keep False
user_answer = True if user_answer == "Y" else False
# We increment the score if the answer is the same that it's stored in your dictionary
score += questions[key]["score"] if user_answer == questions[key]["answer"] else 0
print "Final score {0}".format(score)
A bit of set-up code, like
def get_yesno(prompt):
while True:
response = raw_input(prompt).strip().lower()
if response in {'y', 'yes'}:
return True
elif response in {'n', 'no'}:
return False
else:
print("Please respond with yes or no.")
class YesNo:
__slots__ = ('question', 'yes_points', 'no_points')
def __init__(self, question, yes_points=1, no_points=0):
self.question = question
self.yes_points = yes_points
self.no_points = no_points
def ask(self):
if get_yesno(self.question):
return self.yes_points
else:
return self.no_points
means that you can easily define questions like
questions = [
YesNo("Do you exercise daily? "),
YesNo("Do you have more than 3 drinks a week? ", -5, 2)
]
and then your main program becomes
def main():
score = sum(q.ask() for q in questions)
print("Your score was {}".format(score))
if __name__ == "__main__":
main()
Add your questions to a list. (Lists)
Then simply use:
for question in questionList:
q1 = raw_input(question)
if q1 == "y":
total += 1
else:
total = total
print total
You specifically mention that you would like to use a dictionary, so this answer will provide a solution as to how to do that.
If you are only expecting answers to be 'yes'/'no', then you can setup your dictionary as follows:
test_dict = {'question1': {'yes': 100, 'no': 50},
'question2': {'yes': 75, 'no': 25}}
You can then ask questions, grab their answers, and pass them through the dictionary to accumulate their points.
question1_ans = raw_input("Is your favorite animal a Rhino?").lower()
num_points += test_dict['question1'][question1_ans]
In that case, if you answer 'yes', then num_points will be 100. Else, answering no will result in num_points being 50.
Obviously this doesn't prevent them from answering something like: "FOO", instead of 'yes'/'no', which would result in a KeyError.

python quiz validation not working

The validation doesnt work. im not sure why, is there a way to validate a string. The questions asked are endless i need 10 questions to be asked
import random
name=(input("Please enter your name"))
print("welcome",name,"the arithmetic is about to start")
question=0
while question<10:
number=random.randint(1,10)
numbers=random.randint(1,10)
arith=random.choice("+" "-" "/")
if arith=="+":
print(number,arith,numbers)
answer=number+numbers
if arith=="-":
print(number,arith,numbers)
answer=number-numbers
if arith=="/":
print(number,arith,numbers)
answer=number/numbers
while True:
try:
usersanswer= int(input())
except ValueError:
print ("That is not a valid answer")
continue
if usersanswer==answer:
print("correct")
break
else:
print("incorrct")
The validation doesnt work. im not sure why, is there a way to validate a string
I've taking silentphoenix's answer and made it somewhat more pythonic and six'ed.
You should almost never use python2's input, because on top of being massive security hole, it sometimes does things that can be...rather unexpected.
import random
import operator # contains the python operators as functions
try:
input = raw_input # rebind raw_input to input, if it exists
# so I can just use input :P
except NameError:
pass
name = input("Hi, what is your name?\n")
print("Hi {} let's get started! Question 1".format(name))
#Get out of the habit of using string concatenation and use string
#formatting whenever possible. Strings are *immutable*;
#concatenation has to produce a lot temporary strings and is *slow*
#str.join and str.format are almost always better ideas.
#Python does not have a switch-case, so emulating one with a dictionary
operator_mapping = {'+': operator.add,
'-': operator.sub,
'*': operator.mul,
#'/': operator.truediv, #hey, division exists.
#But if you want division to actually work, you'll
#have to introduce a fudge factor :P
}
for i in range(10): # If you're just going for 10 iterations, it should be a for loop
# Brevity :P This is a list comprehension
first_number, second_number = [random.randint(1,10) for _ in range(2)]
oper = random.choice(list(operator_mapping))
answer = operator_mapping[oper](first_number, second_number)
while int(input("{} {} {} = ".format(first_number, oper, second_number))) != answer:
#while abs(float(input("{} {} {} = ".format(first_number, oper, second_number)))-answer) < 0.001: if you want truediv.
print('Wrong answer! try again!')
#If I've left the loop, user has given correct (enough) answer
if i <9: # all but last
print('Well done! Now onto question number {0}'.format(i+2))
print('Well done! You are done!')
In the third line, you ask for input. But a name is a string, so you need raw_input. raw_input takes strings, input only takes numerical values.
Python 2.7 getting user input and manipulating as string without quotations
Nowhere in your code do you update the variable questions, which I am guessing is a counter. You have to update that whenever a question is asked, using question += 1.
Finally, your code at the end does not really make sense. Based off the code, it checks for whether or not it is a string, but then compares it to the answer regardless. The if statement needs to be within the try.
The else statement does not match any outer indentation.
Finally, because of the while True: your code will never exit the loop unless the answer is wrong. At the point the entire program terminates. I see what kind of program you are trying to write, but the parameters for random number generation have to be within some kind of a while question <= 10 loop. As of now, only two lines in the program are being affected by that first while loop.
EDIT: I am working on a good example code. Hopefully this answer will help until I can finish it.
EDIT: Here is code that shows how it works within a while loop.
import random
from random import randint
name = raw_input("Hi, what is your name?\n") # Asks for name
print "Hi " +name+ " let's get started!"
score_count = 0
question_count = 0 # creates counter
while question_count <= 10: # Everything MUST BE WITHIN THIS LOOP
# makes numbers and operator
first_number = randint(1,10)
second_number = randint(1,10)
oper = random.choice("+""-""*")
# determines the problem
if oper == "+":
answer = first_number + second_number
print first_number,second_number,oper
elif oper == "-":
answer = first_number - second_number
print first_number,second_number,oper
elif oper == "*":
answer = first_number*second_number
print first_number, second_number, oper
user_answer = int(raw_input("Your answer: "))
if user_answer != answer:
print 'Wrong answer! try again!'
user_answer = int(raw_input('Your answer: '))
if user_answer == answer: # exits the while loop when the correct answer is given
if question_count < 10:
print 'Well done! Now onto question number {0}'.format(question_count+1)
score_count += 1
elif question_count == 10:
print 'Well done! You are done!'
score_count += 1
else:
print 'Something is wrong.'
question_count += 1 # updates the variable
# GOES BACK TO THE BEGINNING UNTIL question_count IS GREATER THAN OR EQUAL TO 10
print "Your score was: {}".format(score_count)
Happy coding! and best of luck!
hi im Nathan and I saw this post I am 5 years to late but I figured if someone on here is knew to python I have a much easier (in my opinion) way to do this in python 3, the code is below:
import random #random module automatically downloaded when you install python
name = input("Please enter your name ")
print("welcome",name,"the arithmetic is about to start")
question=0
while question<10:
number=random.randint(1,10) #creating a random number
numbers=random.randint(1,10) #creating a random number
list = ["+","-","/"] #creating a list (or sometimes called array)
arith=random.choice(list) #getting random operators from list (+,-,/)
question += 1 #basically means add one to question variable each time in loop
if arith=="+":
print(number,arith,numbers)
answer=number+numbers
elif arith=="-":
print(number,arith,numbers)
answer=number-numbers
elif arith=="/":
print(number,arith,numbers)
answer=number/numbers
answer = int(answer)
#from HERE
useranswer = "initialising this variable"
while useranswer == "initialising this variable":
try:
usersanswer= int(input())
if usersanswer==answer:
print("correct")
break
else:
print("incorrect")
except ValueError:
print ("That is not a valid answer")
#to HERE it is input validation this takes a while to explain in just commenting
#but if you dont know what this is then copy this link https://youtu.be/EG69-5U2AfU
#and paste into google for a detailed video !!!!!!
I hope this helps and is a more simplified commented bit of code to help you on your journey to code in python

Is there any way to make this Python function run for more intervals?

I am extremely new to python and just wrote up this really simple code. In the end this is something I made just to get my feet wet and my head wrapped around coding. Python is my first language, I started learning it a couple days ago.
And yes, I am aware that this was a very roundabout choice for a coding method, it's also the first thing I ever produced myself that is more than a couple lines long. So, in the end, is there any way I could make the function Question run more times without running into an issue with variables being returned? I am unsure as to whether that would actually be an issue or I am just too tired to see reason right now. I know I would need to create more if statements for the results section. That much is obvious.
name = raw_input("Please enter you preferred name: ")
print "Welcome, %r, to the general stupidity quiz." % name
raw_input("\n\tPlease press any button to continue")
question1 = "\n\nWhat is the equivilent of 2pi in mathmatics? "
answer1 = "tao"
answer1_5 = "Tao"
question2 = "\nWhat is 2 + 2? "
answer2 = "4"
w = 0
def Question(question, answerq, answere, inputs):
user_answer = raw_input(question)
if user_answer in [str(answerq), str(answere)]:
print "Correct!"
x = inputs + 1
return x
else:
print "False!"
x = inputs
return x
x = Question(question1, answer1, answer1_5, w)
x = Question(question2, answer2, answer2, x)
print "\nYou got " + str(x) + " questions correct..."
if x == 2:
print "You're not stupid!"
elif x == 1:
print "You're not smart!"
else:
print "I hate to tell you this...but..."
raw_input()
I added a raw_input() at the end so my cmd window wouldn't close. I know I could use ubuntu (recently uninstalled it) and I could also just run the code using the cmd window, but it's just a thing I tagged onto the end.
You should aim to have your functions be self contained and do one thing. Your function checks the correctness of a user input to an question and increments a counter. That is clearly two things. I will move the incrementing of the counter out of the function:
def question(question, answerq, answere):
user_answer = raw_input(question)
if user_answer in [str(answerq), str(answere)]:
print "Correct!"
return True
else:
print "False!"
return False
x = 0
if question(question1, answer1, answer1_5):
x += 1
if question(question2, answer2, answer2):
x += 1
Now I am going to clean it up a little by changing some names to be more meaningful and not assuming that every question will always have exactly two answers:
def question(question, correct_answers):
user_answer = raw_input(question)
if user_answer in correct_answers:
print "Correct!"
return True
else:
print "False!"
return False
correct_count = 0
if question(question1, [answer1, answer1_5]):
correct_count += 1
if question(question2, [answer2, answer2]):
correct_count += 1
To learn more, look into coding best practices and coding style. I recommend reading PEP8 for Python.
Welcome to programming! It's hard to tell what you are exactly after here but it seems to me like you want to be able to ask a bunch of different questions without writing more code each time.
One thing you can do is put your list of questions/answers into a list:
quiz = [("what is one + one? ", "2"), ("what is 2 + 2? ", "4")]
Here we are only allowing one correct answer so we need to change the Question() function (we can still accept "Tao" and "tao" by calling answer.lower() to remove capitalisation problems):
def Question(question, answer):
user_answer = raw_input(question)
if user_answer.lower() == answer:
print "Correct!"
x = inputs + 1
return x
else:
print "False!"
x = inputs
return x
Now all we have to do is call the Question function for each question in the quiz list:
for q in quiz:
Question(q[0], q[1])

Categories