Sign in to follow this  

I need guidance (not the answer) to a python question.**Ok, now I need an answer..**

This topic is 3028 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, I'm trying to do something new to me, not sure if it's even possible going the route I'm going and I am having trouble finding any good search results for my attempt (so assuming I'm trying something wrong or taking it the wrong direction). In my program I have a nested while statement that asks for users to answer a yes/no question. If they answer yes, the loop breaks and the program continues, however, if they answer 'no' then it currently re-asks the same question. Here's the code:
while 1:
                ready = raw_input("How about now? (Yes/No) ")
                if ready == 'yes':
                    print "It's about time!  I was getting bored."
                    break




What I'd like to do is if the user types 'no' that the program asks a question, but it takes the questions from a pre-made dictionary or list. Then, every time the user types 'no' the program will take the next response from the list and print it. So, if I have a dictionary or list of 5 responses, each time the user types 'no' it will respond with the next phrase in the list. So far I've been trying to figure out how to do this using a dictionary to hold the phrases. response = {1:'phrase 1',2:'phrase 2',3:'phrase 3'} I am not sure if this is the right way to approach it, but I don't know how to handle getting each value (or returning the key as a value) one at a time and being able to print the result(well ok that's not true, I know how to get the value from a dictionary using the dictVar.get method). I don't want to have to write a new line for every response and make a ton of while loops. I figured there must be a way to have the code automatically pick the next phrase in some sort of loop using a dictionary or list. So, I don't want or need the answer to the question all coded out for me, I just need a hint at what direction I should be going. I'd like to figure some of this out on my own if possible. Should I be using a dictionary? A List? Should I write my own function to handle some of this? Thanks a bunch! [Edited by - Landshark on August 19, 2009 12:21:54 AM]

Share this post


Link to post
Share on other sites
You could use an array (or map, with integer keys) and store a variable that counts how many times 'no' is entered. Or you could use a list of phrases, and slice the head (or tail, depending on which you take) off the list everytime the head (or tail) is used...

If you go the list method, you could look into the 'pop' function for lists.

Share this post


Link to post
Share on other sites
Thanks a million Choffstein, I figured it out using lists.

Now I have a totally new error happening, my program hangs (crashes) when I receive the IndexError (which I catch the exception for). I don't know what I'm missing, the except IndexError is suppose to be caught, but when it gets to that point the program freezes.


Here's the whole thing: **Note, running this program will cause the program to hang/possibly freeze your pc**


"""
This is a guess a number game. It's created using while loop to only break when the user guesses the correct number
"""


#Need to first have the code find a random number and set it to a variable
import random

number = random.randint(1,10)
ready = 'placeholder'
quitnow = 'placeholder'
phrases = ['How about now? [Yes/No] ', "You're not ready yet? [Yes/No] ", "Seriously, what are you doing that's taking so much time? Can we play now? [Yes/No] ", "I can't wait any longer! Last chance, are you ready? [Yes/No] "]


#Here is the intro text to the game

print ""
while 1:
print "Welcome to the Number Guessing Game!"
print ""
print "I will now think of a number between 1 and 10 and"
print "you will try to guess it."

#Ask the user if thye are ready to play
while 1:
if quitnow == 'quitnow':
break
if ready == 'yes':
break
ready = raw_input("Are you ready to play? (Yes/No) ")
if ready == 'yes':
print "Alright, let's begin!"
break
elif ready == 'no':
while 1:
try:
ready = raw_input(phrases.pop(0))
if ready == 'yes':
print "It's about time! I was getting bored."
break
except IndexError:
quitnow = 'quitnow'





#next, create the while loop that controls the guessing

while 1:
if quitnow == 'quitnow':
print 'That\'s it, I\'m leaving!'
break
guess = int(raw_input("What number am I thinking of? "))
if guess == number:
print "Congratulations, you have guessed the correct number!"
break
elif guess != number:
print "Try again..."

playagain = raw_input('Play again? [Yes/No] ')
if playagain == 'no':
break



