Xamarin C#应用生成双份符号列表时偶发数组越界异常求助
解决System.IndexOutOfRangeException的问题
嘿,我一眼就瞅出你代码里的问题所在了!咱们一步步拆解来看:
首先看你报错的那行代码:
letras[i] = Convert.ToString(simbolo)[alea.Next(0, simbolo.Length)];
这里犯了一个很典型的错误:Convert.ToString(simbolo)并没有帮你取出数组里的单个符号,而是把整个simbolo数组对象转换成了字符串,结果会是类似"System.String[]"这样的内容。当你用alea.Next(0, simbolo.Length)生成0到15之间的随机数时,这个字符串的长度远小于16(比如"System.String[]"只有14个字符左右),一旦随机数超过这个字符串的最大索引,就会直接抛出IndexOutOfRangeException——这就是为啥你的代码有时正常有时报错,完全看随机数有没有踩中超出范围的情况。
正确的写法&优化方案
你的需求是生成每个符号恰好出现两次的随机列表,原来的随机选取逻辑其实也有问题(可能导致某个符号出现次数不是2次),正确的做法应该是先对simbolo数组进行洗牌,这样既能保证每个符号的出现次数,又能实现随机顺序。
修正后的代码示例:
// 注意:Random实例最好只初始化一次,避免重复创建导致随机数序列重复 Random alea = new Random(); static int[] letras = new int[16]; string[] simbolo = new string[]{"A","B","A","B","C","D","C","D","E","F","E","F","G","H","G","H"}; // 用Fisher-Yates洗牌算法打乱数组顺序,保证每个元素出现两次且随机 for (int i = simbolo.Length - 1; i > 0; i--) { int j = alea.Next(0, i + 1); // 交换数组元素 string temp = simbolo[i]; simbolo[i] = simbolo[j]; simbolo[j] = temp; } // 将洗牌后的符号转换为int值(这里假设你要取字母的ASCII码,若有自定义映射可替换) for (int i = 0; i < letras.Length; i++) { letras[i] = (int)simbolo[i][0]; // 如果是自定义数字映射(比如A=1、B=2),可以用switch或字典实现: // letras[i] = simbolo[i] switch { "A" => 1, "B" => 2, ... }; }
关键修正点说明
- 去掉了错误的
Convert.ToString(simbolo),直接通过数组索引simbolo[j]获取目标元素,彻底避免字符串索引越界 - 采用Fisher-Yates洗牌算法,完美匹配你“每个符号出现两次”的需求,同时保证顺序随机
- 优化了随机数生成逻辑,洗牌时的随机范围始终在数组有效索引内,不会出现越界问题
内容的提问来源于stack exchange,提问作者Janel Garces
相关产品推荐
相关产品推荐

