Debugging Trivia game in Python - python

Creating function to print question, add choices to a list.
def print_et_list ():
answer_list = []
function = open ("modStory.txt","r")
#Question
question = function.readline()
print question
#Choices
one = answer_list.append (function.readline())
two = answer_list.append (function.readline())
for item in answer_list:
print item
#Solution
try:
solution = int(function.readline())
except:
print "There's an error in the answer"
##for the blank line
function.readline()
return question, one, two, solution, function
##Function for prompting the user for an answer, comparing an answer, keeping score and printing score.
def hey_user (solution):
score = 0
user_answer = int(raw_input ("Enter what you think the answer is, user.\n"))
if user_answer == solution:
print "You've got it right!"
score = score + 1
elif user_answer == 0:
sys.exit()
else:
print "You've got it wrong."
return score
def main ():
question, one, two, solution, function = print_et_list()
scoresofar = hey_user (solution)
print "\nYour score is now", scoresofar
while question:
question, one, two, solution, function = print_et_list()
function.close()
main ()
raw_input ("Hit enter to exit.")
For some reason I am unable to get this thing to loop properly. The code above infinte loops itself.
This following is the text file in question which is just garbled song lyrics. The program will run the first fragment properly, and will infinte loop the first fragment once the user gives the answer.
Can you carry my drink I have everything else
1 - I can tie my tie all by myself
2 - I'm getting tired, I'm forgetting why
2
is diving diving diving diving off the balcony
1 - Tired and wired we ruin too easy
2 - sleep in our clothes and wait for winter to leave
1
While it sings to itself or whatever it does
1 - when it sings to itself of its long lost loves
2 - I'm getting tired, I'm forgetting why
2

To correct the infinite loop, avoid to re-open the file on each call to print_et_list()
Try this (I renamed function into file_handle to be a little more explicit while reading the code)
import sys
def print_et_list (file_handle):
answer_list = []
#Question
question = file_handle.readline()
print question
#Choices
one = file_handle.readline()
two = file_handle.readline()
answer_list.append(one)
answer_list.append (two)
for item in answer_list:
print item
#Solution
solution = None
try:
result = file_handle.readline()
result.replace("\n","")
solution = int(result)
except:
print "There's an error in the answer"
##for the blank line
file_handle.readline()
return question, one, two, solution
##file_handle for prompting the user for an answer, comparing an answer, keeping score and printing score.
def hey_user (solution, score=0):
user_answer = int(raw_input ("Enter what you think the answer is, user.\n"))
print "you answered '%s'"%user_answer
if user_answer == solution:
print "You've got it right!"
score += 1
elif user_answer == 0:
sys.exit()
else:
print "You've got it wrong."
return score
def main ():
file_handle = open ("modStory.txt","r")
question, one, two, solution = print_et_list(file_handle)
scoresofar = hey_user(solution)
print "\nYour score is now", scoresofar
while question:
question, one, two, solution = print_et_list(file_handle)
if question:
scoresofar = hey_user(solution, scoresofar)
print "\nYour score is now", scoresofar
file_handle.close()
main ()
raw_input ("Hit enter to exit.")
This is not a perfect version, but it seems to work ;)

append doesn't return anything, so one and two are None.

Related

How do I Run a Background Timer for Each Prompt in My Word Game?

