I am trying to ask the user to pick a quiz, read the relevant questions from a txt file, ask for user answers, validate and check they are correct then add up to scores. I am completely self taught so have picked this code up from various sites but as I have adapted it it no longer works - what have I done wrong? I know its probably something really obvious so please be gentle with me!
getting the message global name the_file not defined
import time
def welcome():
print ("Welcome to Mrs Askew's GCSE ICT Quiz")
print()
def get_name():
firstname = input("What is your first name?:")
secondname = input("What is your second name?:")
print ("Good luck", firstname,", lets begin")
return firstname
return secondname
def displaymenu():
print("-------------------------------------------------------")
print("Menu")
print()
print("1. Input and Output Devices")
print("2. Collaborative working")
print("3. quiz3")
print("4. quiz4")
print("5. view scores")
print("6. Exit")
print()
print("-------------------------------------------------------")
def getchoice():
while True:
print("enter number 1 to 6")
quizchoice = input()
print("You have chosen number "+quizchoice)
print()
if quizchoice >='1' and quizchoice <='6':
print("that is a valid entry")
break
else:
print("invalid entry")
return quizchoice
def main():
welcome()
get_name()
while True:
displaymenu()
quizchoice = getchoice()
print ("please chooses from the options above: ")
if quizchoice == ("1"):
the_file = open("questions.txt", "r")
startquiz()
elif quizchoice == ("2"):
collaborativeworking()
startquiz()
else:
break
def collborativeworking():
the_file = open("Collaborative working.txt", "r")
return the_file
def next_line(the_file):
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
category = next_line(the_file)
question = next_line(the_file)
answers = []
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct=correct[0]
explanation = next_line(the_file)
time.sleep(2)
return category, question, answers, correct, explanation
def startquiz():
title = next_line(the_file)
score = 0
category, question, answers, correct, explanation = next_block(the_file)
while category:
# ask a question
print(category)
print(question)
for i in range(4):
print("\t", i + 1, "-", answers[i])
# get answer and validate
while True:
answer =(input("What's your answer?: "))
if answer >= '1' and answer <='4':
break
else:
print ("the number needs to be between 1 and 4, try again ")
# check answer
answer=str(answer)
if answer == correct:
print("\nRight!", end=" ")
return score
main()
Couple of things I noticed. You haven't provided the error you are getting (/ problems you are having) so these are the things I noticed in my quick look:
First: enter code hereimport time should be import time
Second: All function definitions (def func():) should have the code in them indented e.g.
def get_name():
firstname = input("What is your first name: ")
Third: print () should be print()
Fourth: Multiline strings do exist
"""
Look at me mum!
WOWWWW!
"""
Fifth: It looks like a lot of this has been copied from elsewhere, if you are learning, I suggest you don't copy, but try to understand what things are doing and then hand write it
Sixth: There are a lot of bugs. I think I got most of them, but you should really change something in the way you're working. It really does fail in so many places
Seventh: Here is your code with some improvements:
import time
def welcome():
print("Welcome to Mrs Askew's GCSE ICT Quiz\n")
def get_name():
firstname = input("What is your first name: ")
secondname = input("What is your second name: ")
print("Good luck" + firstname + ", lets begin") # or print("Good luck {}, lets begin".format(firstname))
return firstname, secondname
def displaymenu():
print("""-------------------------------------------------------
Menu
1. Input and Output Devices
2. Collaborative working
3. quiz3
4. quiz4
5. view scores
6. Exit
-------------------------------------------------------""")
def getchoice():
while True:
quizchoice = input("Enter number 1 to 6: ")
print("You have chosen number " + quizchoice "\n")
if quizchoice >= "1" and quizchoice <= "6":
print("That is a valid entry")
break
else:
print("invalid entry")
return quizchoice
def main():
welcome()
get_name()
while True:
displaymenu()
quizchoice = getchoice()
print("Please chooses from the options above: ")
if quizchoice == ("1"):
the_file = open("questions.txt", "r")
startquiz()
elif quizchoice == ("2"):
collaborativeworking()
startquiz()
else:
break
def collborativeworking():
the_file = open("Collaborative working.txt", "r")
return the_file
def next_line(the_file):
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
category = next_line(the_file)
question = next_line(the_file)
answers = []
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct = correct[0]
explanation = next_line(the_file)
time.sleep(2)
return category, question, answers, correct, explanation
def startquiz():
title = next_line(the_file)
score = 0
category, question, answers, correct, explanation = next_block(the_file)
while category:
# ask a question
print(category)
print(question)
for i in range(4):
print("\t", i + 1, "-", answers[i])
# get answer and validate
while True:
answer =(input("What's your answer?: "))
if answer >= '1' and answer <='4':
break
else:
print ("the number needs to be between 1 and 4, try again ")
# check answer
answer=str(answer)
if answer == correct:
print("\nRight!", end=" ")
return score
main()
Eighth: Please take time to make an answer before you post. People here want to answer questions, and try to answer them with the most effort they can put in, so we expect questioners to put in the same effort, to spend time on their questions (basically pretend you are asking the person you respect most in your life this question, then behave appropriately e.g. Dear your royal highness, beloved master and benefactor, who I so dearly love, please, oh please, do me the great kindness to answer my humble question that I have taken 2 days to write properly so you wouldn't be offended and have to waste as little time as possible with such a small thing as me...)
Ninth: There are much better ways to do what you want.
I suggest you:
Try perfecting parts of your program, before writing 108 lines
Try not having so many functions
Try to decrease the length of your code, make it not so verbose, but succinct
Use consistent formatting (e.g. only one type of quotes; only, spaces or tabs)
Also read up on some basic python (learn python the hard way is good)
I also highly recommend PEP (Python Enhancement Proposals) 8 and the other PEP's
Look at test-driven development in python
Related
I'm trying to figure out how to clear an "if" condition and how to fix the result = print(x) part of my code. I'm trying to create a little search code based on the variable data, but I can't figure a few things out:
import time
def start():
data = ["Lucas_Miguel", "João_Batista", "Rafael_Gomes", "Bruna_Santos", "Lucas_Denilson"]
print("1" + " - Check Name")
print("2" + " - Register a New Name")
option = input("Choose an option: ")
if option == "1":
def other():
name = input("Type the first name: ")
for x in data:
if name in x:
result = print(x)
while True:
print("Yes " "or " "No")
confirm = input("Is the name you want in the options?: ")
if confirm == "Yes":
break
if confirm == "No":
print("Yes", " or", " No")
try_again = input("Do you want to write again?: ")
if try_again == "Yes":
return other()
other()
else:
print("Option not available")
time.sleep(1)
return start()
start()
The first problem is in the result = print(x) part. It works, but when the answer is more than one name, only the first one appear and I don't know how to fix it.
The second problem is in the "confirm = input" part. Basically, if the person answered with "No", when they go back, the answer will still be saved and the input will run twice, the first time with the saved answer and the second with the new answer. So I want to be able to clear that before the person answer it again.
I want to apologize already if the code is ugly or weird, but I started a few days ago, so I'm still learning the basics. Also thanks in advance for the help.
There is quite a bit here to unpack and like the comment on the question suggests you should aim to look at how to ask a more concise question.
I have some suggestions to improve your code:
Split the other into its own function
Try to use more accurate variable names
As much as you can - avoid having multiple for loops happening at the same time
Have a look at list comprehension it would help a lot in this case
Think about whether a variable really belongs in a function or not like data
What you're asking for is not immediately clear but this code should do what you want - and implements the improvements as suggested above
import time
data = ["Lucas_Miguel", "João_Batista", "Rafael_Gomes", "Bruna_Santos", "Lucas_Denilson"]
def other():
name_input = input("Type the first name: ")
matches = [name for name in data if name_input in name]
if len(matches) == 0:
print ("No matches")
for name in matches:
print(name)
while True:
print("Yes " "or " "No")
confirm = input("Is the name you want in the options?: ")
if confirm == "Yes":
break
if confirm == "No":
print("Yes", " or", " No")
try_again = input("Do you want to write again?: ")
if try_again == "Yes":
return other()
else:
return
def start():
print("1" + " - Check Name")
print("2" + " - Register a New Name")
option = input("Choose an option: ")
if option == "1":
other()
else:
print("Option not available")
time.sleep(1)
return start()
start()
The first problem will be solved when you remove 8 spaces before while True:.
The second problem will be solved when you add return (without arguments) one line below return other() at the indentation level of if try_again == "Yes":
Everybody can see that you are just learning Python. You don't have to apologize if you think, your code is "ugly or weird". We all started with such small exercises.
I am a student and have been looking but not found an answer that makes sense to me yet so I apologise.
Basically I am creating a chatbot that will read out facts from a text file. I want the bot to read one line, then ask to continue. If Y, it reads out the next line until the end or the user says N.
So far it can read one line, then it just reads the same line over and over. I know there's other things wrong with it too but I'm just trying to get this part to work atm. I am self taught so sorry if this is bad.
Appreciate any input!
# Defining functions
def well_bot():
print("Hi there, my name is Well Bot. ")
print("My job is to tell people general facts about mental health and different types of mental illnesses. ")
info = get_info()
print(info)
#this should only print if they want a fact
getfact = print_facts()
print(getfact)
#var to read from illnesses text file to add later
def get_info():
res = input("What can I teach you about today? \n[a] Facts \n[b] Types \n> ")
if res == "a":
print ("Okay. I will give you some general facts about mental health. ")
with open('facts.txt') as facts:
next_fact = facts.readline()
print (next_fact)
return continue_ask()
elif res == "b":
return "Okay, I can tell you about two different mental illnesses: \n[1] Depression \n[2] Bipolar Disorder \n> "
else:
print_message()
return get_info()
def continue_ask():
while True:
if input("Want to know more? Enter Y to continue or N to finish: ") == "Y":
with open('facts.txt') as facts:
next_fact = facts.readline()
print (next_fact)
return continue_ask()
else:
print ("Okay, thanks, bye! ")
break
def print_message():
print("I'm sorry, I didn't quite get that. Can you choose again? ")
return get_info()
#Call Bot
well_bot()
This should do the trick
def gen_lines(filepath):
"""Lines Generator: Open the file and yield each line"""
with open(filepath) as f:
for line in f:
yield line
def choose_argument():
"""Ask the user to choose an argument and return the right line generator."""
argument = input("What can I teach you about today? \n[a] Facts \n[b] Types \n> ")
if argument.lower() == "a":
return gen_lines("facts.txt")
elif argument.lower() == "b":
return gen_lines("types.txt")
else:
print("I'm sorry, I don't know what you want me to do.")
return choose_argument()
def asking_loop(line_generator):
"""Looping the lines asking the user at each step."""
# Get the first line from the generator.
print(next(line_generator))
# Loop until the user says "no".
while True:
whant_more = input("Do you want to know more? \n[y] Yes \n[n] No \n> ")
if whant_more.lower() == "y":
print(next(line_generator))
continue
elif whant_more.lower() == "n":
print("Okay, thanks, bye! ")
break
else:
print("I'm sorry, I don't know what you want me to do.")
continue
def main():
"""Main function."""
print("Hi there, my name is Well Bot. ")
print("My job is to tell people general facts about mental health and different types of mental illnesses. ")
line_generator = choose_argument()
asking_loop(line_generator)
if __name__ == "__main__":
main()
Open once and store line-by-line in an array
file = []
with open('facts.txt') as facts:
file = facts.read().split('\n')
line = 0
def continue_ask():
global line
while True: # not a fan of that would rather self call imo
if input("Want to know more? Enter Y to continue or N to finish: ") == "Y":
line+=1
try:
print(file[line])
except IndexError:
print("no more facts left :(")
break
else:
print ("Okay, thanks, bye! ")
break
Python Beginner In Need Of Assistance
My program, being a true or false quiz where the user enters data which is saved, works in two parts.
Part #1: Program asks the user how many questions they have. The user then fills out a series of questions and answers for that amount. If the answer provided for a question is not (true) or (false) the program re-demands the answer. The user then saves to use this data in order to study in Part 2.
def vf():
import pickle
import random
import os
os.system('cls')
v = input("How many questions do you have : ")
vvff = list()
for i in range(0, int(v)):
v = input("Enter question : ")
while True:
f = input("Enter answer to that question (true or false) : ")
if f.lower() in ('true', 'false', 'True', 'False'):
continue
else:
print("This answer is invalid, please enter True or False")
vf = {"question": v, "answer": f}
vvff.append(vf)
question_vff = input("Would you like to save (yes or no) ")
if (question_vff == 'yes'):
pickle.dump(vvff, open("Save.dat", "wb"))
print("Saved!")
if (question_vff == 'no'):
print ("Please save to use you're data.")
Part #2: The user uses the save data from before to answer a true or false quiz. This quiz shuffles the questions and answers and the user answers each of them. If the user gets it right, the program says good job, if they get it wrong the program says wrong answer.
def vf2():
import pickle
import random
import os
os.system('cls')
vvff = pickle.load(open("Save.dat", "rb"))
random.shuffle(vvff)
for f in vvff:
print(f["question"])
response = input("What was the answer to that question? : ")
if (response == f["answer"]):
print("Good answer!")
else:
print("Wrong answer...")
print("The answer is", f, ".")
print("The study/quiz session is now over. Either create new data or try again later.")
My problem is that, in part 2, the program is supposed to shuffle the questions from the saved data and ask every single one to the user. However, it only asks for the last question they entered in part 1 of the program. What's causing this and how do I fix it? Help is greatly appreciated.
There's a little mistakes here and there so I will just go and correct them in one go:
def vf():
import pickle
import random
import os
os.system('cls')
n = input("How many questions do you have : ") #Changed v to n to avoid overlap
vvff = list()
for i in range(0, int(n)):
v = input("Enter question : ")
while True:
f = input("Enter answer to that question (true or false) : ")
if f.lower() in ('true', 'false'): #removed capitals, it's already lowercase
continue
else:
print("This answer is invalid, please enter True or False")
vf = {"question": v, "answer": f} #Moved inside for-loop
vvff.append(vf) #Moved inside for-loop
question_vff = input("Would you like to save (yes or no) ")
if (question_vff == 'yes'):
pickle.dump(vvff, open("Save.dat", "wb"))
print("Saved!")
if (question_vff == 'no'):
print ("Please save to use you're data.")
You can use := for python3.8
import os
import pickle
import random
from pathlib import Path
FILE = "Save.dat"
def clear():
os.system("cls")
def vf():
clear()
vvff = []
for _ in range(int(input("How many questions do you have: "))):
q = input("\nEnter question: ")
prompt = "Enter answer to that question (true or false): "
while (a := input(prompt)).lower() not in ("true", "false"):
print("This answer is invalid, please enter True or False")
vvff.append({"question": q, "answer": a})
tip = "\nWould you like to save [(yes)/no] "
while input(tip).strip().lower() not in ("yes", "y", ""):
print("Please save to use your data.\n")
Path(FILE).write_bytes(pickle.dumps(vvff))
print("Saved!")
def vf2():
clear()
vvff = pickle.loads(Path(FILE).read_bytes())
random.shuffle(vvff)
for qa in vvff:
print(qa["question"])
response = input("What was the answer to that question? ")
if (response == qa["answer"]):
print("Good answer!\n")
else:
print("Wrong answer...")
print(f"The answer is {qa} .\n")
print("The study/quiz session is now over. Either create new data or try again later.")
def main():
vf()
vf2()
if __name__ == "__main__":
main()
I have researched this subject, and cannot find a relevant answer, here's my code:
#Imports#
import random
from operator import add, sub, mul
import time
from random import choice
#Random Numbers#
beg1 = random.randint(1, 10)
beg2 = random.randint(1, 10)
#Variables + Welcoming message#
correct = 0
questions = 10
print ("Welcome to the Primary School Maths quiz!!")
print ("All you have to do is answer the questions as they come up!")
time.sleep(1)
#Name#
print("Enter your first name")
Fname = input("")
print ("Is this your name?" ,Fname)
awnser = input("")
if awnser == ("yes"):
print ("Good let's begin!")
questions()
if input == ("no"):
print("Enter your first name")
Fname = input("")
print ("Good let's begin!")
#Question Code#
def questions():
for i in range(questions):
ChoiceOp = random.randint (0,2)
if ChoiceOp == "0":
print (("What is " +beg1 ,op ,beg2))
begAns = input("")
if int(begAns) == beg1*beg2:
print("That's right -- well done.\n")
correct = correct +1
else:
print("No, I'm afraid the answer is ",begAns)
if ChoiceOp == "1":
print (("What is " +beg1 ,op ,beg2))
begAns = input("")
if int(begAns) == beg1-beg2:
print("That's right -- well done.\n")
correct = correct +1
else:
print("No, I'm afraid the answer is ",begAns)
if ChoiceOp == "2":
print (("What is " +beg1 ,op ,beg2))
begAns = input("")
if int(begAns) == beg1+beg2:
print("That's right -- well done.\n")
correct = correct +1
else:
print("No, I'm afraid the answer is ",begAns)
questions()
If I'm perfectly honest I'm not quite sure what's wrong, I have had many problems with this code that this wonderful site has helped me with, but anyway this code is designed to ask 10 random addition, subtraction and multiplication questions for primary school children any help I am thankful in advance! :D
You have both a function def questions() and a variable questions = 10. This does not work in Python; each name can only refer to one thing: A variable, a function, a class, but not one of each, as it would be possible, e.g. in Java.
To fix the problem, rename either your variable to, e.g., num_questions = 10, or your function to, e.g., def ask_question()
Also note that you call your questions function before it is actually defined. Again, this works in some other languages, but not in Python. Put your def quesitons to the top and the input prompt below, or in another function, e.g. def main().
Hi i wrote some code for a maths program and wanted some help to validate user input. I want the program to, when the user ignores a question and simply presses the enter key for the next question, to show them the exact same question again and notify them saying every question must be attempted. Heres the code i have so far
import time
import random
msg=0
questionsAsked=0
score=0
op = ["-","*","+"]
username= input("What is your name? ")
print("Okay "+username+ " lets begin the test. Good luck!")
praise= ["Well done!","Great job!", "Spot on!", "Perfect!"]
wrong = ["Unlucky!", "Not quite", "Incorrect"]
def actual(num1,num2,operation):
actual=eval(str(num1) + operation + (str(num2)))
return actual
def useranswer(num1,num2,operation):
useranswer=int(input(str(num1)+operation+str(num2)+"= "))
return useranswer
while questionsAsked <10:
num1 = random.randint(0,12)
num2 = random.randint(0,12)
operation = random.choice(op)
praiseMsg= random.choice(praise)
wrongMsg= random.choice(wrong)
if useranswer(num1,num2,operation) != actual(num1,num2,operation):
print(wrongMsg)
else:
print(praiseMsg)
score= score+1
questionsAsked=questionsAsked+1
else:
if score>5:
msg= str("Well done "+username+"! You scored over 50%")
else:
msg=str("Better luck next time " + username)
print("You scored " +str(score)+ " out of 10. \n" +msg )
time.sleep(3)
username = raw_input("What is your name? ")
while not username:
username = raw_input("Not understood. What is your name?")
You could wrap this in a function:
def insist_upon_answer(prompt):
answer = raw_input(prompt)
while not answer:
answer = raw_input("All questions must be answered. {}".format(prompt)
return answer
and call it:
name = insist_upon_answer("What is your name?")
Like triphook's answer, for Python 3:
username = input("Input: ")
while username=="":
username = input("Input (again): ")