diff --git a/.gitignore b/.gitignore index 34124a5..722dd18 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ build .vscode +app/bin \ No newline at end of file diff --git a/Justfile b/Justfile index 675b9de..6ed91e0 100644 --- a/Justfile +++ b/Justfile @@ -11,7 +11,7 @@ clean: fd -td -I build -x rm -r watch: - watchexec -c -w app/src "just test && just run" + watchexec -r -c -w app/src "just test && just run" watchdoc: - watchexec -c -w app/src "just doc" + watchexec -r -c -w app/src "just doc" diff --git a/app/sample_sudokus/testfall_3.txt b/app/sample_sudokus/testfall_3.txt new file mode 100644 index 0000000..3d08a4c --- /dev/null +++ b/app/sample_sudokus/testfall_3.txt @@ -0,0 +1,9 @@ +1 2 3 0 0 0 0 0 0 +4 5 6 0 0 0 0 0 0 +0 0 0 7 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/app/sample_sudokus/testfall_5.txt b/app/sample_sudokus/testfall_5.txt new file mode 100644 index 0000000..e512bf8 --- /dev/null +++ b/app/sample_sudokus/testfall_5.txt @@ -0,0 +1,9 @@ +0 0 8 0 0 9 0 6 2 +0 0 0 0 0 0 0 0 5 +1 0 2 5 0 0 0 0 0 +0 0 0 2 1 0 0 9 0 +0 5 0 0 0 0 6 0 0 +6 0 0 0 0 0 0 2 8 +4 1 0 6 0 8 0 0 0 +8 6 0 0 3 0 1 0 0 +0 0 0 0 0 0 4 0 0 \ No newline at end of file diff --git a/app/src/main/java/gui/SudokuController.java b/app/src/main/java/gui/SudokuController.java index 348c997..a283ab8 100644 --- a/app/src/main/java/gui/SudokuController.java +++ b/app/src/main/java/gui/SudokuController.java @@ -25,10 +25,16 @@ public class SudokuController { @Override public void actionPerformed(ActionEvent e) { // Solve the board - model.solve(); - + boolean solved = model.solve(); // Update the view view.updateView(model.getBoard()); + if (!solved) { + view.showErrorMessage("Could not solve the board."); + System.out.println("Could not solve the board."); + System.out.println(model.toString()); + } else { + } + } }); @@ -64,6 +70,13 @@ public class SudokuController { if (newBoard != null) { // Set the model model.setBoard(newBoard); + + // Warn and clear if the board is not solvable + if(!model.isSolvable()) { + view.showErrorMessage("The board is not solvable."); + model.clear(); + } + // Update the view view.updateView(model.getBoard()); } @@ -88,14 +101,33 @@ public class SudokuController { int row = view.getSelectedRow(); int col = view.getSelectedColumn(); - int value = Integer.parseInt(view.getCellValue(row, col)); - // Check if the input is legal and update the model and view - if (model.isLegal(row, col, value)) { - model.set(row, col, value); - view.updateView(model.getBoard()); + // The value to be inserted into the cell + // Zero inicates an empty cell + // Negative values are invalid + int value = 0; + + String cellValue = view.getCellValue(row, col); + + // We need to check for null and empty string + if (cellValue == null || cellValue.equals("")) { + value = 0; } else { + try { + value = Integer.parseInt(cellValue); + } catch (NumberFormatException ex) { + value = -1; + } + } + + // If the input is invalid, value < 0 indicates parse error + if (value != 0 && !model.isLegal(row, col, value) || value < 0) { + value = 0; view.showErrorMessage("Invalid input. Try again."); } + + // Update the model and view + model.set(row, col, value); + view.updateView(model.getBoard()); } } } diff --git a/app/src/main/java/sudoku/Solver.java b/app/src/main/java/sudoku/Solver.java index 89d24cf..95a77b3 100644 --- a/app/src/main/java/sudoku/Solver.java +++ b/app/src/main/java/sudoku/Solver.java @@ -29,7 +29,12 @@ public class Solver implements SudokuSolver { /** Resets the board to all zeros */ @Override public void clear() { - board = new int[9][9]; + for (int[] row : board) { + for (int i = 0; i < row.length; ++i) { + row[i] = 0; + } + } + // board = new int[9][9]; } /* {@inheritDoc} */ @@ -144,6 +149,11 @@ public class Solver implements SudokuSolver { return false; } + // Ihe the number is already present in the cell + if (board[row][col] == num) { + return true; + } + // Check both the row and column for (int i = 0; i < 9; i++) { if (board[row][i] == num || board[i][col] == num) { diff --git a/app/src/test/java/sudoku/SolverTest.java b/app/src/test/java/sudoku/SolverTest.java index af637e1..3a5833b 100644 --- a/app/src/test/java/sudoku/SolverTest.java +++ b/app/src/test/java/sudoku/SolverTest.java @@ -86,7 +86,7 @@ class SolverTest { @Test void unsolvableTest() { Solver solver = new Solver(); - + // Simple example solver.clear(); solver.set(0, 0, 1); @@ -107,6 +107,37 @@ class SolverTest { assertFalse(solver.solve()); } + @Test + void unsolvableTestCase3() { + Solver solver = new Solver(); + + // More complex example + solver.clear(); + solver.set(0, 0, 1); + solver.set(0, 1, 2); + solver.set(0, 2, 3); + solver.set(1, 0, 4); + solver.set(1, 1, 5); + solver.set(1, 2, 6); + solver.set(2, 3, 7); + assertFalse(solver.isSolvable()); + } + + @Test + void solvableTestCase3() { + Solver solver = new Solver(); + + // More complex example + solver.clear(); + solver.set(0, 0, 1); + solver.set(0, 1, 2); + solver.set(0, 2, 3); + solver.set(1, 0, 4); + solver.set(1, 1, 5); + solver.set(1, 2, 6); + assertTrue(solver.isSolvable()); + } + @Test void setBoardInvalidInputThrowsTest() { Solver solver = new Solver();