【问题标题】:Filling a 2D array with randomised numbers用随机数填充二维数组
【发布时间】:2012-07-27 15:31:40
【问题描述】:

我已经开始了一个项目,试图创建一个 Ken Ken 拼图。如果您不确定 Ken Ken 是什么,它与数独类似,在行或列中不能有重复的整数值。

我正在尝试使用为每个新行创建的数组列表中的数字填充二维数组。我会检查从数组列表中获取的数字是否与它自己的行和列中的任何数字不匹配。

当我运行我的代码时,当我尝试从列表中删除整数值时出现“索引超出范围”异常。我不确定为什么会发生这种情况,因为我认为我得到了正确的元素。

这是我的代码:

int GRID_SIZE = 4; int[][] grid = new int[GRID_SIZE][GRID_SIZE]; List<Integer> nums = new ArrayList<Integer>();

private void populateGrid() {

    for (int row = 0; row < GRID_SIZE; row ++) {

        // Creates an array of values from 1 to grid size.
        for (int i = 1; i <= GRID_SIZE; i++) nums.add(i);

        for (int col = 0; col < GRID_SIZE; col++) {

            while (nums.size() > 0) {

                // Gets a random number from the Array List
                int ranNum = nums.get(numGen.nextInt(GRID_SIZE));

                // Checks to see if the number is placeable.
                if (canPlace(ranNum, row, col)) {

                    // Places the number in the 2D Array
                    grid[row][col] = ranNum;
                    break;

                } else {

                    // Removes duplicate element from the Array List.
                    nums.remove(ranNum); <------{Index Out Of Bounds Exception]
                }
            }
        }
    } 
}

private boolean canPlace(int ranNum, int row, int col) {

    for (int i = 0; i < GRID_SIZE; i++) {

        // Checks if the specified number is already in the row/column.
        if (grid[col][i] == ranNum) return false;
        if (grid[i][row] == ranNum) return false;
    }

    return true;
}

我对此有几个问题:

首先,为什么我会收到错误消息

其次还有什么比二维数组更适合用于网格和我放置数字的方式

最后,我是否正确使用了中断

提前感谢您的回答。

【问题讨论】:

  • 这在第二个 for 循环中似乎是错误的:i &lt;= GRID_SIZE
  • 您使用什么确切的数据类型来存储随机数列表?如果它是一个列表,它可能会随着你删除东西而缩小,所以如果你的列表有 9 个,并且你找到一个并删除它,它现在有 8 个。如果你再次尝试查看第 9 个位置,这是一个越界异常
  • 我真的不知道从哪里开始。即使小问题得到解决,你的整个方法似乎都是错误的,无法解决最困难的问题。你需要有回溯。
  • 是的,nums 声明的尺寸是否与 grid 相同?另外,请指出您获得IndexOutOfBoundsException 的行。
  • @Keppil 谢谢你,我想我也是从 0 而不是 1 开始的。我现在已经改变了。

标签: java arrays random sudoku latin-square


【解决方案1】:

IndexOutOFBoundsException 发生是因为 List API 中的故障 (IMO)。它有一个remove(Object element) 方法,这是您要调用的方法,还有一个remove(int index) 方法,这是您实际调用的方法。后者尝试删除给定索引处的元素,因为您的参数可能大于列表大小,所以该索引不存在。 您可以将 ranNum 变量转换为 IntegerObject 以确保调用正确的方法。

【讨论】:

  • 非常感谢您的回答,我一直认为 int 和 Integer 是一样的,这对我来说是一个很好的教训。我现在已经修复了我的代码,它现在可以正常工作了,再次感谢!
【解决方案2】:
for (int i = 0; i <= GRID_SIZE; i++) nums.add(i);

这对我来说没有多大意义。您正在添加 0-4 的数字。您的数组中最多只有 3 个索引。 0-1-2-3...

实际上没有看到更多代码,或者没有确切地知道索引超出范围的位置......这是在黑暗中拍摄。

【讨论】:

  • 感谢您的回复,我现在已经更正了,我得到了我想要的数字。
  • @Jordan King 如果答案是正确的,你应该接受它作为正确的答案,这样人们就会知道哪里出了问题。很高兴它有帮助。
【解决方案3】:

再次仔细查看我的代码后,我意识到我的主要错误与canPlace(int ranNum, int row, int col) 方法有关。

我所做的只是交换colrow 的值,它就奏效了。

感谢大家的帮助。

【讨论】:

    【解决方案4】:

    用不同的方法解决这个问题怎么样?从一个有效的正方形开始并对其进行变换。 “交换两行”和“交换两列”这两个操作保留了正方形的属性。这允许您进行两次Fisher-Yates 洗牌,一次在行上,一次在列上,只要您从一个有效的正方形开始,这将为您提供一个有效的随机正方形。构造一个初始的有效正方形很简单:

    123456
    234561
    345612
    456123
    561234
    612345
    

    【讨论】:

    • 非常感谢,我尝试了这个想法,并且成功了(以及许多其他益智游戏)。谢谢!
    猜你喜欢
    • 2014-05-10
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    相关资源
    最近更新 更多