Search code examples
pythonpython-3.xattributeerror

Attribute error problems with python hangman code


I have some trouble with my python hangman code and i cant seem to be able to fix it. Just to let everyone know I am new to coding and am still learning how to do stuff. It would be much appreciated if anyone could help me. I find that the same happens when I try to "append" at any other part of the code from the while loop from under the "print... dashes" part.Thank you!

Here is the code:

import random

name = input("Hello, my name is H.A.N.K.M.A.N! What is yours?: ")
print("Hello, "+name," do you wanna play Hangman? Yes? Well why didn't you say so? Lets Goooooooo!")

def extractwords(filename,number):
    myfile=open(filename+".txt","r")
    details=myfile.readlines()
    myfile.close()
    words=[]
    for i in details:
        for item in i.split():
            letter=True
            for j in item:
                if j.isalpha()==False:
                    letter = False
            item = item.lower()
            if len(item)==number and letter==True and item not in words:
                    words.append(item)
    return words
player = "y"
while player =="y":
    complete=0
    guessed=[]
    errors=""
    characters = random.randint(5,9)
    tries = characters+3

    wordlist=extractwords("wordlist",characters)
    word=random.choice(wordlist)
    print("Testing word:",word)
    print("You have "+ str(tries)+" tries left")

    letters=[]
    for i in word:
        letters.append(i)

    hword=[]
    for i in range(0,characters):
        hword.append("-")

    dashes=""
    for i in hword:
        dashes = dashes+i

    print("The word you need to guess is ",dashes)
    while complete < characters and tries > 0:
        guess = input("Please input your letter: ")
        if guess in word:
            guessed.append(dashes)
            print("Noice job! You guessed the right letter!")
            tries=tries-1
            print("You have "+ str(tries)+" tries left")
            print(dashes)
            if len(guessed) == len(word):
                print("What? How did this happen? Yuu must have been cheating!Just Kidding! You did a good job on finding the word, so a GOOD JOB is in order!")
                layer = input("Would you like to play again? y/n: ")
        elif guess.isalpha and guess not in word:
            tries=tries-1
            print("I am sorry, but your guess is a number / not part of the word that I am thinking off. Please have another go!")
            errors.append(guess)
            print("The letters you entered so far:", errors)
            print("You have "+ str(tries)+" tries left")
        elif len(guess)!=1 or "abcdefghiklmnoopqestuvwxyz":
            print("Please enter a valid/single letter.")
        elif guess in guessed:
            print("Please enter a letter that you havent entered previously. ")
        else:
            pass
    if tries==0:
        print("You lose!The word you were supposed to guess was ",word)
player = input("Would you like to play again? y/n: ")

