3
\$\begingroup\$

I made a simple Hangman game in Python:

import random 

class Hangman:

    def __init__(self):
        self.words = ["bike", "monkey", "planet"]
        self.random_word = random.choice(self.words)
        self.lenght = len(self.random_word)
        self.no_of_try = int(self.lenght) + 3
        self.empty_word = ["_"] * self.lenght

    @staticmethod
    def user_input():
        print("Enter a guess: ")
        user_input = input()
        return user_input

    def find_index(self):
        letter = self.user_input()
        possition = self.random_word.index(letter)
        return (letter, possition)
    
    def substitue(self):
        try:
            guess_letter, guess_index = self.find_index()
            self.empty_word[guess_index] = guess_letter 
            print(self.empty_word)
            return True                     
        except ValueError as e:
            return False

    def play_game(self):
        while self.no_of_try > 0:
            print("no: " + str(self.no_of_try))
            game = self.substitue()
            if game:
                print("Bravo")
                self.no_of_try -=  1
            else:
                self.no_of_try -=  1
                print("Wrong")

            if "_" not in self.empty_word:
                print("You win")
                break
            if self.no_of_try == 0:
                print("Game over")
                break

if __name__ == "__main__":
    h = Hangman()
    h.play_game()
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Right now the program will have a problem if you use a word which has the same letter more than once. string.index will only return the index of the first occurrence. What you could do instead is use a set to check what letters still need to be guessed. If a character in the word is still in the set, it hasn’t been guessed and an underscore should be printed. If it isn’t in the set, it has been guessed and it should be printed.

The code can be simplified significantly. You only really need one function which takes a list of strings as an argument. You could do something like this:

import random

def hangman(word_list):
    word = random.choice(word_list)
    letters = set(word)
    guesses = len(word) + 3
    while len(letters) > 0 and guesses > 0:
        guess = input(str(guesses) + " guesses left\nguess something:\n")
        if guess in letters:
            print("correct")
            letters.remove(guess)
        else:
            print("wrong")
        guesses -= 1
        print(*(ch if ch not in letters else '_' for ch in word))
    print("win" if len(letters) == 0 else "lose")

if __name__ == "__main__":
    hangman(["bike", "monkey", "planet", "mississippi"])

NITPICKING

You have a function in your current code which could be replaced with a call to input. the user_input function could be replaced with this: input("Enter a guess:\n"). Also you can simplify this:

if game:
    print("Bravo")
    self.no_of_try -=  1
else:
    self.no_of_try -=  1
    print("Wrong")

into this:

self.no_of_try -=  1
print("Bravo" if game else "Wrong")

I also noticed a couple things in the __init__ method. The word list and the randomly chosen word’s length don’t need to be instance variables because they’re only used in __init__, and you don’t need to cast the length to int because it’s already an int.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thank you. This was really helpful, I will consider this practices in the future projects :) \$\endgroup\$ Commented Jan 15, 2021 at 9:33

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.