数独解算器无法正确解决

时间:2018-12-05 04:10:59

标签: java multithreading solver sudoku

我创建了一个程序,该程序接受未完成的数独难题的测试用例,并且应该使用多线程来快速解决它。我遇到了一个问题,它只能工作1/3次,并且当它“起作用”时,它会返回一个破坏规则的谜题。例如,同一列中有两个5。我想知道线程是否执行得太快并且无法通信?我可以改变哪些事情或看不到问题?

这是我的SudokuSolver课。它包含两种方法:cellChecker和fillPuzzle。单元格检查器检查单个单元格,并在其填充时返回false;如果单元格为空(包含0),则返回true。它也包含多线程的代码,我怀疑这是问题所在。

fillPuzzle仅在需要时创建拼图,然后使用cellChecker正确解决数独难题。

public boolean cellChecker(int puzzle[][], int row, int col, int number) {
    //Set the cellCheck boolean to true for a default case
    cellCheck = true;
    //variables that give us the start of the row and column respectively
    //If it doesn't get divided by 3 and then multiplied by 3, the threads
    //get an out of bounds exception and gets real mad. found this math
    //from stackoverflow.
    int rowStart = (row / 3) * 3;
    int colStart = (col / 3) * 3;

    //The threads are created to do the 9x9 grid in 3x3 sections,
    //so it can get done quicker and cut down the large task at hand.
    //checks via col
    Thread thread1 = new Thread(new Runnable() {
        public void run() {
            //for loop that checks the col
            for (int i = 0; i < 9; i++) {
                if (puzzle[row][i] == number) {
                    cellCheck = false;
                }
            }
        }
    });
    thread1.start();

    //another thread to take on it's 3x3 part via row
    Thread thread2 = new Thread(new Runnable() {
        public void run() {
            //for loop that checks the row
            for (int i = 0; i < 9; i++) {
                if (puzzle[i][col] == number) {
                    cellCheck = false;
                }
            }
        }
    });
    thread2.start();

    //another thread to take on it's 3x3 part via cell by cell
    Thread thread3 = new Thread(new Runnable() {
        public void run() {
            //for loop that checks the specific cell
            for (int rowCell = rowStart; rowCell < rowStart + 3; rowCell++) {
                for (int colCell = 0; colCell < colStart + 3; colCell++) {
                    if (puzzle[rowCell][colCell] == number) {
                        cellCheck = false;
                    }
                }
            }
        }
    });
    thread3.start();

    //returns the boolean whether the box is empty or not. If it is false,
    //it is filled with the number it needs. if it's true, it still needs
    //a number
    return cellCheck;
}

public boolean fillPuzzle(int puzzle[][], int row, int col) {
    if (row < 9) {
        //if the 9x9 puzzle is not created and filled with 0's, create it
        if (puzzle[row][col] != 0) {
            if (col < 8) {
                //returns created 9x9 puzzle
                return fillPuzzle(puzzle, row, col + 1);
            } else if (row < 8) {
                //returns created 9x9 puzzle
                return fillPuzzle(puzzle, row + 1, 0);
            }
            //already created, return true!
            return true;
        } else {
            //if the puzzle is created, go through and check for the number
            //up until or equal to 9 because sudoku goes from 1-9
            //once it finds the number that belongs in the cell, it
            //puts it in that cell
            for (int i = 1; i <= 9; i++) {
                if (cellChecker(puzzle, row, col, i)) {
                    puzzle[row][col] = i;
                    //If at the end of col, add a row to finish the table
                    if (col == 8) {
                        if (fillPuzzle(puzzle, row + 1, 0)) {
                            return true;
                        }
                    } else {
                        //add 1 to the col if it doesn't == 8 because
                        //that means there's not enough cols
                        if (fillPuzzle(puzzle, row, col + 1)) {
                            return true;
                        }
                    }
                    //all else fails, set it to 0 and we'll check it later
                    puzzle[row][col] = 0;
                }
            }
            return false;
        }
    }
    return true;
}

这是我的菜单类,其中发生拼图测试用例

public class Menu {

private SudokuSolver solver = new SudokuSolver();
//This is a test case sudoku puzzle I found off the internet to use as
//an example
private int sudokuPuzzle[][] = {{8, 0, 0, 0, 0, 0, 0, 0, 0},
                                {0, 0, 3, 6, 0, 0, 0, 0, 0},
                                {0, 7, 0, 0, 9, 0, 2, 0, 0},
                                {0, 5, 0, 0, 0, 7, 0, 0, 0},
                                {0, 0, 0, 0, 4, 5, 7, 0, 0},
                                {0, 0, 0, 1, 0, 0, 0, 3, 0},
                                {0, 0, 1, 0, 0, 0, 0, 6, 8},
                                {0, 0, 8, 5, 0, 0, 0, 1, 0},
                                {0, 9, 0, 0, 0, 0, 4, 0, 0}};

public void start() {
    //set to the method fillPuzzle. It tries to solve the
    //sudoku puzzle and if it does, it is set to true. If it doesn't
    //it says no thank you.
    boolean filledPuzzle = solver.fillPuzzle(sudokuPuzzle, 0, 0);

    //if it filled the puzzle, it prints it out.
    if (filledPuzzle) {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                System.out.print(sudokuPuzzle[row][col] + " ");
            }
            System.out.println();
        }
        //if it can't, it let's the person know.
    } else {
        System.out.println("Solution not found");
    }
}

}

最后,这听起来可能很愚蠢,但是我不确定100%如何实现Runnable的工作,但是它确实在sudokusolver类中给了我一个空的run方法,如果我删除它,我会很生气。我想知道是否需要放置一些东西才能使其正确有效地工作?

@Override
public void run() {

}

0 个答案:

没有答案