Java生成无重复随机整数数组 解决Swing猜格子游戏重复值问题
如何生成不含重复值的随机整数数组?
问题根因
你目前的代码有三个核心问题,导致去重失效、游戏逻辑异常:
Collections.shuffle()调用完全无效:correct_squares是基本类型int[]数组,Arrays.asList(correct_squares)不会把每个int值拆成列表元素,只会生成一个长度为1、唯一元素就是整个int数组的List,打乱单元素列表不会改变任何内容。- 逻辑顺序完全错误:shuffle的作用仅为打乱已有元素的排列顺序,不具备去重能力。你先生成了一组可能重复的随机数,再执行打乱操作,重复值会一直保留。
- 重置逻辑存在索引越界bug:重置按钮中写的
random_int.nextInt(26)会生成025范围的数值,而5x5网格的合法索引只有024,会出现不存在的正确格子,导致游戏永远无法通关。
正确实现方案
你需要从25个格子里选10个不重复的正确位置,Fisher-Yates洗牌是最适合这个场景的方案,正确用法不是打乱你生成的随机数,而是按以下步骤操作:
- 先生成0~24所有网格索引的集合,这个集合里天然没有重复值
- 调用
Collections.shuffle()打乱整个集合的顺序(JDK内部的shuffle本身就是基于Fisher-Yates算法实现的) - 取打乱后集合的前10个元素存入
correct_squares数组,得到的结果天然无重复、无越界
你可以把生成正确格子的逻辑抽成独立方法,避免构造函数和重置逻辑写重复代码:
// 类中新增该方法,专门生成无重复的正确格子索引 private void generateCorrectSquares() { // 生成所有合法的格子索引,初始状态无重复 ArrayList<Integer> allGridIndexes = new ArrayList<>(); for (int i = 0; i < 25; i++) { allGridIndexes.add(i); } // 打乱所有索引的顺序 Collections.shuffle(allGridIndexes); // 取前10个作为正确格子 for (int i = 0; i < correct_squares.length; i++) { correct_squares[i] = allGridIndexes.get(i); } System.out.println(Arrays.toString(correct_squares)); }
之后把构造函数里原来的for循环生成随机数+shuffle的代码全部删掉,替换成generateCorrectSquares();;重置按钮逻辑里原来的for循环生成随机数+shuffle的代码也删掉,替换成同样的方法调用即可,同时修复了之前的索引越界问题。
原理说明
Fisher-Yates洗牌算法的逻辑是从后往前遍历集合,每次将当前位置的元素和集合前方随机位置的元素交换,最终得到所有排列概率均等的无偏打乱结果。因为初始集合中每个索引仅出现一次,打乱后取任意长度的连续子序列都不会出现重复值,时间复杂度为O(n),效率远高于“生成随机数后查重、重复则重生成”的方案。
内容的提问来源于stack exchange,提问作者AskingLotsOfQuestions
相关产品推荐
相关产品推荐

