Reputation: 25
i am learning python and am following a tutorial the current lesson has us creating a quiz game and instead of making the game static i wanted to make it so the order in which the answers to each question where given is random so i wrote some code. But it seems terribly inefficient and was wondering if some more experienced coders could help me analyze and see what i could have done better. its python 3 btw
import random
def random_letter(possible_answers):
x = random.choice(possible_answers)
return x
def random_question(q_correct,q_incorrect,answer):
templist = []
if answer == 'a':
templist =[]
templist2=[0,1,2]
templist3=['B: ','C: ', 'D: ']
templist.insert(0,'A: '+q_correct)
for i in range(3):
x = random.choice(templist2)
templist2.remove(x)
templist.append(templist3[i]+q_incorrect[x])
if answer == 'b':
templist =[]
templist2=[0,1,2]
templist3=['A: ','C: ','D: ']
for i in range(3):
x = random.choice(templist2)
templist2.remove(x)
templist.append(templist3[i]+q_incorrect[x])
templist.insert(1, 'B: ' + q_correct)
if answer == 'c':
templist =[]
templist2=[0,1,2]
templist3=['A: ','B: ', 'D: ']
for i in range(3):
x = random.choice(templist2)
templist2.remove(x)
templist.append(templist3[i]+q_incorrect[x])
templist.insert(2, 'C: ' + q_correct)
if answer == 'd':
templist =[]
templist2=[0,1,2]
templist3=['A: ','B: ', 'C: ']
for i in range(3):
x = random.choice(templist2)
templist2.remove(x)
templist.append(templist3[i]+q_incorrect[x])
templist.insert(3,'D: '+q_correct)
return templist
possible_answers = ['a','b','c','d']
questions = {
"who created Python?" :random_letter(possible_answers),
"What year was python created":random_letter(possible_answers),
"Python is tributed to which comedy group":random_letter(possible_answers),
"Is the Earth Round":random_letter(possible_answers)
}
templist = []
for value in questions.values():
templist.append(value)
q1_correct = "Guido van Rossum"
q1_incorrect = ["Elon Musk", "Bill Gates","Mark Zuckerburg"]
q2_correct = "1991"
q2_incorrect = ['1989','2000','2016']
q3_correct = 'Monty Python'
q3_incorrect = ['Lonely Island', 'Smosh',"SNL"]
q4_correct = 'True'
q4_incorrect =['False','sometimes','the f*cks wrong with u']
q1_list = random_question(q1_correct,q1_incorrect,templist[0])
q2_list = random_question(q2_correct,q2_incorrect,templist[1])
q3_list = random_question(q3_correct,q3_incorrect,templist[2])
q4_list = random_question(q4_correct,q4_incorrect,templist[3])
final_questions = [q1_list,q2_list,q3_list,q4_list]
print(q1_list,q2_list,q3_list,q4_list)
Upvotes: 2
Views: 333
Reputation: 15525
A few comments about your code:
An added benefit of putting the data in a separate file is that you can ask your friends to contribute to the list of questions, without risking them inadvertently damaging the code in the python file.
Putting these comments into practice, I get two files, questions.csv
and questions.py
:
questions.csv
"Who created Python?","Guido van Rossum","Elon Musk", "Bill Gates","Mark Zuckerberg"
"What year was python created",1991,1989,2000,2016
"Python is tributed to which comedy group","Monty Python","Lonely Island", "Smosh","SNL"
"Is the Earth Round","True","False","sometimes","the f*cks wrong with u"
questions.py
import csv # reader
import random # choice, shuffle
import string # ascii_uppercase
def get_data(filename):
with open(filename, 'r') as f:
r = csv.reader(f)
data = [row for row in r]
return data
def get_random_question(data):
row = random.choice(data)
question = row[0]
correct_answer = row[1]
possible_answers = row[1:]
random.shuffle(possible_answers)
return question, correct_answer, possible_answers
def ask_question(question, correct_answer, possible_answers):
d = {index: answer for index,answer in zip(string.ascii_uppercase, possible_answers)}
print(question)
for index, answer in d.items():
print(f' {index}: {answer}')
user_answer = input()
while d[user_answer[0].upper()] != correct_answer:
print('Wrong!! Try again')
user_answer = input()
print('Correct!!')
if __name__ == '__main__':
data = get_data('questions.csv')
question, correct_answer, possible_answers = get_random_question(data)
ask_question(question, correct_answer, possible_answers)
Execution:
$ python3 questions.py
Python is tributed to which comedy group
A: Lonely Island
B: "Smosh"
C: Monty Python
D: SNL
c
Correct!!
$ python3 questions.py
What year was python created
A: 1989
B: 2016
C: 2000
D: 1991
b
Wrong!! Try again
a
Wrong!! Try again
c
Wrong!! Try again
d
Correct!!
Upvotes: 1
Reputation: 81
To simplify your code the "expert" way you should use random.shuffle
. This might be the simplest way to accomplish what you're trying to do. To understand how to make the code you have more efficient without using random.shuffle
there are some modifications you can do to your code. This might not necessarily make it more efficient but it simplifies what you already have.
There's no need to have templist2 = [0, 1, 2]
inside all ifs so you can just take it outside.
Instead of having to type 'A: '
, 'B: '
, 'C: '
and 'D: '
, you can get that dynamically by using ans = answer.upper() + ': '
.
Instead of getting the index of the answer you can get it by subtracting the char value of 'a'
to the answer using ord(answer) - ord('a')
.
The for loop is repeated in all ifs so you can also just take that out of the ifs.
That would save a lot of space.
def random_question(q_correct, q_incorrect, answer):
templist = []
templist2 = [0, 1, 2]
templist3 = ['A: ', 'B: ', 'C: ', 'D: ']
ans = answer.upper() + ': '
templist3.remove(ans)
for i in range(3):
x = random.choice(templist2)
templist2.remove(x)
templist.append(templist3[i] + q_incorrect[x])
templist.insert(ord(answer) - ord('a'), ans + q_correct)
return templist
Upvotes: 0
Reputation: 961
You can use random.shuffle
to randomize answers for a single question. I know that you are a beginner for python so I decided to write more clear code to show you how you can use it.
from typing import List
import string
from random import shuffle
class Question:
def __init__(self, question, answers: List[str]):
self.question = question
self.answers = answers
def ask(self):
answers = self.answers.copy() # the best way is just to copy this list because assignment would just create a reference (and we don't want that to happen)
shuffle(answers) # randomizing order of answers
correct_index = answers.index(self.answers[0]) # we keep here the index of the correct answer in case of checking if the user provided the correct answer
# printing out the question and randomized answers with letters from `string.ascii_uppercase` list
print(self.question)
for i, ans in enumerate(answers):
print(f'{string.ascii_uppercase[i]}) {ans}')
q = Question(question="Who created Python?", answers=["Guido van Rossum", "Elon Musk", "Bill Gates","Mark Zuckerburg"])
q.ask()
The Question
class takes two parameters, question
and answers
. We can assume that always the first answer is correct to avoid making more class parameters. We are going to randomize it any way. Method ask
prints out the question and randomized answers.
Here is an example of the output:
Who created Python?
A) Bill Gates
B) Mark Zuckerburg
C) Guido van Rossum
D) Elon Musk
Who created Python?
A) Guido van Rossum
B) Elon Musk
C) Bill Gates
D) Mark Zuckerburg
Hope that it's all clear for you
Upvotes: 1