C#不重复随机数生成器运行后持续输出相同数字的问题
嘿,我帮你定位到程序的问题啦!你的C#随机数生成器之所以会出现持续输出相同内容、甚至卡住异常的情况,核心原因是**check变量没有在每次检查重复前重置状态**,另外我还做了一些实用的优化,来一步步拆解:
核心问题:残留的check状态导致死循环
你把check声明成了静态变量,当某次检测到重复数字后,它会被设为true,但后续生成新的不重复数字时,这个变量没有被重置回false——也就是说,哪怕下一个随机数是全新的,程序也会因为check还是true而拒绝把它加入列表。最后程序会一直卡在while(gen.Count < quantity)的死循环里,看起来就像是持续输出相同内容(其实是之前的输出一直停在控制台,程序根本没走到后续的输出步骤)。
修复后的完整代码
using System; using System.Collections.Generic; using System.Linq; namespace numgen { class Program { static int quantity, min, max, temp; static int control = 2; public static void Main(string[] args) { var gen = new List<int>(); Random rnd = new Random(); while (control > 0) { Console.Clear(); if (control == 2) { Console.Write("Add meg a minimum számot: "); min = int.Parse(Console.ReadLine()); Console.Write("Add meg a maximum számot: "); max = int.Parse(Console.ReadLine()); Console.Write("Add meg a hány számot kérsz: "); quantity = int.Parse(Console.ReadLine()); // 新增:防止用户要求的数量超过范围能提供的不重复数字总数 if (quantity > max - min) { Console.WriteLine($"Hiba: A kért számok száma nem lehet nagyobb, mint a tartomány mérete ({max - min})!"); Console.WriteLine("Nyomj meg egy billentyűt a folytatáshoz..."); Console.ReadKey(); continue; } } gen.Clear(); while (gen.Count < quantity) { // 把check改成局部变量,每次循环自动重置为false bool check = false; temp = rnd.Next(min, max); foreach (int num in gen) { if (temp == num) { check = true; break; } } if (!check) { gen.Add(temp); } } gen.Sort(); foreach (int num in gen) { Console.WriteLine(num); } Console.WriteLine("\n[2] Új adatok megadása"); Console.WriteLine("[1] Számok újragenerálása"); Console.WriteLine("[0] Kilépés"); // 新增:防止用户输入非数字导致程序崩溃 while (!int.TryParse(Console.ReadLine(), out control)) { Console.WriteLine("Kérlek érvényes számot adj meg (0,1,2)!"); } } } } }
关键修复&优化说明
- 重置
check状态:把check从静态变量改成每次检查重复时的局部变量,这样每次循环都会自动初始化为false,彻底解决了状态残留的问题。 - 输入合法性校验:
- 新增了数量范围校验:如果用户要求生成的数字数量超过了指定区间的不重复数字总数(比如min=1,max=5,最多只能生成4个不重复数),会提示错误并跳过本次生成,避免无限死循环。
- 用
int.TryParse替代int.Parse:防止用户输入非数字内容导致程序直接崩溃,体验更友好。
- 额外优化建议:如果你的生成数量接近区间总数,当前的重复检查方式效率会很低,推荐用洗牌算法来提升性能——先把区间内所有数字放进列表,打乱后取前N个:
这种方式完全避免了重复检查的循环,效率提升明显。// 替换原有的生成逻辑 gen = Enumerable.Range(min, max - min).ToList(); // Fisher-Yates洗牌算法 for (int i = gen.Count - 1; i > 0; i--) { int j = rnd.Next(i + 1); (gen[i], gen[j]) = (gen[j], gen[i]); } gen = gen.Take(quantity).ToList(); gen.Sort();
内容的提问来源于stack exchange,提问作者Kiss Gergő
相关产品推荐
相关产品推荐

