Terminé mi aplicación Python Hangman con un código muy básico.
import random import sys # lets set some variables wordList = [ "lion", "umbrella", "window", "computer", "glass", "juice", "chair", "desktop", "laptop", "dog", "cat", "lemon", "cabel", "mirror", "hat" ] guess_word = [] secretWord = random.choice(wordList) # lets randomize single word from the list length_word = len(secretWord) alphabet = "abcdefghijklmnopqrstuvwxyz" letter_storage = [] def beginning(): print("Hello Mate!\n") while True: name = input("Please enter Your name\n").strip() if name == "": print("You can"t do that! No blank lines") else: break beginning() def newFunc(): print("Well, that"s perfect moment to play some Hangman!\n") while True: gameChoice = input("Would You?\n").upper() if gameChoice == "YES" or gameChoice == "Y": break elif gameChoice == "NO" or gameChoice == "N": sys.exit("That"s a shame! Have a nice day") else: print("Please Answer only Yes or No") continue newFunc() def change(): for character in secretWord: # printing blanks for each letter in secret word guess_word.append("-") print("Ok, so the word You need to guess has", length_word, "characters") print("Be aware that You can enter only 1 letter from a-z\n\n") print(guess_word) def guessing(): guess_taken = 1 while guess_taken < 10: guess = input("Pick a letter\n").lower() if not guess in alphabet: #checking input print("Enter a letter from a-z alphabet") elif guess in letter_storage: #checking if letter has been already used print("You have already guessed that letter!") else: letter_storage.append(guess) if guess in secretWord: print("You guessed correctly!") for x in range(0, length_word): #This Part I just don"t get it if secretWord[x] == guess: guess_word[x] = guess print(guess_word) if not "-" in guess_word: print("You won!") break else: print("The letter is not in the word. Try Again!") guess_taken += 1 if guess_taken == 10: print(" Sorry Mate, You lost :<! The secret word was", secretWord) change() guessing() print("Game Over!")
Entonces, tengo un par de preguntas sobre mi código:
-
Empecé a aprender algunas cosas sobre las clases en Python y pensé «Oye, escribamos este ahorcado con clases ) «Pero después de un poco de codificación me di cuenta de que acababa de crear clases con 1 función y en lugar de
func()
las llaméclass.func()
y eso» es todo. ¿Hay alguna buena razón por la que y cómo debería usar las clases en un juego de Hangman? -
Sé que el código es muy básico y, a mi nivel, no debería importarme exactamente la eficacia de el código, pero aún así: ¿Qué parte debería mejorarse (no el código en sí, sino mi lógica allí)? Quiero escribir de una manera «adecuada» pero mi código todavía se ve súper básico.
Respuesta
Jugabilidad
Ejecuté tu juego para probarlo primero y noté algo extraño cuando una letra es encontrado dos veces en la misma palabra, como » vidrio » aquí:
Pick a letter A You guessed correctly! ["-", "-", "a", "-", "-"] Pick a letter s You guessed correctly! ["-", "-", "a", "s", "-"] ["-", "-", "a", "s", "s"]
No estoy seguro de que sea por diseño, pero como jugador me parece extraño que «se muestra dos veces. Encontré dónde se originó en el código:
for x in range(0, length_word): #This Part I just don"t get it if secretWord[x] == guess: guess_word[x] = guess print(guess_word)
Si simplemente anula la sangría print(guess_word)
por dos niveles, evitará ese comportamiento ya que no se ejecutará en un bucle:
for i in range(0, length_word): if secretWord[i] == guess: guess_word[i] = guess print(guess_word)
Imprimir una matriz sin formato como ["-", "-", "a", "s", "s"]
es un poco confuso, al principio no sabía qué era hasta que acerté uno y vi los resultados. Así que hagamos que imprima algo más amigable:
print("Word to guess: {0}".format(" ".join(guess_word)))
Pick a letter o You guessed correctly! Word to guess: - o -
¡Mucho mejor! Pero se volverá un poco complicado escribir todo eso cada vez, así que hagamos una función de utilidad para ello y podemos usarlo para print(guess_word)
al comienzo de un juego también.
def print_word_to_guess(letters): """Utility function to print the current word to guess""" print("Word to guess: {0}".format(" ".join(guess_word)))
Entonces simplemente print_word_to_guess(guess_word)
siempre que lo necesitemos. También sería posible crear un mensaje diferente opcional pero por defecto a Word to guess:
, pero lo dejo como un desafío.
El juego tampoco me dice nada acerca de cuántas oportunidades me quedan, así que me quedo adivinando (literalmente) hasta que lo descubra. Es muy fácil hacer una pequeña función de utilidad:
def print_guesses_taken(current, total): """Prints how many chances the player has used""" print("You are on guess {0}/{1}.".format(current, total))
Luego, algunas adiciones de código:
def guessing(): guess_taken = 1 MAX_GUESS = 10 print_guesses_taken(guess_taken, MAX_GUESS) while guess_taken < MAX_GUESS:
Y:
for i in range(0, length_word): if secretWord[i] == guess: guess_word[i] = guess print_word_to_guess(guess_word) print_guesses_taken(guess_taken, MAX_GUESS)
Su lista de palabras es bastante limitada, para el futuro considere quizás buscar un archivo de texto en línea con un montón de palabras y simplemente lea uno al azar, eso ¡Traería más variedad!
Mejoras en el código
main
función
Ejecutas todo tu juego funciones tan pronto como las haga. Tendría más sentido ponerlos dentro de la función __main__
:
if __name__ == "__main__": beginning() newFunc() change() guessing()
Por cierto, newFunc()
no funciona bien como nombre, ya que no dice nada sobre lo que hace. Algo como ask_user_to_play()
sería mucho mejor.
Nomenclatura de constantes
Python no tiene constantes reales, pero sin embargo, es una buena práctica nombrar variables que no deberían cambiar (por cambio quiero decir reasignados a valores diferentes) en ALL_CAPS_WITH_UNDERSCORES. Un simple hallazgo & reemplazar en un IDE o editor de texto hace el truco para arreglar todo el script.
GUESS_WORD = [] SECRET_WORD = random.choice(wordList) # lets randomize single word from the list LENGTH_WORD = len(SECRET_WORD) ALPHABET = "abcdefghijklmnopqrstuvwxyz" letter_storage = []
Docstring
Es un buen hábito agregar una docstring a todas las funciones, clases y módulos, para describir otras programadores para qué es el código en cuestión. He hecho eso para la función de utilidad anterior 2.
Sugerencias de tipo
Desde Python 3, ahora puede usar escriba sugerencias para las firmas de sus funciones y métodos, y use herramientas de análisis de código estático. Esto también hace que el código sea más fácil de leer para los humanos.
Código mejorado
Esto es lo que se me ocurrió, aplicando todo lo anterior y mejorando el espaciado ( el suyo tenía demasiadas líneas en blanco en todas partes). Es probable que haya otras cosas que podrían mejorarse, pero este debería ser un buen comienzo.
import random, sys from typing import List # TODO try to load these from a text file WORD_LIST = [ "lion", "umbrella", "window", "computer", "glass", "juice", "chair", "desktop", "laptop", "dog", "cat", "lemon", "cabel", "mirror", "hat" ] GUESS_WORD = [] SECRET_WORD = random.choice(WORD_LIST) # lets randomize single word from the list LENGTH_WORD = len(SECRET_WORD) ALPHABET = "abcdefghijklmnopqrstuvwxyz" letter_storage = [] # Utility functions def print_word_to_guess(letters: List) -> None: """Utility function to print the current word to guess""" print("Word to guess: {0}".format(" ".join(letters))) def print_guesses_taken(current: int, total: int) -> None: """Prints how many chances the player has used""" print("You are on guess {0}/{1}.".format(current, total)) # Game functions def beginning() -> None: """Starts the game""" print("Hello Mate!\n") while True: name = input("Please enter Your name\n").strip() if name == "": print("You can"t do that! No blank lines") else: break def ask_user_to_play() -> None: """Ask user if they want to play""" print("Well, that"s perfect moment to play some Hangman!\n") while True: gameChoice = input("Would You?\n").upper() if gameChoice == "YES" or gameChoice == "Y": break elif gameChoice == "NO" or gameChoice == "N": sys.exit("That"s a shame! Have a nice day") else: print("Please Answer only Yes or No") continue def prepare_secret_word() -> None: """Prepare secret word and inform user of it""" for character in SECRET_WORD: # printing blanks for each letter in secret word GUESS_WORD.append("-") print("Ok, so the word You need to guess has", LENGTH_WORD, "characters") print("Be aware that You can enter only 1 letter from a-z\n\n") print_word_to_guess(GUESS_WORD) def guessing() -> None: """ Main game loop to have user guess letters and inform them of the results """ guess_taken = 1 MAX_GUESS = 10 print_guesses_taken(guess_taken, MAX_GUESS) while guess_taken < MAX_GUESS: guess = input("Pick a letter\n").lower() if not guess in ALPHABET: #checking input print("Enter a letter from a-z ALPHABET") elif guess in letter_storage: #checking if letter has been already used print("You have already guessed that letter!") else: letter_storage.append(guess) if guess in SECRET_WORD: print("You guessed correctly!") for i in range(0, LENGTH_WORD): if SECRET_WORD[i] == guess: GUESS_WORD[i] = guess print_word_to_guess(GUESS_WORD) print_guesses_taken(guess_taken, MAX_GUESS) if not "-" in GUESS_WORD: print("You won!") print("Game Over!") break else: print("The letter is not in the word. Try Again!") guess_taken += 1 print_guesses_taken(guess_taken, MAX_GUESS) if guess_taken == 10: print(" Sorry Mate, You lost :<! The secret word was {0}".format(SECRET_WORD)) if __name__ == "__main__": beginning() ask_user_to_play() prepare_secret_word() guessing()
Comentarios
- No puedo ‘ decir cuánto aprecio tu respuesta. Revisaré todos tus consejos y me desafiaré a mí mismo con ellos, gracias de nuevo 🙂
- No hay problema, ¡también me divertí revisándolo! Espero que publiques más en el futuro =)