I'm making an unoriginal game for a first project that just runs in my python terminal. The user is randomly given a set of 2-3 letters and the user has to come up with a real word (checked by the Webster dictionary) that contains the given set of letters within 5 seconds. For example, if the game generates "le" the user can input "elephant" within 5 seconds as a correct word and gives them a point.
The problem is that I can't seem to implement the 5 second timer function to run in the back for every time a prompt is given without messing up some other part or running into another problem. I've looked into threading and can't seem to make use of it.
Here is the code for the main game:
from letters import letter_sets_list
fhand = open("words_dictionary.json")
data = fhand.read()
global score
score = int(0)
game_over = False
while game_over is False:
import random
random_letters = random.choice(letter_sets_list)
print('Word that contains:', random_letters)
answer = input("Type a word:")
if answer in data and random_letters in answer:
score += 1
print("nice one")
else:
game_over = True
print("Game Over \n Score:", score)
fhand.close()
exit()
Here is the timer function I found off YouTube and tried to implement:
def countdown():
global my_timer
my_timer = int(5)
for x in range(5):
my_timer -= 1
sleep(1)
countdown_thread = threading.Thread(target=countdown)
countdown_thread.start()
Take a look at that. Especially check if that will work for you:
import time
from threading import Thread
answer = None
def check():
time.sleep(2)
if answer != None:
return
print("Too Slow")
Thread(target = check).start()
answer = input("Input something: ")
Edit: I tried to implement code from my previous answer to your code but with a little different approach:
import time, threading
#from letters import letter_sets_list
#import random
#fhand = open("words_dictionary.json")
#data = fhand.read()
data = ["answer"]
answer = [None]
random_letters = [None]
global score
score = int(0)
game_over = False
x = 0
def game(answer, random_letters):
#random_letters = random.choice(letter_sets_list)
print('Word that contains:', random_letters)
while True:
answer[0] = input("Type a word: ")
mythread = threading.Thread(target=game, args=(answer, random_letters))
mythread.daemon = True
mythread.start()
for increment in range(5):
time.sleep(1)
if answer[0] in data: # and random_letters in answer
score += 1
print("Good answer")
x = 1
break
if x != 1:
print("\nTime is up")
else:
x = 0
game_over = True
In this approach I didnt use time.sleep() inside threaded function but outside of it which helps with killing it. Also i assumed that if your answer is incorrect you would like to have another chance to answer untill time is up or answer is correct so I just used while loop in threaded function. The code is quite simple so I think if you spend a little time analysing your parts of the code you will figure it out.
Some parts of the code I didn't use as I dont have access to your json files ect., but if I understand correctly what you're trying to do, it shoud work. Also check how will behave your kernel. In my case sometimes it shows some problems but my PC is not the best and so it might be only problem with RAM or other part of my computer as it happens quite often with my projects.

Python program does not behave as intended

