2015-11-01 4 views
0

Я сделал программу, которая проверяет законченную головоломку 9x9 Sudoku, чтобы узнать, правильно ли она. Моя программа отлично работает, однако я хочу научиться использовать потоки. Я хочу, чтобы один поток проверял каждую строку, один поток, чтобы проверять каждый столбец, а затем один поток для проверки каждого блока. Всего три потока. У меня возникли проблемы с преобразованием моего кода, чтобы сделать это правильно, не получая ошибок. Мой код ниже:Многопоточная головоломка Sudoku в Java

public class Sudoku { 

public final Runnable row; 
public final Runnable col; 
public final Runnable block; 
public final Runnable testboard; 

public Sudoku(){ 
    row = new Runnable(){ 
     public void run(){ 
      Sudoku.this.testRows(board); 
     } 
    }; 
    col = new Runnable(){ 
     public void run(){ 
      Sudoku.this.testCols(board); 
     } 
    }; 
    block = new Runnable(){ 
     public void run(){ 
      Sudoku.this.testRegions(board); 
     } 
    }; 
    testboard = new Runnable(){ 
     public void run(){ 
      Sudoku.this.testBoard(board); 
     } 
    }; 
} 

public boolean testBoard(int[][] board) { 
    if (!testSize(board)) { 
     return false; 
    } 
    if (!testRows(board)) { 
     return false; 
    } 
    if (!testCols(board)) { 
     return false; 
    } 
    if (!testRegions(board)) { 
     return false; 
    } 
    return true; 
} 

boolean testSize(int[][] board) { 
    if (board.length != 9) { 
     return false; 
    } 
    for (int i = 0; i < board.length; i++) { 
     if (board[i].length != 9) { 
      return false; 
     } else; 
    } 
    return true; 
} 

boolean checkDigits(int[] array) { 
    if (array.length != 9) { 
     return false; 
    } 
    int[] counts = new int[10]; 
    for (int i = 0; i 
      < array.length; i++) { 

     if (array[i] < 1 || array[i] > 9) { 
      return false; 
     } 
     if (counts[array[i]] > 0) { 
      return false; 
     } 
     counts[array[i]]++; 
    } 
    return true; 
} 

boolean testRows(int[][] board) { 
    for (int i = 0; i < board.length; i++) { 
     if (!checkDigits(board[i])) { 
      return false; 
     } 
    } 
    return true; 
} 

boolean testCols(int[][] board) { 
    int[] tmp = new int[board.length]; 
    for (int col = 0; col < board.length; col++) { 
     for (int row = 0; row < board.length; row++) { 
      tmp[row] 
        = board[row][col]; 
     } 
     if (!checkDigits(tmp)) { 
      return false; 
     } 
    } 
    return true; 
} 

boolean testRegions(int[][] board) { 
    for (int row = 0; row < board.length; row += 3) { 
     for (int col = 0; col 
       < board.length; col += 3) { 
      if (!testRegion(board, row, col)) { 
       return false; 
      } 
     } 
    } 
    return true; 
} 

boolean testRegion(int[][] board, int startRow, int startCol) { 
    int[] tmp = new int[board.length]; 
    int index = 0; 
    for (int row = startRow; row < startRow + 3; row++) { 
     for (int col = startCol; col < startCol + 3; col++) { 
      tmp[index] 
        = board[row][col]; 
      index++; 
     } 
    } 
    return checkDigits(tmp); 
} 
} 

public class TestPuzzle { 

public static void testpuzzle() throws FileNotFoundException{ 
    Sudoku sudoku = new Sudoku(); 
    String fileName = "SudokuRight.txt";//This is for the print statment 
    Scanner inputStream = null; 
    String[] line; 
    System.out.println("The file " + fileName + " contains the following sudoku puzzle:\n"); 
    inputStream = new Scanner(new File("C:\\Users\\username\\Documents\\NetBeansProjects\\Sudoku\\SudokuRight.txt")); 
    int[][] puzzle = new int[9][9]; 
    int row = 0; 
    while (inputStream.hasNextLine()) { 
     line = inputStream.nextLine().split(","); 
     for (int i = 0; i < 9; i++) { 
      puzzle[row][i] = Integer.parseInt(line[i]); 
     } 
     row++; 
    } 
    for (int i = 0; i < 9; i++) { 
     System.out.println(Arrays.toString(puzzle[i])); 
    } 

    boolean result = sudoku.testBoard(puzzle); 
    System.out.println("Result: " + result); 
    if (result == true) { 
     System.out.println("This sudoku solution IS valid!"); 
    } else if (result == false) { 
     System.out.println("This sudoku solution IS NOT valid!"); 
    } 
} 
} 

