0

Current assignment is building a basic text adventure. I'm having trouble with the following code. The current assignment uses only functions, and that is the way the rules of the assignment state it must be done.

def make_selections(response):
    repeat = True
    while repeat == True:
        selection = raw_input('-> ')
        for i, v in enumerate(response):
            i +=1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
            if selection == i:
                print v[1]
            else:
                print "There's an error man, what are you doing?!?!?"

firstResponse = 'You chose option one.'
secondResponse = 'You chose option two.'
thirdResponse = 'You chose option three.'

responses = [(0, firstResponse), (1, secondResponse),( 0, thirdResponse)]

make_selections(responses)

My intention in that code is to make it so if the user selects a 1, it will return firstResponse, if the user selects 2 it will return secondResponse, etc.

I am basically just bug testing the code to make sure it produces the appropriate response, hence the "Error man..." string, but for some reason it just loops through the error message without printing the appropriate response string. Why is this?

I know that this code is enumerating the list of tuples and I can call them properly, as I can change the code to the following and get the expected output:

for i, v in enumerate(response):
    i += 1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
    print i, v

Also, two quick asides before anyone asks:

  • I know there is currently no way to get out of this while loop. I'm just making sure each part of my code works before I move on to the next part. Which brings me to the point of the tuples.
  • When I get the code working, a 0 will produce the response message and loop again, asking the user to make a different selection, whereas a 1 will produce the appropriate response, break out of the loop, and move on to the next 'room' in the story... this way I can have as many 'rooms' for as long of a story as I want, the player does not have to 'die' each time they make an incorrect selection, and each 'room' can have any arbitrary amount of options and possible responses to choose from and I don't need to keep writing separate loops for each room.
5
  • 2
    Can you please fix the indentation on your code? Commented Oct 7, 2014 at 19:24
  • 1
    A couple side notes: enumerate(response, 1) will give you the 1-based indices without needing that i += 1. Also, you don't need while repeat == True:, just while repeat:. Commented Oct 7, 2014 at 19:26
  • A few points to think of - (1) what it the type of the raw input you're getting? what's type(selection) compared to type(i)? (2) responses contains tuples, and you're never using the first index of those tuples (i.e., you're not using the 0 of (0, firstResponse)). (3) If you're working with numbered options, do you even need that first index? surely there's an easier way to access the correct item on the response list, using the raw_input, without using a loop... Commented Oct 7, 2014 at 19:28
  • 2
    I don't see any downvotes here, but even if there were: The first thing you have to learn about SO is that votes are not a reflection on you, but on the question. And not even on the question's "abstract goodness", but on whether it's likely to improve SO as a searchable repository of questions and answers. The fact that you have 2 weeks of coding experience has nothing to do with how people should vote. Commented Oct 7, 2014 at 20:28
  • Thank you all for your comments and answers! @Korem, thank you for the Socratic approach to helping me with this problem. I noticed that i and selection where different types and fixed it by changing the relevant line to selection = int(raw_input('-> ')). I am not using the tuples currently because I haven't written that part of the code yet. I was planning on using them as a flag to to an if statement to break out of the loop and allow the code to continue in order for the player to progress into the next room. Commented Oct 7, 2014 at 20:48

3 Answers 3

1

There are a few problems here.

First, there's no good reason to iterate through all the numbers just to see if one of them matches selection; you already know that will be true if 1 <= selection <= len(response), and you can then just do response[selection-1] to get the v. (If you know anything about dicts, you might be able to see an even more convenient way to write this whole thing… but if not, don't worry about it.)

But if you really want to do this exhaustive search, you shouldn't print out There is an error man after any mismatch, because then you're always going to print it at least twice. Instead, you want to only print it if all of them failed to match. You can do this by keeping track of a "matched" flag, or by using a break and an else: clause on your for loop, whichever seems simpler, but you have to do something. See break and continue Statements, and else Clauses on Loops in the tutorial for more details.

But the biggest problem is that raw_input returns a string, and there's no way a string is ever going to be equal to a number. For example, try '1' == 1 in your interactive interpreter, and it'll say False. So, what you need to do is convert the user's input into a number so you can compare it. You can do that like this:

try:
    selection = int(selection)
except ValueError:
    print "That's not a number!"
    continue
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! By far the best solution and gave me more insight into what I'm doing and the most efficient way to do it. I actually just caught the problem with raw_input about 5 minutes ago and fixed it by changing the line to selection = int(raw_input('-> '))
1

Seems like this is a job for dictionaries in python. Not sure if your assignment allows this, but here's my code:

def make_selections(response):
   selection = raw_input('-> ')
   print response.get(selection, err_msg)

resp_dict = {
    '1':'You chose option one.',
    '2':'You chose option two.',
    '3':'You chose option three.'
}
err_msg = 'Sorry, you must pick one of these choices: %s'%sorted(resp_dict.keys())
make_selections(resp_dict)

1 Comment

The reason to use a dictionary is that you can have a key that is exactly equal to the string that is returned by "raw_input", so no convert to integer. Also, you can specify any string as the key, so if you want, you can have the user type "north", "south", or "east" as their choices, and this function still works, just make a dictionary with those keys as the options.
0

The problem is that you are comparing a string to an integer. Selection is raw input, so it comes in as a str. Convert it to an int and it will evaluate as you expect.

You can check the type of a variable by using type(var). For example, print type(selection) after you take the input will return type 'str'.

def make_selections(response):
    repeat = True
    while repeat == True:
        selection = raw_input('-> ')
        for i, v in enumerate(response):
            i +=1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
            if int(selection) == i:
                print v[1]
            else:
                print "There's an error man, what are you doing?!?!?"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.