I'm writing my first short programs with Python. This program should stop after the third wrong guess. The program works as expected with the first question, and stops itself after three wrong guesses.
However, I cannot understand why, with the second question, after the third wrong guess, the first question is repeated.
easy_text = '''Hello __1__!' In __2__ this is particularly easy; all you
have to do is type in: __3__ "Hello __1__!" Of course, that isn't a very
useful thing to do. However, it is an example of how to output to the user
using the __3__ command, and produces a program which does something, so it
is useful in that capacity..'''
def split_string():
global easy_text_splitted
easy_text_splitted = easy_text.split(" ")
return None
def level1():
print """You will get 3 guesses per problem
The current paragraph reads as such:"""
print easy_text
return first_question(3)
def first_question(guesses):
while guesses > 0:
split_string()
first_answer = raw_input("What should be substituted in for __1__?")
if first_answer.lower() == "world":
easy_text_splitted[1] = first_answer
easy_text_splitted[19] = first_answer
new_easy_text = " ".join(easy_text_splitted)
print new_easy_text
second_question(3)
else:
guesses -= 1
print "That's not the answer I expected. You have " +
str(guesses) + " guess(es) left"
return first_question(guesses)
def second_question(guesses):
while guesses > 0:
split_string()
second_answer = raw_input("What should be substituted in for 2?")
if second_answer.lower() == "python":
easy_text_splitted[4] = second_answer
new_easy_text = " ".join(easy_text_splitted)
print new_easy_text
else:
guesses -= 1
print "That's not the answer I expected. You have \n " +
str(guesses) + " guess(es) left"
return second_question(guesses)
def level_selection(index):
level = raw_input("Choose the desired level of difficulty: easy, \n
medium, or hard ")
if level.lower() == "easy":
return level1()
if level.lower() == "medium":
return level2
if level.lower() == "hard":
return level3
else:
print "Error"
index -= 1
if index > 0:
return level_selection(index)
return "Bye!"
print level_selection(3)
level2 = "You selected medium"
level3 = "You selected hard"
Whatever the value of guesses was in first_question when second_question was called, it is the same when it returns, so the loop continues, and repeats the first question.
Using a debugger will help you follow how this works.

What can you use instead of zip?

Soooo, this is killing me right now. Should've asked a lot earlier, but there we go. So I think there is something wrong with the zip that I've made, and it's driving me mad. If there's an another way to do this, please let me konw, but if you teach me how to use zip, that'll be great to. Also if someone can point out all the things I've messed up, that would be fantastic.
fun_string = """In ___0___, crazy ___1___ with ___2___, ate a meal called ___3___ on a grill""",
horror_string = """In ___0___ owned by ___1___, many were killed by ___2___ because of huanted ___3___""",
mystery_string = """The most mysterious place on Earth is ___0___, next to ___1___'s house because of a ___2___ living in ___3___"""
answers = [ ]
blanks = ["___0___", "___1___", "___2___", "___3___"]
def select_level():
user_input = raw_input("""Type in a story you wish to play: """)
while user_input not in ["Fun","Horror","Mystery"]:
user_input = raw_input("Invalid story. Please try again: ")
if user_input == "Fun":
quiz(fun_string, answers, blanks)
if user_input == "Horror":
quiz(horror_string, answers, blanks)
if user_input == "Mystery":
quiz(mystery_string, answers, blanks)
def zip(*iterables):
# zip('ABCD', 'xy') --> Ax By
iterables = map(iter, iterables)
while iterables:
yield tuple(map(next, iterables))
def quiz(quiz_string, answers, blanks):
print quiz_string
for answer, question in zip(answers, blanks):
raw_input ("Type in a word: ")
quiz_string = quiz_string.replace(blanks[1], answers)
if blanks == None:
print quiz_string
print """Welcome to kis ReMadlibs!!!!"""
print """Select a story you wish to particiate!!"""
print """Fun, Horror, Mystery"""
print select_level()
It's not clear why you're using your own zip() instead of Python's zip(), nor why you believe you need zip() at all. You can get this program to work by simplifying the code:
fun_string = """In ___0___, crazy ___1___ with ___2___, ate a meal called ___3___ on a grill"""
horror_string = """In ___0___ owned by ___1___, many were killed by ___2___ because of huanted ___3___"""
mystery_string = """The most mysterious place on Earth is ___0___, next to ___1___'s house because of a ___2___ living in ___3___"""
answers = []
blanks = ["___0___", "___1___", "___2___", "___3___"]
def select_level():
user_input = raw_input("Type in a story you wish to play: ")
while user_input not in ["Fun", "Horror", "Mystery"]:
user_input = raw_input("Invalid story. Please try again: ")
if user_input == "Fun":
quiz(fun_string, answers, blanks)
elif user_input == "Horror":
quiz(horror_string, answers, blanks)
elif user_input == "Mystery":
quiz(mystery_string, answers, blanks)
def quiz(quiz_string, answers, blanks):
print quiz_string
for blank in blanks:
answer = raw_input("Type in a word: ")
quiz_string = quiz_string.replace(blank, answer)
answers.append(answer)
print quiz_string
print """Welcome to kis ReMadlibs!!!!"""
print """Select a story you wish to particiate!!"""
print """Fun, Horror, Mystery"""
select_level()

Problems transferring information from one part of a function to another

While working on my program I have run into a problem where the information stored in Menu option 1 is not being transferred to Menu option 2. As you can see it is correctly stored when in menu one. When it returns to go to menu option 2 its like it never went to option 1.
update #1:
some suggestions I've had is to understand scope? from what I can tell the program is not passing the data along to its parent program even though I've typed out return in each of the definitions.
#Must be able to store at least 4 grades
#Each class can have up to 6 tests and 8 hw's
#Weighted 40%*testavg 40% hw average attendance is 20%
#User must be able to input a minimum grade warning
#after each test the your program must calculate the students average and issue warning if necessary
##Define the Modules##
import math
def menu (a): #2nd thing to happen
menuend = 'a'
while menuend not in 'e':
menuend = raw_input("Type anything other then 'e' to continue:\n")
print "What would you like to do ?"
menudo = 0
print "1 - Enter Courses\n2 - Select Course to Edit\n3 - Save File\n4 - Load File\n5 - Exit\n"
menudo = input("Enter Selection:")
if (menudo == 1):
menuchck = 0
menuchck = raw_input("\nYou have entered #1 (y/n)?:\n")
if menuchck in ["Yes","yes","y","Y"]:
x = m1()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 2):
menuchck1 = 0
menuchck1 = raw_input("\nYou have entered #2 (y/n)?:\n")
if menuchck1 in ["Yes","yes","y","Y"]:
x = m2()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 3):
print "Entered 3"
elif (menudo == 4):
print "Entered 4"
else:
print "Anything Else Entered"
def course(): #3rd thing to happen
b = {}
while True:
while True:
print "\n",name,", please enter your courses below ('e' to end):"
coursename = raw_input("Course Name:")
if (coursename == 'e'):
break
will = None
while will not in ('y','n'):
will = raw_input('Ok for this name : %s ? (y/n)' % coursename)
if will=='y':
b[coursename] = {}
print "\n",name,", current course load:\n",b
coursechck = None
while coursechck not in ('y','n'):
coursechck = raw_input("Are your courses correct (y/n)")
if coursechck =='y':
return b
else:
b = {}
print
##Menu Options##
def m1():
a = course()
return a
def m2():
print "Excellent",name,"lets see what courses your enrolled in\n"
print x
return x
###User Input Section###
name = raw_input("Enter Students Name:\n")
a = {}
menu(a)
raw_input("This is the end, my only friend the end")
In your if-elif blocks in the do==1 case, you write m1(), but for the last case, you write x=m1(). You should have the latter everywhere (by typing m1() you only run the function, but do not store the returned x anywhere).
By the way, you can avoid this if-elif confusion using if chck in ["Yes","yes","Y","y"]:

