7
\$\begingroup\$

guys I'm new to python and I decided to learn it via doing some project myself so I started working on Hangman game is there somebody willing to chceck my code for some common mistakes and what could be better done than it is, btw the works fine.

import random


def rand_word(version):
    if version.lower() == "slovak":
        words = open("Slova", "r")
        all_lines = words.readlines()
        line_num = random.randint(0, len(all_lines))
        words.close()
        return all_lines[line_num]
    elif version.lower() == "english":
        words = open("Words", "r")
        all_lines = words.readlines()
        line_num = random.randint(0, len(all_lines))
        words.close()
        return all_lines[line_num]
    else:
        print("Wrong input! [FATAL ERROR]")
        input("Press enter to EXIT!")
        exit()


def draw(what_to_do):

    HANGMANPICS = ['''
      +---+
      |   |
          |
          |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
          |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
      |   |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|   |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
     /    |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
     / \  |
          |
    =========''']

    if what_to_do == 1:
        print(HANGMANPICS[what_to_do])
    elif what_to_do == 2:
        print(HANGMANPICS[what_to_do])
    elif what_to_do == 3:
        print(HANGMANPICS[what_to_do])
    elif what_to_do == 4:
        print(HANGMANPICS[what_to_do])
    elif what_to_do == 5:
        print(HANGMANPICS[what_to_do])
    elif what_to_do == 6:
        print(HANGMANPICS[what_to_do])
    elif what_to_do == 7:
        print(HANGMANPICS[what_to_do])
    else:
        print(HANGMANPICS[0])


def list_fill(size):
    i = 0
    size -= 1
    while i < size:
        positions.append("_")
        i += 1


print("HANGMAN")
print("You have 6 tries to guess the correct word!")
dictionary = input("Chose dictionary Slovak or English: ")
positions = []
tries = 0
win_con = 1
addition = False
temp_word = rand_word(dictionary)
#print(temp_word)
list_fill(len(temp_word))


while tries < 6:

    counter = 0
    draw(tries)
    print(*positions)
    user_letter = input("Enter a letter: ")

    for letter in temp_word:

        if letter == user_letter:
            positions[counter] = letter
            win_con += 1
            tries -= 1
        else:
            addition = True

        counter += 1

    if addition:
        tries += 1

    if win_con == len(temp_word):
        print("You have won!")
        print(*positions)
        input("Press enter to EXIT!")
        exit()

print("You have run out of tries! ")
print(f"The word was {temp_word.upper()}")
input("Press enter to EXIT!")

\$\endgroup\$
2
  • \$\begingroup\$ version = version.lower() and you don't have to repeate lower() in all if/else \$\endgroup\$
    – furas
    Jun 14 '20 at 15:46
  • \$\begingroup\$ BTW: HANGMANPICS has elements with indexes from 0 to 6 but you use index 7 \$\endgroup\$
    – furas
    Jun 14 '20 at 16:46
4
\$\begingroup\$

Below my version with changes - I didn't run it to test.

I describe it after code.

import random

# --- constants ---

HANGMANPICS = ['''
      +---+
      |   |
          |
          |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
          |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
      |   |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|   |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
          |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
     /    |
          |
    =========''', '''
      +---+
      |   |
      O   |
     /|\  |
     / \  |
          |
    ========='''
]

# --- functions ---

def rand_word(version):
    
    version = version.lower()
    
    if version == "slovak":
        filename = "Slova"
    elif version == "english":
        filename = "Words"
    else:
        print("Wrong input! [FATAL ERROR]")
        input("Press enter to EXIT!")
        exit()

    words = open(filename) 
    #all_lines = words.readlines()  # it keeps `\n` in lines
    #all_lines = words.read().split('\n')  # it removes `\n`  in lines
    all_lines = words.read().splitlines()  # it removes `\n`  in lines
    words.close()
    
    print(all_lines)

    #line_num = random.randint(0, len(all_lines))
    #return all_lines[line_num]

    word = random.choice(all_lines)
    return word    

def draw(what_to_do):

    if 1 <= what_to_do <= 7:
        print(HANGMANPICS[what_to_do])
    else:
        print(HANGMANPICS[0])
   
    # or

    #if what_to_do < 1 or what_to_do > 7:
    #    what_to_do = 0
    #print(HANGMANPICS[what_to_do])