It took me about 30 minutes just to figure out I originally had my except in the wrong indent (IDLE was giving a syntax error), and I finally got in the right place (I think), and now my program freezes. :(


Share this post


Link to post
Share on other sites
Hopefully I don't give away too much here:

Using the for loop in python you can iterate over every element in a list without slicing or any stupid tricks.
Nest a while loop and you're done.
If you need the responses simply declare a list somewhere outside your loops and append the user inputs to it.


ques = ["Are you a plant?", "Are you a man?"]
resp = []
for q in ques:
while 1:
userinp = str(raw_input(q+" "))
resp.append(userinp)
if userinp == "yes":
break
else:
continue # don't actually need this, it restarts the inner while





E:
Judging by your post this doesn't actually do what you want. Something more similar to what you were trying to do is this:

# Added some comments
import random
no = random.randint(1,10)
ques = ["Want to play? [yes/no]", "Again, want to play? [yes/no]"]
userinp = ""
for q in ques: # for every element in ques assign it to q and do the following
userinp = str(raw_input(q+" ")) # get our userinput
if userinp == "yes": # they answered yes to one of our questions
while 1: # prompt the user for a guess, forever
guess = int(raw_input("Guess a number 1<n<10: "))
if guess == no: # they guessed right
print "Got it!"
break # break out of while loop
else: # guess again
print "Try again."
break # leave for loop (quits)
else: # they didn't answer yes
continue # go on to the next question





Sorry, took me a couple of minutes to test that.

[Edited by - monkey_32606 on August 19, 2009 11:23:43 AM]

Share this post


Link to post
Share on other sites
Monkey, thank you. I'm not reading your spoiler quite yet. :)

I was able to get the program to actually function. I figured out I was causing an infinite loop here:


while 1:
try:
ready = raw_input(phrases.pop(0))
if ready == 'yes':
print "It's about time! I was getting bored."
break
except IndexError:
quitnow = 'quitnow'



Because it would just keep looping the 'try' and the list was already empty, so it would keep catchin the exception, over and over, infinite loop. :)

I fixed that by adding

if quitnow == 'quitnow':
break

under the while 1:


One problem fixed, another one emerges. So, I have a problem now where if I do get to the prompt "Play again? [Yes/No]" and choose 'yes' it will continue with this prompt:

I can't wait any longer! Last chance, are you ready? [Yes/No] no
That's it, I'm leaving!
Play again? [Yes/No] yes
Welcome to the Number Guessing Game!

I will now think of a number between 1 and 10 and
you will try to guess it.
That's it, I'm leaving!
Play again? [Yes/No] yes
Welcome to the Number Guessing Game!


I see that 'quitnow' is now equal to 'quitnow' which is then caught in the first while loop

if quitnow == 'quitnow':
break

So it skips all of the code and goes to the end of the first while loop.

Now I am trying to figure around using the quitnow/break scenario inside the first loop.

I know the code is a bit messy, but it's teaching me good things so far. :)


Share this post


Link to post
Share on other sites
A suggestion:


# use a bool instead of those quitnow = "quitnow"
a = True # note capital T (lower case true is undefined)
b = False # as above
if a:
print "You will see this."
if b:
print "You will NOT see this."




I had another but I forgot it while I was typing this one up. :(

Share this post


Link to post
Share on other sites
Hey Monkey, thanks again. Using bools solved my last issue. My program now works completely as intended. Now it's just a matter of making the code cleaner (such as not catching an exception and using it as a function of the code).


Full source:


"""
This is a guess a number game. It's created using while loop to only break when the user guesses the correct number
"""


#Need to first have the code find a random number and set it to a variable
import random
number = random.randint(1,10)
ready = 'placeholder'
phrases = ["How about now? [Yes/No] ", "You're not ready yet? [Yes/No] ", "Seriously, what are you doing that's taking so much time? Can we play now? [Yes/No] ", "I can't wait any longer! Last chance, are you ready? [Yes/No] "]


#Here is the intro text to the game

print ""
while 1:
quitnow = False
print "Welcome to the Number Guessing Game!"
print ""
print "I will now think of a number between 1 and 10 and"
print "you will try to guess it."

#Ask the user if thye are ready to play
while 1:
if quitnow:
break
if ready == 'yes':
break
ready = raw_input("Are you ready to play? (Yes/No) ")
if ready == 'yes':
print "Alright, let's begin!"
break
elif ready == 'no':
while 1:
if quitnow:
break
try:
ready = raw_input(phrases.pop(0))
if ready == 'yes':
print "It's about time! I was getting bored."
break
except IndexError:
quitnow = 'quitnow'





#next, create the while loop that controls the guessing

while 1:
if quitnow:
print 'That\'s it, I\'m leaving!'
break
guess = int(raw_input("What number am I thinking of? "))
if guess == number:
print "Congratulations, you have guessed the correct number!"
break
elif guess != number:
print "Try again..."

playagain = raw_input('Play again? [Yes/No] ')
if playagain == 'no':
break




I've used the for loop in practice, but I'm not grasping your for loop code at a glance yet, so that's my next step.

Thanks again everyone, this is really fun and awesome. :)




Share this post


Link to post
Share on other sites
You're having to catch an exception because you're popping elements off of your phrases list and when it reaches the end there is no phrase to remove from the empty list. You've got a couple of options on how to handle this. First option; keep track of the number of elements in the list and simply not pop the last one. Second option; iterate over every element in the list of phrases using a for loop. The second piece of code I posted uses this method.

