Mastermind类猜数字游戏代码问题:红/白校验逻辑异常问询
解决Mastermind猜数字游戏中Whitecheck统计错误的问题
嘿,我来帮你搞定这个恼人的统计bug!你遇到的问题本质是校验顺序搞反了——原代码先统计数字对但位置错的情况,之后才处理位置和数字都对的情况,导致已经匹配正确位置的数字被错误计入whitecheck。比如你说的例子:答案是1234,猜测是4234,原代码先检查位置1的4,发现它在答案里但位置不对,就先加了whitecheck,之后处理位置4的4时,虽然标记了checklist,但已经没法把之前加的whitecheck减回去了。
正确的校验逻辑应该这么走
要彻底解决这个问题,得把校验顺序反过来:
- 第一步:先统计所有redcheck(位置和数字都正确),同时把这些已经匹配的数字标记出来,避免后续重复统计。
- 第二步:再统计whitecheck(数字正确但位置错误),这时候要排除已经被redcheck匹配的数字,还要保证答案里的每个数字只能被匹配一次。
优化后的代码实现
你的修改思路是对的——分离red和white的校验顺序,但我们可以把代码写得更简洁通用,比如用列表标记已匹配的数字,避免一堆重复的if语句:
import random # 生成不重复的4位数字密码(范围1-4) code = [] while len(code) != 4: n = random.randint(1, 4) if n not in code: code.append(n) answer = ''.join(str(num) for num in code) attempts = 3 print(f"调试用:生成的密码是 {answer}") while attempts > 0: # 简化输入:让用户直接输入连续的4位数字 guess = input("请输入4个1-4的数字(直接连输,比如1234):").strip() # 输入合法性校验 if len(guess) != 4 or not guess.isdigit() or any(int(c) not in range(1, 5) for c in guess): print("喂,得输入合法的4位1-4数字哦!") continue redcheck = 0 whitecheck = 0 # 把答案和猜测转成列表,方便标记已匹配的数字 answer_copy = list(answer) guess_copy = list(guess) # 第一步:统计redcheck,标记已匹配的位置 for i in range(4): if guess_copy[i] == answer_copy[i]: redcheck += 1 # 用特殊字符标记,避免后续重复统计 answer_copy[i] = 'X' guess_copy[i] = 'X' # 第二步:统计whitecheck,跳过已标记的位置 for i in range(4): if guess_copy[i] != 'X' and guess_copy[i] in answer_copy: whitecheck += 1 # 找到答案中对应的数字并标记,防止重复匹配 match_idx = answer_copy.index(guess_copy[i]) answer_copy[match_idx] = 'X' guess_copy[i] = 'X' print(f"你输入的是:{guess}") if guess == answer: print(f"🎉 太棒了!你破解了密码!") print(f"正确位置且数字正确:{redcheck} 个") print(f"数字正确但位置错误:{whitecheck} 个") break else: attempts -= 1 print(f"❌ 不对哦,还有 {attempts} 次机会。") print(f"正确位置且数字正确:{redcheck} 个") print(f"数字正确但位置错误:{whitecheck} 个") if attempts == 0: print(f"😔 很遗憾,你输了,正确密码是:{answer}")
代码为啥这么写?
- 输入更友好:让用户直接输入连续数字,比逐个输入位置方便多了,还加了输入校验,防止乱输。
- 标记法避免重复统计:用
X标记已经匹配的数字,不管是red还是white,每个数字只会被统计一次,完美解决了你之前的bug。比如测试答案1234、猜测4234的情况:- 第一步统计redcheck:位置2、3、4的数字都匹配,redcheck=3,这三个位置被标记成
X。 - 第二步统计whitecheck:猜测的位置1是
4,但答案里的4已经被标记成X了,所以不会计入whitecheck,最终whitecheck=0,完全符合预期。
- 第一步统计redcheck:位置2、3、4的数字都匹配,redcheck=3,这三个位置被标记成
- 扩展性强:哪怕以后你想改成允许密码里有重复数字,这个逻辑也能直接用,不用大改。
对你修改方案的小补充
你之前分离red和white校验顺序的思路完全正确,但原修改代码里的checklist逻辑在处理重复数字时会有问题(不过你的游戏现在是生成不重复数字,所以暂时没暴露),而用标记列表的方法更通用,能覆盖所有情况。
内容的提问来源于stack exchange,提问作者Pythonnoob
相关产品推荐
相关产品推荐

