Filling a 2D array with randomised numbers

1.2k views Asked by At

I have started a project trying to create a Ken Ken puzzle. If you are not sure what Ken Ken is, it is similar to Sudoku in the way that there can be no duplicated integer values in a row or column.

I am trying to fill a 2D Array with numbers from an Array List that is created for every new row. I make checks to see whether or not the number taken from the Array List does not match any numbers within its own row and column.

When I run my code I get an "Index Out Of Bounds" exception when I try removing the integer value from the list. I'm not sure why this is happening because I think I am getting the right element.

Here is my code:

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;
}

I have a few questions about this:

First of all, why am I getting the error that I am?

Secondly is there anything better to use than a 2D Array for the grid and the way I place my numbers?

Lastly, am I using the break correctly?

Thanks in advance for your answers.

4

There are 4 answers

1
rossum On BEST ANSWER

How about a different approach to the problem? Start with a valid square and transform it. The two operations, 'exchange two rows' and 'exchange two columns' preserve the properties of the square. This allows you to do two Fisher-Yates shuffles, one on the rows and one on the columns which would give you a valid randomised square as long as you start from a valid square. Constructing an initial valid square is trivial:

123456
234561
345612
456123
561234
612345
0
Jordan King On

After giving my code a good look over again I realised that my main error was to do with the canPlace(int ranNum, int row, int col) method.

All I did was swap the col and row values and it worked.

Thank you all for your help.

1
Jorn On

The IndexOutOFBoundsException happens because of a failure (IMO) in the List API. It has a remove(Object element) method, which is what you want to call, and a remove(int index) method, which is what you are actually calling. The latter tries to remove the element at the given index, which isn't there as your argument is probably greater than the list size. You can cast your ranNum variable to either Integer or Object to make sure you call the correct method.

2
While-E On
for (int i = 0; i <= GRID_SIZE; i++) nums.add(i);

This doesn't make much sense to me. You're adding numbers from 0-4. You only have indexes up to 3 in your arrays. 0-1-2-3...

Without actually seeing more code, or knowing exactly where you're getting your index out of bounds... it's a shot in the dark.