Вот мой основной класс:

public static void main(String[] args) throws FileNotFoundException { 
    Sudoku x = new Sudoku(); 
    new Thread(x.row).start(); 
    new Thread(x.col).start(); 
    new Thread(x.block).start(); 
    new Thread(x.testboard).start(); 
} 

Вот мой файл, который я просматриваю в:

8,3,5,4,1,6,9,2,7 
2,9,6,8,5,7,4,3,1 
4,1,7,2,9,3,6,5,8 
5,6,9,1,3,4,7,8,2 
1,2,3,6,7,8,5,4,9 
7,4,8,5,2,9,1,6,3 
6,5,2,7,8,1,3,9,4 
9,8,1,3,4,5,2,7,6 
3,7,4,9,6,2,8,1,5 

Вот мой выход, прежде чем я попытался с помощью темы :

The file SudokuRight.txt contains the following sudoku puzzle: 

[8, 3, 5, 4, 1, 6, 9, 2, 7] 
[2, 9, 6, 8, 5, 7, 4, 3, 1] 
[4, 1, 7, 2, 9, 3, 6, 5, 8] 
[5, 6, 9, 1, 3, 4, 7, 8, 2] 
[1, 2, 3, 6, 7, 8, 5, 4, 9] 
[7, 4, 8, 5, 2, 9, 1, 6, 3] 
[6, 5, 2, 7, 8, 1, 3, 9, 4] 
[9, 8, 1, 3, 4, 5, 2, 7, 6] 
[3, 7, 4, 9, 6, 2, 8, 1, 5] 
Result: true 
This sudoku solution IS valid! 
BUILD SUCCESSFUL (total time: 0 seconds) 

Я хочу, чтобы мой выход ut, чтобы быть тем же самым, что и выше, но я хочу найти способ разбить мои методы на потоки, чтобы все строки, столбцы и блоки проверялись одновременно. Любая помощь была бы очень оценена.

+1

Зачем вы заносили код? – wvdz

+0

Код, который закомментирован, - это код, который я пытался использовать для создания тем, но он не работает. – user2113442

+1

«это не работает» не очень хорошее описание проблемы. И это довольно запутанно, что вы отправляете код, который действительно работает. Вероятно, вы должны удалить весь этот рабочий код и показать только код, который не работает, и почему он не работает. – wvdz

ответ

0

Вы можете сделать это следующим образом:

Сначала создайте вызываемая для каждого теста вы делаете

Callable<Boolean> testCollumnsTask = new Callable<>(){ 

      @Override 
      public Boolean call(){ 
       return Boolean.valueOf(testCols(board)); 
      } 
    } 

Что является намного проще с лямбды

Callable<Boolean> callable =() -> Boolean.valueOf(testCols(board)); 

Сделайте то же самое для отдохнуть, заменить testCols другими испытаниями.

Теперь многопоточный testBoard (если вы используете Java 8)

public boolean testBoard(int[][] board) { 
    List<Callable<Boolean>> tests = new ArrayList<>(); 
    tests.add(() -> Boolean.valueOf(testCols(board)); 
    tests.add(() -> Boolean.valueOf(testRegions(board)); 
    tests.add(() -> Boolean.valueOf(testRows(board)); 
    tests.add(() -> Boolean.valueOf(testSize(board)); 

    /*Maybe store this threadPool in a field so you dont create it everytime*/ 
    ExecutorService threadPool = Executors.newCachedThreadPool(); 
    List<Future<Boolean>> results = threadPool.invokeAll(tests); 

    for(Future<Boolean> future: results){ 
     if(!Boolean.TRUE.equals(future.get()){ 
      return false; 
     } 
    } 
    return true; 
} 

future.get() бросает проверяемое исключение, которое вы должны решить, как справиться с этим.

+0

В какой класс я могу вставить вызываемый код? Я предполагаю конструктор класса Sudoku? И где я делаю заявление лямбда? Я также заменяю свой текущий метод testBoard тем, который вы предоставили? – user2113442

+0

В Callable < > указан тип результата. Поскольку результат теста является логическим, имеет смысл заставить логическую задачу возвращать. Вы можете заменить тот, который я предоставил, или изменить строку Runnable на строку Callable . Тогда лямбда является 'row =() -> testRows (доска);' – Zpetkov

+0

Это мой первый раз, используя лямбда. Поэтому мне не нужно использовать первый блок кода, который вы предоставили с переопределением? Я могу просто набрать 1 строку кода для каждого теста, который я хочу сделать (размер, строка, столбец, область). Но где я делаю заявление лямбда. NetBeans говорит, что это не должно быть в конструкторе. – user2113442