MIT 6.0001 PS3拼字游戏函数异常:字母不足却返回True
问题根源:字母计数逻辑错误 + 布尔值覆盖问题
你遇到的问题核心在于两段代码里判断单词能否由手牌组成的逻辑完全错误,游戏内和测试模块的结果差异只是巧合(比如游戏内遍历到最后一个字母时刚好触发True,而测试模块的遍历中途出现了False并覆盖了最终值)。
我们来拆解具体的错误点:
1. 错误的手牌处理:直接pop()删除键,而非减少计数
你的代码里用h_holder.pop(let)处理手牌字母,但pop()会直接把整个字母键从字典中移除,完全忽略该字母原本的计数。比如手牌里有'a':3,单词需要两个'a':
- 第一次遇到
'a'时,pop('a')会直接删掉'a'这个键 - 第二次遇到
'a'时,let in h_holder返回False,此时can_make被设为False
但正确的逻辑应该是减少对应字母的计数,只有当计数减到0时再考虑删除键(或者保留计数为0,判断时检查计数是否大于0)。
2. 布尔值can_make被错误覆盖
你的代码每次循环都会重新赋值can_make,这意味着只有最后一个字母的检查结果会决定最终的can_make值:
- 如果单词最后一个字母存在于手牌中,哪怕前面有字母缺失,
can_make也会被设为True(这就是游戏内返回错误True的原因) - 如果最后一个字母不存在,哪怕前面所有字母都符合要求,
can_make也会被设为False(测试模块的情况)
修复后的代码逻辑
我们需要重构手牌检查的逻辑:
- 遍历单词的每个字母,先检查手牌中该字母的计数是否大于0
- 如果符合条件,就减少该字母的计数;如果不符合,直接判定无法组成单词并终止检查
- 只要有一个字母不满足,立即返回
False;只有所有字母都满足,才返回True
修正后的测试模块代码示例
word = "Rapture" hand = {'r': 1, 'a': 3, 'p': 2, 't': 1, 'u': 2} word_list = ["hot", "day", "face", "holl", "rapture", "honey"] l_word = word.lower() h_holder = hand.copy() in_list = l_word in word_list can_make = True # 默认设为True,只要有一个字母不满足就改成False for let in l_word: # 检查手牌中是否有该字母且计数>0 if h_holder.get(let, 0) > 0: h_holder[let] -= 1 # 计数减到0时可删除键(可选,不影响判断逻辑) if h_holder[let] == 0: del h_holder[let] else: can_make = False break # 只要有一个字母不满足,直接终止循环 if in_list and can_make: print("True") else: print("False") print("Can make is", can_make) print("In list is", in_list)
游戏内代码的修正版本
同样替换检查逻辑:
# 先判断单词是否在列表中 in_list = l_word in word_list if not in_list: return False h_holder = hand.copy() can_make = True for let in l_word: if h_holder.get(let, 0) > 0: h_holder[let] -= 1 if h_holder[let] == 0: del h_holder[let] else: can_make = False break return can_make
修改后,两段代码都会正确判断:比如Rapture(小写为rapture,需要2个r),你的游戏内手牌只有1个r,所以正确结果应该是False——之前游戏内返回True完全是错误逻辑导致的巧合。
内容的提问来源于stack exchange,提问作者Riley F.
相关产品推荐
相关产品推荐

