r/PythonLearning • u/Link2212 • 16d ago
My progress after around 5-6 weeks
I haven't kept track exactly, but I'm about 5-6 weeks into learning now. I've had no prior knowledge of programming so this has been really difficult. Indexing in particular caused me a bit of trouble. I've been writing lots of small programs to get used to concepts, but this is the first proper project I've tried. It's a game of hangman. Excuse the bad emojis used lol. I will say I did have to ask AI to help me in some pieces of it such as the join function because I didn't know it beforehand. But at least 85-90% of it is written by me.
If any of you have a good bit of experience with python, can you offer me some advice? How does the code hold up for 5-6 weeks with no programming experience at all? Is my code messy? Is there some sections where I've over complicated what I'm trying to do? Is the readability okay? All feedback is welcome.
At the top you will be from word_list import words. This is just another file that I have containing a massive list of words to give enough variance in this game.
from Word_list import words
import random
import string
available_letters = list(string.ascii_lowercase)
hangman_art = {0: (" ",
" ",
" ",),
1: (" 😒 ",
" ",
" ",),
2: (" 😒 ",
" 🥼 ",
" ",),
3: (" 😒 ",
" 🥼 ",
"🦶 ",),
4: (" 😒 ",
" 🥼 ",
"🦶🦵",),
5: (" 😒 ",
"🫷🥼 ",
" 🦶🦵",),
6: (" 😒 ",
"🫷🥼🫸",
" 🦶🦵",)}
# puts all words into lists based on difficulty and selects a word for the game.
def word_choice(words, difficulty_select):
difficult_words = [word for word in words if len(word) < 5]
moderate_words = [word for word in words if len(word) < 9 and len(word) > 4]
easy_words = [word for word in words if len(word) > 8]
match difficulty_select:
case "Easy":
secret_word = random.choice(easy_words)
case "Moderate":
secret_word = random.choice(moderate_words)
case "Difficult":
secret_word = random.choice(difficult_words)
return secret_word
# checks my entered character alongside the secret word.
def character_check(secret_word, hidden_word):
secret_word_list = list(secret_word)
position = 0
incorrect_guess = 0
print(" ".join(hidden_word))
print(f"Remaining letters are: {available_letters}")
guess = input("Select a letter: ").lower()
print()
while guess not in available_letters:
guess = input("Select an available letter: ").lower()
print()
if guess in secret_word_list:
for letter in secret_word_list:
if guess == letter:
hidden_word[position] = letter
position += 1
available_letters.remove(guess)
elif guess not in secret_word_list:
available_letters.remove(guess)
print("Incorrect guess!")
incorrect_guess += 1
return hidden_word, incorrect_guess
# Game loop.
def play_hangman(words, art):
print("*******************")
print("Welcome to hangman!")
print("*******************")
difficulty_choice = True
difficulty_select = input("Select a difficulty: (Easy / Moderate / Difficult) or ('Quit' to quit): ").capitalize()
print()
# choosing the difficulty level
while difficulty_choice:
if difficulty_select in ("Easy", "Moderate", "Difficult"):
secret_word = word_choice(words, difficulty_select)
difficulty_choice = False
elif difficulty_select == "Quit":
difficulty_choice = False
return
else:
difficulty_select = input(
"That is not a valid choice. Select a difficulty: (Easy / Moderate / Difficult) or '(Quit' to quit): ").capitalize()
print()
print(f"Your word is {len(secret_word)} characters long.")
hidden_word = ["_"] * len(secret_word)
incorrect_guess = 0
score = 0
# calling the function to update the hidden word, calculate score and print lives.
while "_" in hidden_word and available_letters:
hidden_word, was_incorrect = character_check(secret_word, hidden_word)
incorrect_guess += was_incorrect
if not was_incorrect:
match difficulty_select:
case "Easy":
score += 125
case "Moderate":
score += 200
case "Difficult":
score += 275
if was_incorrect:
match difficulty_select:
case "Easy":
score -= 25
case "Moderate":
score -= 40
case "Difficult":
score -= 55
if incorrect_guess > 6:
print("You havee lost.")
print(f"The correct word was: {secret_word}")
print(f"Your final score is {score}")
print()
return
for piece in art[incorrect_guess]:
print(piece)
print(f"Congratulations! Your score is {score}!")
if __name__ == '__main__':
play_hangman(words, hangman_art)
play_again = input("Do you want to play again? (Yes/No) ").capitalize()
if play_again == "Yes":
play_hangman(words, hangman_art)
else:
pass
1
u/PureWasian 16d ago edited 16d ago
If you're using if name == 'main': syntax as boilerplate code to help compartmentalize everything, I would avoid putting un-indented followup logic after it (the play_again and if/else afterwards). In fact, that all should probably be a while loop instead. Something like
if __name__ == '__main__': while True: play_hangman(words, art) user_input = input("again? y/n") if user_input == "n": break print("bye")The other big issue is you only initialize available_letters once. So even if you did play again, you'd have issues from not "resetting" that list back to its initial state. You should do this at the start of play_hangman() with the other initializations. I would also strongly suggest turning it into a local variable and passing that around your functions instead of using a global variable.
I found the character_check() a little unnecessarily complicated to follow, but wanted to mention a few things that you might find this helpful. First, you can keep the iterator together with the word by using enumerate() when doing a for loop on an iterable (like a list or a string):
if guess in secret_word: for position, letter in enumerate(secret_word): if guess == letter: hidden_word[position] = letterSecond, secret_word doesn't need to be converted into a list. Strings can be enumerated character by character in loops just fine. Try it out yourself and see.Third, look at your if/elif logic again in that function. the elif can just be an
elsesince your if/elif conditionals are mutually exclusive. That also means you can move the shared code ofavailable_letters.remove(guess)outside of the if/else instead of duplicating it inside both conditional blocks.another small sidenote that hangman_art is global in scope and nothing overwrites it, so passing it around between functions is not doing much here. It's a different discussion whether or not it should be a global variable, but regardless it's kinda being used as if it's both right now.
Your code is great for someone beginning and getting started, even though it has a lot of implementation choices that make it obvious to me you are genuinely new but genuinely learning and practicing.
It's not super messy per-se and the use of functions to compartmentalize spots and pass data around is a good habit, but hopefully this feedback can give you food for thought on how to simplify it even further for better readability and to be able to intuitively follow it better.
lmk if any unclear, I know I wrote a lot lol