如何修复C#版Monty Python游戏:实现随机奖品门与非奖品门揭露
Monty Python 游戏代码修改建议
核心问题分析
- OutOf Bounds Exception根源:
Convert.ToInt32(new Random())是完全错误的用法,会将Random实例转换为一个超大整数(远大于门的编号范围1-3),后续逻辑判断时会引发错乱甚至索引越界。 - 奖品随机放置逻辑失效:手动固定了"Car"的位置,且
PrizeDoor的赋值完全无效,没有实现随机分配奖品的功能。 - 非奖品门揭露逻辑缺失:
RevealedDoor没有任何校验规则,无法保证它既不是用户选择的门,也不是奖品门,且门后无奖品。
具体修改建议
1. 正确生成随机数
- 只创建一个Random实例(多次创建会因系统时钟问题导致重复随机数),用
rng.Next(1, 4)生成1-3的整数(Next方法为左闭右开,上限设为4才能包含3)。 - 彻底移除
Convert.ToInt32(new Random())这种错误写法。
2. 实现奖品随机放置
- 初始化所有门为"Nothing",再随机选择一个门设置为"Car",同时记录该门的编号为
prizeDoor。
3. 实现合规的非奖品门揭露逻辑
- 揭露的门必须满足三个条件:不是用户选择的门、不是奖品门、门后为"Nothing"。
- 通过过滤门编号列表筛选符合条件的门,再随机选取一个。
4. 增加输入合法性校验
- 校验用户输入的门编号是否在1-3范围内,避免无效输入引发转换异常或逻辑错误。
修正后的完整代码
using System; using System.Collections.Generic; using System.Linq; class Guess { static void Main(string[] args) { // 初始化所有门为默认空奖 Dictionary<int, string> doors = new Dictionary<int, string> { {1, "Nothing"}, {2, "Nothing"}, {3, "Nothing"} }; Random rng = new Random(); // 随机分配奖品门 int prizeDoor = rng.Next(1, 4); doors[prizeDoor] = "Car"; // 获取用户初始选择,带输入校验 int selectedDoor; while (true) { Console.WriteLine("Which door do you want to select? (1/2/3)"); if (int.TryParse(Console.ReadLine(), out selectedDoor) && selectedDoor >= 1 && selectedDoor <= 3) { break; } Console.WriteLine("Invalid input! Please enter a number between 1 and 3."); } // 筛选并随机揭露合规的非奖品门 var availableRevealDoors = doors.Keys.Where(d => d != selectedDoor && d != prizeDoor).ToList(); int revealedDoor = availableRevealDoors[rng.Next(availableRevealDoors.Count)]; Console.WriteLine($"We reveal door {revealedDoor}, which has {doors[revealedDoor]}!"); // 询问是否更换选择 Console.WriteLine("Do you want to change your selection? (Yes/No)"); string selection = Console.ReadLine()?.Trim()?.ToLower(); if (selection == "yes") { // 获取用户新选择,带输入校验(不能选原门和已揭露的门) int newSelectedDoor; while (true) { Console.WriteLine($"Which door would you like to choose now? (Cannot choose {selectedDoor} or {revealedDoor})"); if (int.TryParse(Console.ReadLine(), out newSelectedDoor) && newSelectedDoor >= 1 && newSelectedDoor <= 3 && newSelectedDoor != selectedDoor && newSelectedDoor != revealedDoor) { break; } Console.WriteLine($"Invalid input! Please choose a door other than {selectedDoor} and {revealedDoor}."); } // 判断最终结果 Console.WriteLine(newSelectedDoor == prizeDoor ? "Congratulations! You won the game!" : "Sorry, you lost the game!"); } else { // 保持原选择,判断结果 Console.WriteLine(selectedDoor == prizeDoor ? "Congratulations! You won the game!" : "Sorry, you lost the game!"); } } }
额外说明
- 统一了变量命名规范(符合C#小驼峰命名习惯),提升代码可读性。
- 新增的输入校验逻辑避免了用户误输入导致的程序崩溃。
- 揭露门的逻辑严格遵循Monty Python游戏规则:主持人只会打开无奖品且非用户初始选择的门。
内容的提问来源于stack exchange,提问作者Nicholas Chang
相关产品推荐
相关产品推荐