Python custom modules - error with example code

I am reading the book "Python Programming for the Absolute Beginner (3rd edition)". I am in the chapter introducing custom modules and I believe this may be an error in the coding in the book, because I have checked it 5 or 6 times and matched it exactly.
First we have a custom module games.py
class Player(object):
""" A player for a game. """
def __init__(self, name, score = 0):
self.name = name
self.score = score
def __str__(self):
rep = self.name + ":\t" + str(self.score)
return rep
def ask_yes_no(question):
""" Ask a yes or no question. """
response = None
while response not in ("y", "n"):
response = input(question).lower()
return response
def ask_number(question, low, high):
""" Ask for a number within a range """
response = None
while response not in range (low, high):
response = int(input(question))
return response
if __name__ == "__main__":
print("You ran this module directly (and did not 'import' it).")
input("\n\nPress the enter key to exit.")
And now the SimpleGame.py
import games, random
print("Welcome to the world's simplest game!\n")
again = None
while again != "n":
players = []
num = games.ask_number(question = "How many players? (2 - 5): ", low = 2, high = 5)
for i in range(num):
name = input("Player name: ")
score = random.randrange(100) + 1
player = games.Player(name, score)
players.append(player)
print("\nHere are the game results:")
for player in players:
print(player)
again = games.ask_yes_no("\nDo you want to play again? (y/n): ")
input("\n\nPress the enter key to exit.")
So this is exactly how the code appears in the book. When I run the program I get the error IndentationError at for i in range(num):. I expected this would happen so I changed it and removed 1 tab or 4 spaces in front of each line from for i in range(num) to again = games.ask_yes_no("\nDo you want to play again? (y/n): ").
After this the output is "Welcome to the world's simplest game!" and that's it.
I was wondering if someone could let me know why this is happening?
Also, the import games module, is recognized in Eclipse after I added the path to PYTHONPATH.
I actually have this book myself. And yes, it is a typo. Here is how to fix it:
# SimpleGame.py
import games, random
print("Welcome to the world's simplest game!\n")
again = None
while again != "n":
players = []
num = games.ask_number(question = "How many players? (2 - 5): ", low = 2, high = 5)
for i in range(num):
name = input("Player name: ")
score = random.randrange(100) + 1
player = games.Player(name, score)
players.append(player)
print("\nHere are the game results:")
for player in players:
print(player)
again = games.ask_yes_no("\nDo you want to play again? (y/n): ")
input("\n\nPress the enter key to exit.")
All I did was indent num 4 spaces and lined it up with the first for-loop.
You have an infinite loop here:
again = None
while again != "n":
players = []
If this is exactly the way it's printed in the book, the book does have an error.
You've got these two lines:
num = games.ask_number(question = "How many players? (2 - 5): ", low = 2, high = 5)
for i in range(num):
The second one is more indented than the first. That's only legal if the first one is a block-introducer like a for or while or if. Since it's not, this is an IndentationError. And that's exactly what Python is telling you.
(It's possible that you've copied things wrong. It's also possible that you're mixing tabs and spaces, so it actually looks right in your editor, but it looks wrong to Python. But if neither of those is true, the book is wrong.)
So, you attempted to fix it by dedenting everything from that for loop on.
But when you do that, only one line is still left under the while loop:
while again != "n":
players = []
There's nothing that can possibly change again to "n", so this will just spin forever, doing nothing, and not moving on to the rest of the program.
So, what you probably want to do is to indent the num = … line to the same level as the for i… line, so both of them (and all the stuff after) ends up inside the while loop.

Categories