While it's not really wrong, most people would recommend that you not deliberately trigger exceptions to break out of code either.

Share this post


Link to post
Share on other sites

I'm rewriting my code for this small program, because I want to learn how to write it more efficiently.

Basically, here's what I've come up with so far (using many of the above suggestions and tailoring them to my program):

I'm calling this program "Guess a Number Game V2.0"


import random
quitnow = False
test = "test" #only used for testing purposes
ready = "placeholder"
phrases = ["Are you ready to play? (Yes/No) ",
"How about now? [Yes/No] ",
"You're not ready yet? [Yes/No] ",
"Seriously, what are you doing that's taking so much time? Can we play now? [Yes/No] ",
"I can't wait any longer! Last chance, are you ready? [Yes/No] "]


#Here is the intro text to the game
print ""
print ""
while 1:
if quitnow:
break
print "Welcome to the Number Guessing Game!"
print ""
print "I will now think of a number between 1 and 10 and"
print "you will try to guess it."
print ""

#Ask the user if they are ready to play
while 1:
number = random.randint(1,10)
if quitnow:
break
if ready == 'yes':
break
for que in phrases:
ready = raw_input("%s" %que)
if ready == 'yes':
print "Alright, let's begin!"
while 1:
guess = int(raw_input("What number am I thinking of? "))
if guess == number:
print "Congratulations, you have guessed the correct number!"
break
elif guess !=number:
print "Try again..."
print ""

playagain = raw_input("Play again? [Yes/No] ")
if playagain =='no':
quitnow = True
break
break






I'm trying to work through the issues on my own, but so far here's what up.

First, if the player completes the game (guesses the number) and chooses to play again, when the program restarts it grabs the 2nd string in the 'phrases' list rather than starting over with the first one. I tried to combat this by tossing in the very last break to hopefully get out of the 2nd while loop, but it doesn't seem to work.

Second, same issue, because I'm not able to get out of the 2nd while loop the random number is not random after the first play through, the code 'random = random.randint(1,10)' is only checked once, so it's keeping the same number value in the 'number' variable.

