Python Hangman游戏:ask_for_name与menu关联play函数失败问题
Python Hangman游戏函数关联问题解决
问题描述
开发Python版Hangman游戏时,尝试将ask_for_name()和menu()函数与play()函数关联,但遇到以下问题:
- 游戏启动后直接进入
play()游戏流程,未执行用户名输入和菜单环节 - 游戏结束后选择“否”重启,回到用户名输入和菜单,但此时选择“P”启动游戏会触发错误
- 调整函数定义位置后,要么函数无法正常运行,要么不会被调用
问题代码
def ask_for_name(): while True: name = input(YELLOW_COLOR + "Please Enter Your Name:\n") if not name.isalpha(): print("Name must be letters only\n") else: print(f"Hello {name}, Welcome to Chris's Hangman and Good Luck!\n") menu() return name def menu(): """ menu function which gives the user two options - Press 1 to play or 2 for instructions - only accepts valid keys or error message comes up """ while True: user_input = input("Press P to Play game\nPress I for Instructions\n").upper() if user_input == "P": play() elif user_input == "I": print( "1.The computer will generate a random word and it's\n" "your task to guess the letters from the word.\n" "2.To guess, type a letter of your choice and hit enter.\n" "3.If you guess correctly, the letter will be revealed.\n" "4.If you guess incorrectly, you will lose a life and \n" " the Hangman will start to appear.\n" "5.You have 8 lives to guess the correct word.\n" "Good Luck!\n") enter_input = input("Press Enter to go back to the menu\n").upper() if enter_input == "": menu() else: print(RED_COLOR + "Oops look's like you pressed the wrong key!\n") else: print("Invalid Character, please try again!\n") word = "dog" #random.choice(WORDS) word = word.upper() reveal = list(len(word)*'_') lives = 8 game_is_won = False def check_letter(letter, word): global reveal for i in range(0,len(word)): letter = word[i] if guess == letter: reveal[i] = guess if '_' not in reveal: return True else: return False def restart_game(): """ Gives player option to restart, otherwise returns to menu """ game_restart = False while not game_restart: restart = input("Would you like to play again?" "Y/N").upper() try: if restart == "Y": game_restart = True play() elif restart == "N": game_restart = True print("\n") header() ask_for_name() menu() else: raise ValueError( "You must type in Y or N" ) except ValueError as e: print("\n You must type in Y or N Please try again.\n") def play(): os.system("clear") header() print(hangman[8-lives]) print(' '.join([str(e) for e in reveal])) print(f"You have {lives} lives") while game_is_won == False and lives > 0: play() guess = input('Guess a letter or an entire word:') guess = guess.upper() if guess == word: game_is_won = True reveal = word elif len(guess) == 1 and guess in word: game_is_won = check_letter(guess, word) else: lives -= 1 if game_is_won: player_won() print("WELL DONE") else: player_lost() print(f"YOU FAILED the word was: {word}") restart_game()
问题分析
- 全局变量未重置:
word、reveal、lives、game_is_won等状态变量定义为全局,第二次进入游戏时仍使用上一次的状态,导致逻辑混乱报错 - 函数缩进错误:
ask_for_name()中的while循环、check_letter()中的for循环、play()函数内代码均未正确缩进,导致函数逻辑无法正常执行 - 递归调用陷阱:
menu()中选择“返回菜单”时递归调用menu(),会导致函数调用栈不断累积,最终引发异常 - 执行流程错误:程序启动后直接执行了
play()外的while循环,跳过了ask_for_name()和menu()的初始化流程 - 函数逻辑错误:
check_letter()未使用传入的letter参数,反而依赖全局的guess变量,导致猜字母逻辑失效
解决方案
关键修改点
- 将游戏状态变量移至
play()函数内部,每次启动游戏时初始化新状态 - 修复所有函数的缩进错误,确保代码块逻辑正确
- 用循环替代递归调用,避免函数栈溢出
- 调整程序入口,从调用
ask_for_name()开始 - 修正
check_letter()的逻辑,使用传入的参数实现字母匹配 - 移除
play()外的冗余循环,将游戏主循环整合到play()函数内
修改后的完整代码
import os # 补充缺失的常量和辅助函数 YELLOW_COLOR = "\033[93m" RED_COLOR = "\033[91m" RESET_COLOR = "\033[0m" hangman = [ """ +---+ | | | === """, """ +---+ O | | | === """, """ +---+ O | | | | === """, """ +---+ O | /| | | === """, """ +---+ O | /|\\ | | === """, """ +---+ O | /|\\ | / | === """, """ +---+ O | /|\\ | / \\ | === """ ] def header(): print(RESET_COLOR + "=== HANGMAN GAME ===") def player_won(): print(RESET_COLOR + "🎉 YOU WON! 🎉") def player_lost(): print(RESET_COLOR + "💀 GAME OVER 💀") def ask_for_name(): while True: name = input(YELLOW_COLOR + "Please Enter Your Name:\n" + RESET_COLOR) if not name.isalpha(): print("Name must be letters only\n") else: print(f"Hello {name}, Welcome to Chris's Hangman and Good Luck!\n") return name def menu(): """菜单函数:提供开始游戏和查看说明选项""" while True: user_input = input("Press P to Play game\nPress I for Instructions\n").upper() if user_input == "P": play() elif user_input == "I": print( "1. 电脑会生成一个随机单词,你的任务是猜出单词中的字母\n" "2. 输入一个字母并回车进行猜测\n" "3. 猜对则字母会被显示出来\n" "4. 猜错会减少一条生命,同时绞刑架图案逐步显示\n" "5. 你有8条生命来猜出正确单词\n\n" "祝你好运!\n" ) input("按回车键返回菜单...") continue else: print("无效输入,请重新尝试!\n") def check_letter(guess_letter, word, reveal_list): """检查字母是否在单词中,更新显示列表,返回是否猜中所有字母""" found = False for i in range(len(word)): if word[i] == guess_letter: reveal_list[i] = guess_letter found = True return '_' not in reveal_list def restart_game(): """询问玩家是否重启游戏,返回菜单或重新开始""" while True: restart = input("Would you like to play again? Y/N\n").upper() if restart == "Y": play() break elif restart == "N": print("\n") header() ask_for_name() menu() break else: print("必须输入Y或N,请重新尝试!\n") def play(): # 每次游戏初始化全新状态 os.system("clear") header() word = "DOG" # 替换为random.choice(WORDS) reveal = list(len(word)*'_') lives = 8 game_is_won = False while not game_is_won and lives > 0: print(hangman[8 - lives]) print(' '.join(reveal)) print(f"你还有 {lives} 条生命\n") guess = input('猜一个字母或整个单词:').upper() if guess == word: game_is_won = True reveal = list(word) elif len(guess) == 1 and guess in word: game_is_won = check_letter(guess, word, reveal) else: lives -= 1 print(f"错误!剩余生命:{lives}") if game_is_won: player_won() print(f"正确单词是:{word}") else: player_lost() print(f"正确单词是:{word}") restart_game() # 程序入口 if __name__ == "__main__": header() ask_for_name() menu()
说明
- 补充了颜色控制、绞刑架图案、头部提示等缺失的辅助内容
- 所有游戏状态变量在
play()内初始化,确保每次游戏都是全新状态 - 菜单返回逻辑改为循环
continue,避免递归调用导致的栈溢出 check_letter()改为接收参数,不再依赖全局变量,逻辑更清晰- 程序通过
if __name__ == "__main__"启动,确保正确的初始化流程
内容的提问来源于stack exchange,提问作者chris-t93
相关产品推荐
相关产品推荐

