user7433120 user7433120 - 4 years ago 94
Python Question

I am having difficulty understanding why the string index is out of range

The program I am trying to make checks for reiterances of letter in the given word, however, when the word has multiples of the same letter, for instance 'hello' has multiple 'l', the program prints an error saying that the string index is out of range, and I am curious as to why that is.
I have looked at the other threads, but i am still curious as to why that is.
The bottom for loop is where the issue is located.

right =""
guess=""
attempts = 6
tries = 0

print("Hangman: guess letters until you can guess the word or phrase.")
print("In this game you get six tries.")

right_str = str(input("\nEnter your word: "))

#checks to see if user input is all letters or if there are none letters in the string
while right_str.isalpha()==False:
print("Error, only letters are accepted as an input")
right_str = str(input("Enter your word: "))

#displays the proper amount of unknown spaces
for i in range(0, len(right_str)):
right += "-"


print("current: " + right)
print("0 guesses so far out of 6: " + guess)

for i in range(0, 6):
guessed = str(input("Letter guessed: "))

if guessed.lower() in right_str.lower():
for i in range(0, len(right_str)):
if right_str[i] in guessed:
right = right[:i] + guessed[i] + right[i + 1:]
print(right)

Answer Source

Re the code segment:

if guessed.lower() in right_str.lower():
    for i in range(0, len(right_str)):
        if right_str[i] in guessed:
            right = right[:i] + guessed[i] + right[i + 1:]
            print(right)

If guessed is a single letter, what do you expect will happen in your loop when you use guessed[i]? Bottom line, you should be using guessed on its own, not attempting to index it.


By the way, while your attempts to handle varying case in your input is commendable, you've left at least one small hole in it with the third line above (not using guessed.lower()).

You'll probably find it's better to convert everything to lower (or upper) case as it's entered, and store it consistently. That way, comparisons will automatically be correct.


And, one final note, your print statement which outputs the updated right string is happening within the loop meaning that a word like hello or Mississippi is going to result in a lot of outputs for certain guesses.

If your intent is to print out the new result after all occurrences of the current letter have been added, simply move the print to outside the loop, something like (with the added changes suggested in the previous section as well):

right_str = str(input("\nEnter your word: ")).lower()
:
guessed = str(input("Letter guessed: ")).lower()
:
if guessed in right_str:
    for i in range(0, len(right_str)):
        if right_str[i] in guessed:
            right = right[:i] + guessed + right[i + 1:]
    print(right)

And, of course, there's almost always a more Pythonic way to do this:

right = "".join([right_str[i] if right_str[i] == guessed else right[i] for i in range(len(right_str))])

I'll leave that as an exercise for the reader to figure out how it works. Once you grok that, you can probably consider yourself a true Pythonista :-)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download