I think the major issue (unless I'm missing something else) is figuring out how to break out of the 2nd while loop.

Other than that, my code looks a lot cleaner than what I previously had.

Share this post


Link to post
Share on other sites
Think about how you want the course of the program to go. To me, it seems to have two distinct phases:

1. Ask the player to play, until he agrees to.
2. Play guess-the-number with the player.
(3. Repeat.)

Perhaps you should split up 1 and 2. Right now they're all cuddly with each other.

Share this post


Link to post
Share on other sites
Thanks sneftel,

My program actually was working as intended the way it was originally written.

Original code:


"""
This is a guess a number game. It's created using while loop to only break when the user guesses the correct number
"""


#Need to first have the code find a random number and set it to a variable
import random
number = random.randint(1,10)
ready = 'placeholder'
phrases = ["How about now? [Yes/No] ", "You're not ready yet? [Yes/No] ", "Seriously, what are you doing that's taking so much time? Can we play now? [Yes/No] ", "I can't wait any longer! Last chance, are you ready? [Yes/No] "]


#Here is the intro text to the game

print ""
while 1:
quitnow = False
print "Welcome to the Number Guessing Game!"
print ""
print "I will now think of a number between 1 and 10 and"
print "you will try to guess it."

#Ask the user if thye are ready to play
while 1:
if quitnow:
break
if ready == 'yes':
break
ready = raw_input("Are you ready to play? (Yes/No) ")
if ready == 'yes':
print "Alright, let's begin!"
break
elif ready == 'no':
while 1:
if quitnow:
break
try:
ready = raw_input(phrases.pop(0))
if ready == 'yes':
print "It's about time! I was getting bored."
break
except IndexError:
quitnow = 'quitnow'





#next, create the while loop that controls the guessing

while 1:
if quitnow:
print 'That\'s it, I\'m leaving!'
break
guess = int(raw_input("What number am I thinking of? "))
if guess == number:
print "Congratulations, you have guessed the correct number!"
break
elif guess != number:
print "Try again..."

playagain = raw_input('Play again? [Yes/No] ')
if playagain == 'no':
break





I was trying to condense the code using some people's suggestions (using the for function, as an example), but right now it's looking even more complicated to me than before.

I guess a good question I should ask is, does a good programmer focus on readable code or shorter code as a priority? And, does my source of the completed program qualify as easily readable?

Maybe I should have just left this one alone and gone on to something new.

Share this post


Link to post
Share on other sites
Quote:
I guess a good question I should ask is, does a good programmer focus on readable code or shorter code as a priority?
That's a good question to ask, and the answer is usually that readable code and short code are the same thing.
Quote:
And, does my source of the completed program qualify as easily readable?
No.

I understand the temptation to give up on this particular miasma, and perhaps you should. Rewrite the program from scratch, without looking back at your original code, at all, for any reason. And here is your assignment: For this particular implementation, each loop of any kind that you write must have a statement block that does nothing but call a function. (A function that you've written, presumably.) Optionally, it can break if the function returns True. That is, the only loops you can write must be of the sort:


for blah:
someFunc(whatever)

or

while blah:
if someOtherFunc(hey+ho): break


Also, the functions should have short, understandable names that concisely, accurately, and completely describe what the body of the function does.

I know this sounds like kind of a lot of random proscriptions, but I think the root of this miasma is an incomplete separation of behavior, and a conceptual leak between nested loops. Give it a try, see if it doesn't help.

Share this post


Link to post
Share on other sites
Is there any recommended reading material in relation to functions, defining functions and examples?

I don't know why, but I have major 'writers block' when trying to rewrite this code using your above lesson plan.

So far I'm trying to write a function for each section of the code (using readable function names). Some of it works so far, but the part I'm stuck at is trying to pull one of the items from the questions list (just a fun thing to try and make work).

I have a list: questions = ("question 1","question 2","question 3")

I use a questions.pop(0) function to ask the questions in order, but when the list is empty the program errors (I understand this). I'm not sure how to avoid this though, although I've thought about adding a retry argument in the function that counts down to 0, at which point it will break out of the function loop.


Here's the code so far, it's not completed obviously.


import random

questions = ["Are you ready to play? [Yes/No] ",
"How about now? [Yes/No] ",
"Are you finally ready to play? [Yes/No] ",
"I'm getting really bored, are you ready yet? [Yes/No] "]


def ask_play_game():
if questions == []: ##I have no idea how to get the function to stop .pop'ing the list once it's empty.
print "Fine, if you don't want to play then neither do I!"
quit
ready = raw_input(questions.pop(0))
if ready == "y" or "ye" or "yes":



def create_random_number():
number = random.randint(1,10)

def play_game():
create_random_number()
guess = int(raw_input ("What number am I thinking of? "))
if guess == number:
print "Congratulations, you guessed the number!"







As you can see I'm writing the functions that will later be called using loops (I hope this is on the right track for what was suggested in the post above this one). I think I have the idea down, but am just missing some understanding of the techniques.

Being the beginner that I am, perhaps I should try some more basic function lessons before completing the above code. I'm still waiting for the 'Ahh hah!' moment when dealing with functions. I know how to use arguments in functions, but haven't really seen it put to real world use yet to fully understand it.

Share this post


Link to post
Share on other sites
To quit the running program, 'quit' has to be called; thus, 'quit()'.

But that's a quite heavy-handed way of doing things. The normal way to keep your code organized is to arrange things in such a way that you just naturally break out of every bit of running code.

You might put the logic for checking if the question list is empty somewhere else. For example, you're going to have a loop somewhere that repeatedly calls ask_play_game(), right? So, the natural place to check is in the condition for that loop:


while questions != []:
answer = ask_play_game(questions)
# do something with the answer:
# we need to check the answer, and either call play_game(), or keep asking.
# Of course, if we call play_game(), we don't want to keep looping after
# play_game() finishes, so we would have to 'break' at that point. I trust
# you can figure out what this bit of code looks like.
# If we get here, the questions have run out. So we can just let this be the
# end of the program, and we automatically "quit".


Also notice that instead of relying on global variables, I write the code such that the 'questions' are passed to the asking function. (Similarly, I would have the asking function expect that parameter and use it instead of a global.)

Finally, try writing your code top-down instead of bottom-up. Write the main function first. Write as if the functionality you need already existed; then fill it in. That way, you always know what's missing (because you've already written code that requests it).




Oh, and this: ready == "y" or "ye" or "yes" doesn't do what you apparently think it does. The meaning of 'or' doesn't change because of the == sign; it still checks the truth value of whatever is on either side. The first 'or', for example, has ready == "y" on the left, and "ye" on the right. And "ye" is always true (since it's a non-empty string). (Actually, it's a little more subtle than that in Python because of how the type system works, but that gets the idea across.)

In Python, to check if a value is any of several candidates, you can ask if the value is 'in' a sequence (list or tuple; it's good style to use a tuple for fixed data) of the candidates. Thus, ready in ("y", "ye", "yes").

Share this post


Link to post
Share on other sites

This topic is 3028 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this