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!")
1 Answer 1
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
-
\$\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\$infinitezero– infinitezero2020年06月15日 03:16:40 +00:00Commented Jun 15, 2020 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– furas2020年06月15日 13:30:04 +00:00Commented Jun 15, 2020 at 13:30
version = version.lower()
and you don't have to repeatelower()
in allif/else
\$\endgroup\$HANGMANPICS
has elements with indexes from 0 to 6 but you use index 7 \$\endgroup\$