3

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.

finnw
  • 47,861
  • 24
  • 143
  • 221
Jordan King
  • 93
  • 1
  • 6
  • This seems wrong in the second for loop: `i <= GRID_SIZE` – Keppil Jul 29 '12 at 22:21
  • What exact data type are you using to store the random number list? If it is a list, it is probably shrinking as you remove things, so if your list has 9, and you find one and remove it, it now has 8. if you try look at the 9th position again, it's an out of bounds exception – dann.dev Jul 29 '12 at 22:22
  • I don't really know where to start. Even if the minor problems are fixed, your entire approach appear to be wrong and won't be able to solve most harder problems. You need to have backtracking. – Mark Byers Jul 29 '12 at 22:22
  • yes, is `nums` declared with the same dimensions as `grid`? also, please indicate the line where you're getting the `IndexOutOfBoundsException`. – pb2q Jul 29 '12 at 22:23
  • @Keppil Thanks for that, I think I also started at 0 not 1. I have now changed it. – Jordan King Jul 29 '12 at 22:27
  • @dann.dev Oh, sorry I must have over looked that. I think I will change the `ranNum` variable to retrieve a number by `nums.size()`. – Jordan King Jul 29 '12 at 22:40
  • @pb2q `nums` has 4 integer values in it and and grid is a 4x4 2D Array. – Jordan King Jul 29 '12 at 22:44

4 Answers4

2

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.

Jorn
  • 20,612
  • 18
  • 79
  • 126
  • Thank you so very much for this Answer, I always thought that int and Integer were the same, this is a great lesson learnt for me. I have now fixed my code and it is working properly now, Thanks again! – Jordan King Jul 30 '12 at 04:33
1
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.

While-E
  • 1,527
  • 2
  • 20
  • 37
  • Thank you for your response, I have now corrected it and I get the numbers I want. – Jordan King Jul 30 '12 at 04:31
  • @Jordan King If the answer was correct your should accept it as the right answer so people popping in know what was wrong. Glad it helped. – While-E Aug 01 '12 at 21:52
1

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
rossum
  • 15,344
  • 1
  • 24
  • 38
0

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.

Jordan King
  • 93
  • 1
  • 6