def list_fill(size):
    return ["_"] * size
    #return ["_"] * size-1 # if you didn't remove `\n` from lines

# --- main ---
print("HANGMAN")
print("You have 6 tries to guess the correct word!")

dictionary = input("Chose dictionary Slovak or English: ")

tries = 0
win_con = 0

temp_word = rand_word(dictionary)
positions = list_fill(len(temp_word))

while tries < 6:

    counter = 0
    
    draw(tries)
    #print(*positions)
    print(' '.join(positions))  # the same result
    
    user_letter = input("Enter a letter: ")

    addition = False
    
    for letter in temp_word:

        if letter == user_letter:
            positions[counter] = letter
            win_con += 1
            tries -= 1
        else:
            addition = True

        counter += 1

    if addition:
        tries += 1

    if win_con == len(temp_word):
        print("You have won!")
        print(*positions)
        input("Press enter to EXIT!")
        exit()

print("You have run out of tries! ")
print(f"The word was {temp_word.upper()}")
input("Press enter to EXIT!")

rand_word()

You could convert to lower only once

version = version.lower()

Inside if/else you use the same code so you could use it after if/else

if version == "slovak":
    filename = "Slova"
elif version == "english":
    filename = "Words"
else:
    print("Wrong input! [FATAL ERROR]")
    input("Press enter to EXIT!")
    exit()

words = open(filename) 
all_lines = words.readlines()  # it keeps `\n` in lines
words.close()

line_num = random.randint(0, len(all_lines))
return all_lines[line_num]

But readlines() gives lines with \n (and probabably later you have to use size-1 and win_con = 1) but you can read it in different way to remove the \n

all_lines = words.read().split('\n')  # it removes `\n`  in lines

or

all_lines = words.read().splitlines()  # it removes `\n`  in lines

Eventually use list compression to remove \n from elements on list

all_lines = [line.strip() for line in all_lines]

Usingstrip() or rstrip() it removes also spaces/tabs if they are in file.

random has many useful functions and you can get random word without using index

word = random.choice(all_lines)

return word 

BTW: There can be one problem - if would run hangmap for many words then choice() (or randint()) may select the same word again. You would have to remeber which word was already used and repeat selection - or you should shuffle list random.shuffle(all_lines) and later you can run code with for word in all_lines and it will use different words in random order.


draw()

HANGMANPICS never changes so it is good that you use UPPER_CASE_NAME. But you could put it outside function. Inside function it will create it again and again when you run draw() (but it has always the same values so there is no need to create again and again)

EDIT: HANGMANPICS has elements with indexes from 0 to 6 but you use 7

You can use <= instead of == to make it simpler

if 1 <= what_to_do <= 6:  # EDIT: it has to be 6 instead of 7
    print(HANGMANPICS[what_to_do])
else:
    print(HANGMANPICS[0])

or use "reversed" comparitions

if what_to_do < 1 or what_to_do > 6:  # EDIT: it has to be 6 instead of 7
    what_to_do = 0

print(HANGMANPICS[what_to_do])

list_fill()

You can use * to repeat strings on list.

def list_fill(size):
    return ["_"] * size-1

And use return to assign to position

positions = list_fill(len(temp_word))

This way you can run it in a loop which repeats the game with next word


other code

I'm not sure but addition = False probably should be inside while-loop before every for-loop which change addition = True


BTW: open() as default use "r" so you don't have to use it.


EDIT: I don't know if I understand addition. You add only 1 to tries when you don't guess letter but you also subract from tries many times - ie. if you guess a in word ABBA then it substracts 2 because a is two times in this word. The same for char b - it substracts 2. This way you can get tries smaller then 0

I would use to add 1 only when not found letter - and keep current value when found letter (and it doesn't matter how many times it exists in word).

    found = False
    
    for index, letter in enumerate(word):
        if letter == user_letter:
            positions[index] = letter
            win_con += 1
            found = True

    if not found:
        tries += 1
\$\endgroup\$
2
  • \$\begingroup\$ I never like the "wrong input => abandon ship" approach. Just give the user a chance to correct himself without needing to restart the program. \$\endgroup\$ Jun 15 '20 at 3:16
  • \$\begingroup\$ @infinitezero you can describe it with code as answer and it will be useful for OP and other users. \$\endgroup\$
    – furas
    Jun 15 '20 at 13:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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