Я создал программу, которая берет в тестовом случае незаконченную головоломку Судоку и должна использовать многопоточность, чтобы быстро ее решить.Я столкнулся с проблемой, когда он работает только 1/3 раза, а когда он «работает», он возвращает загадку, которая нарушает правила.Например, две пятерки в одном столбце.Мне интересно, если потоки работают слишком быстро и не общаются?Что я могу изменить или какие проблемы не вижу?
Вот мой класс SudokuSolver.Он содержит два метода: cellChecker и fillPuzzle.Средство проверки ячеек проверяет отдельные ячейки и возвращает значение false, если они заполнены, или значение true, если ячейка пуста (содержит 0).Он также содержит код для многопоточности, где я подозреваю, что проблема заключается в следующем.
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, но этодал мне пустой метод run в моем классе sudokusolver и разозлился, если я удалил его.Мне было интересно, нужно ли что-то поместить туда, чтобы оно работало правильно и эффективно?
@Override
public void run() {
}