Search code examples
javamethodsoverlapsudoku

Java: Sudoku- increase number of empty spaces causes my code to throw an exception


I'm trying to make a Sudoku game for my project but if i increase the number of empty spaces in the Sudoku Grid the code just throws an exception arrayoutofbounds but can't figure out where it's coming from. k is the number of empty spaces in the grid.

I haven't tried anything because can't figure out what can be done at this kind of problem

Here is the code:

package sudoku.puzzle;
import java.util.*;

public class SudokuPuzzle {

    int[] mat[];
    int N; // number of columns/rows. 
    int SRN; // square root of N 
    int K; // No. Of missing digits 

    // Constructor 
    SudokuPuzzle(int N, int K) {
        this.N = N;
        this.K = K;

        // Compute square root of N 
        Double SRNd = Math.sqrt(N);
        SRN = SRNd.intValue();

        mat = new int[N][N];
    }
    // Driver code 
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("Select Level Of Difficulty \n 1.Easy\n 2.Medium\n 3.Hard");
        String Choice = in .next(); in .close();
        if ("1".equals(Choice) || "Easy".equals(Choice) || "easy".equals(Choice) || "e".equals(Choice) || "E".equals(Choice)) {
            int N = 9, K = 40;
            SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
            sudoku.fillValues();
            sudoku.printSudoku();
        }
        if ("2".equals(Choice) || "Medium".equals(Choice) || "medium".equals(Choice) || "m".equals(Choice) || "M".equals(Choice)) {
            int N = 9, K = 60;
            SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
            sudoku.fillValues();
            sudoku.printSudoku();
        }
        if ("3".equals(Choice) || "Hard".equals(Choice) || "hard".equals(Choice) || "h".equals(Choice) || "H".equals(Choice)) {
            int N = 9, K = 72;
            SudokuPuzzle sudoku = new SudokuPuzzle(N, K);
            sudoku.fillValues();
            sudoku.printSudoku();
        }
    }

    // Sudoku Generator 
    public void fillValues() {
        // Fill the diagonal of SRN x SRN matrices 
        fillDiagonal();

        // Fill remaining blocks 
        fillRemaining(0, SRN);

        // Remove Randomly K digits to make game 
        removeKDigits();
    }

    // Fill the diagonal SRN number of SRN x SRN matrices 
    void fillDiagonal() {

        for (int i = 0; i < N; i = i + SRN)

            // for diagonal box, start coordinates->i==j 
            fillBox(i, i);
    }

    // Returns false if given 3 x 3 block contains num. 
    boolean unUsedInBox(int rowStart, int colStart, int num) {
        for (int i = 0; i < SRN; i++)
            for (int j = 0; j < SRN; j++)
                if (mat[rowStart + i][colStart + j] == num)
                    return false;

        return true;
    }

    // Fill a 3 x 3 matrix. 
    void fillBox(int row, int col) {
        int num;
        for (int i = 0; i < SRN; i++) {
            for (int j = 0; j < SRN; j++) {
                do {
                    num = randomGenerator(N);
                }
                while (!unUsedInBox(row, col, num));

                mat[row + i][col + j] = num;
            }
        }
    }

    // Random generator 
    int randomGenerator(int num) {
        return (int) Math.floor((Math.random() * num + 1));
    }

    // Check if safe to put in cell 
    boolean CheckIfSafe(int i, int j, int num) {
        return (unUsedInRow(i, num) &&
            unUsedInCol(j, num) &&
            unUsedInBox(i - i % SRN, j - j % SRN, num));
    }

    // check in the row for existence 
    boolean unUsedInRow(int i, int num) {
        for (int j = 0; j < N; j++)
            if (mat[i][j] == num)
                return false;
        return true;
    }

    // check in the row for existence 
    boolean unUsedInCol(int j, int num) {
        for (int i = 0; i < N; i++)
            if (mat[i][j] == num)
                return false;
        return true;
    }

    // A recursive function to fill remaining  
    // matrix 
    boolean fillRemaining(int i, int j) {
        //  System.out.println(i+" "+j); 
        if (j >= N && i < N - 1) {
            i = i + 1;
            j = 0;
        }
        if (i >= N && j >= N)
            return true;

        if (i < SRN) {
            if (j < SRN)
                j = SRN;
        } else if (i < N - SRN) {
            if (j == (int)(i / SRN) * SRN)
                j = j + SRN;
        } else {
            if (j == N - SRN) {
                i = i + 1;
                j = 0;
                if (i >= N)
                    return true;
            }
        }

        for (int num = 1; num <= N; num++) {
            if (CheckIfSafe(i, j, num)) {
                mat[i][j] = num;
                if (fillRemaining(i, j + 1))
                    return true;

                mat[i][j] = 0;
            }
        }
        return false;
    }

    // Remove the K no. of digits to 
    // complete game 
    public void removeKDigits() {
        int count = K;
        while (count != 0) {
            int cellId = randomGenerator(N * N);

            // System.out.println(cellId); 
            // extract coordinates i  and j 
            int i = (cellId / N);
            int j = cellId % 9;
            if (j != 0)
                j = j - 1;

            // System.out.println(i+" "+j); 
            if (mat[i][j] != 0) {
                count--;
                mat[i][j] = 0;
            }
        }
    }

    // Print sudoku 
    public void printSudoku() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++)
                System.out.print(mat[i][j] + " ");
            System.out.println();
        }
        System.out.println();
    }
}

Solution

  • What you got is probably a ArrayIndexOutOfBoundsException. That means at some point you try to access a field of an array outside its boundaries.

    But I can´t see where K could be responsible for that. Can you provide more information about the error? E.g. at which value you get it or in which line.

    EDIT: The variable i int the removeKDigits() function exceeds the boundaries of the array if the random generator spits out the value 81.