`


Solution

  • Ok, so I reviewed your code and you've got more than one problem. THAT'S OKAY. You're new to this. Anyways, I'll go through piece by piece and describe them for you, as well as how to fix them. Ok, let's begin:

    letters=[]
    for i in word:
        letters.append(i)
    

    This code, while it works perfectly fine, is highly redundant. You could replace it simply with letters = list(word).

    hword=[]
    for i in range(0,characters):
        hword.append("-")
    
    dashes=""
    for i in hword:
        dashes = dashes+i
    

    These two go together. you could replace the first with ['-']*characters and the second with '-'*characters. Remember that when you multiply a list (and in this case, strings are lists of characters) by an integer, it returns a list made of that many repetitions of your original list. Even more space efficient... If you defined dashes first, you could follow that up with hword = list(dashes).

    guessed.append(dashes)
    

    I already told you about this one in the comments, but here I go again. guessed should be taking your guess value, not your dashes value.

    print(dashes)  #line 46
    

    Once again... You never change dashes, so you shouldn't print it.

    elif guess.isalpha and guess not in word:
        tries=tries-1
        print("I am sorry, but your guess is a number / not part of the word that I am thinking off. Please have another go!")
        errors.append(guess)
        print("The letters you entered so far:", errors)
        print("You have "+ str(tries)+" tries left")
    elif len(guess)!=1 or "abcdefghiklmnoopqestuvwxyz":
        print("Please enter a valid/single letter.")
    elif guess in guessed:
        print("Please enter a letter that you havent entered previously. ")
    else:
        pass
    

    Before you check if guess is in word, you should probably check it to see if it's even valid. This isn't just python, this is code security in general. The most basic hacking technique is sending input so large that it busts into another part of memory. This is bad. Check yourself before you wreck yourself. I, personally, would do something like this:

    while ...
      #get input
      If not is_valid(your_input):
        continue
      #Do what you want with the input
    

    You'd have to define is_valid(), but that's the gist. The cool part of this code is the continue statement. continue loops the loop back to the start.

    if guess in word:
        guessed.append(guess)
        print("Noice job! You guessed the right letter!")
        tries=tries-1
        print("You have "+ str(tries)+" tries left")
        print(dashes)
        if len(guessed) == len(word):
            print("What? How did this happen? Yuu must have been cheating!Just Kidding! You did a good job on finding the word, so a GOOD JOB is in order!")
            layer = input("Would you like to play again? y/n: ")
    

    Ok, for one, you misnamed player as layer. Tucking fypos. For another, you should probably move your statement beginning in tries=... and ending in ...dashes) (lines 44-46) to outside the if statement. Maybe set that at the very end of your loop so that it's encountered whenever there's a valid input?

    Now, the biggest error I see in your code: dashes. You keep using it, but it's always got the same value. You need to add a section of code in your if guess in word: conditional that updates hword or dashes with your new guess. It's not a simple task, as if your word is bookkeeper, then you'd have to replace e not once, but three times.

    elif len(guess)!=1 or "abcdefghiklmnoopqestuvwxyz":
        print("Please enter a valid/single letter.")
    

    This one... Ok, so I know I've already gone over this section of code, but this has an especially egregious error. You can't say your alphabet right. The section with the alphabet does less than nothing. I assume what you meant is not guess in 'abcdefghijklmnopqrstuvwxyz', but because you left the first part out, it always evaluates to True.

    player = input("Would you like to play again? y/n: ")
    

    This is the one at the end. It's got a problem with indentation. When your game finishes, it'll never be called because it's outside the primary while loop.

    That being said, your code isn't too bad. Here's my fixes:

    import random
    
    name = input("Hello, my name is H.A.N.K.M.A.N! What is yours?: ")
    print("Hello, "+name," do you wanna play Hangman? Yes? Well why didn't you say so? Lets Goooooooo!")
    
    def extractwords(filename,number):
        myfile=open(filename+".txt","r")
        details=myfile.readlines()
        myfile.close()
        words=[]
        for i in details:
            for item in i.split():
                letter=True
                for j in item:
                    if j.isalpha()==False:
                        letter = False
                item = item.lower()
                if len(item)==number and letter==True and item not in words:
                        words.append(item)
        return words
    player = "y"
    while player =="y":
        complete=0
        guessed=""
        errors=""
        characters = random.randint(5,9)
        tries = characters+3
    
        wordlist=extractwords("wordlist",characters)
        word=random.choice(wordlist)
        print("Testing word:",word)
        print("You have "+ str(tries)+" tries left")
    
        letters = list(word)
    
        dashes = '-'*characters
        hword = list(dashes)
        print("The word you need to guess is ",dashes)
        while complete < characters and tries > 0:
            guess = input("Please input your letter: ")
            if not(guess.isalpha() or len(guess)==1):
              print('Error: invalid input.')
              continue
            if guess in word:
              if guess in guessed: 
                print("Already guessed that!")
                continue
              guessed += guess
              print("Guess correct!")
              #code to update dashes
              else:
              print('Incorrect guess.')
              errors += guess
            tries -= 1
            print("The letters you entered so far:", errors+guessed)
            print("You have "+ str(tries)+" tries left")
        if tries==0:
            print('lose')
        else:
         print('win')
        player = input("Would you like to play again? y/n: ")