为何二分法在Hangman游戏中对部分秘密单词失效?
问题分析与修复
核心问题是每次猜测单个字母前,没有重置low和high的初始值。猜完第一个字母"w"后,low和high被锁定在"w"对应的区间,猜下一个字母"i"时,这个区间根本不包含"i",导致二分查找无法收敛,直接陷入无限循环。
另外还有几个次要问题:
- 初始
high设置错误:len(alphabet)是26,设成len(alphabet)+2会得到28,但alphabet的最大索引是25,后续访问可能触发索引越界,这也是你处理不了字母'z'的原因之一。 - 外层
while循环完全冗余:已经用for循环遍历每个字母,外层while会导致重复遍历,逻辑上多余。 - 二分边界调整时没做偏移:当区间只剩两个元素时,不调整
low或high的偏移量,容易出现死循环。
修复后的代码
secret_word = 'wifey' num_guesses = 0 alphabet = "abcdefghijklmnopqrstuvwxyz" guessed_word = '' # 逐个猜测秘密单词里的每个字符 for target_char in secret_word: # 每次猜新字符前,重置二分查找的边界 low = 0 high = len(alphabet) - 1 # 字母表最大索引是25,对应'z' guess_index = (low + high) // 2 # 从中间位置开始猜 while alphabet[guess_index] != target_char: num_guesses += 1 if ord(alphabet[guess_index]) < ord(target_char): low = guess_index + 1 # 排除当前猜测的位置,避免死循环 else: high = guess_index - 1 guess_index = (low + high) // 2 guessed_word += alphabet[guess_index] # 如果你想把猜对的这次也算作一次猜测,就取消下面这行注释 # num_guesses += 1 print('num_guesses =', num_guesses) print(guessed_word)
修复要点说明
- 重置二分边界:每次处理新字符时,把
low和high重新设为0和字母表最大索引,保证每次查找都在完整字母表范围内进行。 - 修正
high初始值:设为len(alphabet)-1,避免索引越界,同时解决了字母'z'的处理问题。 - 边界偏移调整:修改
low和high时使用guess_index+1和guess_index-1,确保区间能持续缩小,避免卡在两个元素的情况。 - 移除冗余循环:删掉外层的
while,直接遍历秘密单词的每个字符,逻辑更清晰。
测试这段代码,不管是"wife"还是"wifey"都能正常猜出,不会陷入无限循环。
内容的提问来源于stack exchange,提问作者mgsberger
相关产品推荐
相关产品推荐

