From 3cf7005151eaf13981e85ea45b70bdf9b27aa5b0 Mon Sep 17 00:00:00 2001 From: Imbus Date: Mon, 11 Dec 2023 13:12:50 +0100 Subject: [PATCH 1/9] User feedback on unsolvable --- app/src/main/java/gui/SudokuController.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/gui/SudokuController.java b/app/src/main/java/gui/SudokuController.java index 348c997..69def49 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(); + if (!solved) { + view.showErrorMessage("Could not solve the board."); + System.out.println("Could not solve the board."); + System.out.println(model.toString()); + } else { + // Update the view + view.updateView(model.getBoard()); + } - // Update the view - view.updateView(model.getBoard()); } }); From 2209dd7786a499809b69625477b3fbf84b11d88a Mon Sep 17 00:00:00 2001 From: Imbus Date: Mon, 11 Dec 2023 13:50:58 +0100 Subject: [PATCH 2/9] Ugly fix for invalid input --- app/src/main/java/gui/SudokuController.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/gui/SudokuController.java b/app/src/main/java/gui/SudokuController.java index 69def49..98c2f31 100644 --- a/app/src/main/java/gui/SudokuController.java +++ b/app/src/main/java/gui/SudokuController.java @@ -94,7 +94,22 @@ public class SudokuController { int row = view.getSelectedRow(); int col = view.getSelectedColumn(); - int value = Integer.parseInt(view.getCellValue(row, col)); + int value = 0; + + String cellValue = view.getCellValue(row, col); + if (cellValue == null || cellValue.equals("")) { + value = 0; + } else { + try { + value = Integer.parseInt(cellValue); + } catch (NumberFormatException ex) { + model.set(row, col, 0); + view.updateView(model.getBoard()); + view.showErrorMessage("Invalid input. Try again."); + return; // Bail out if the input is invalid + } + } + // Check if the input is legal and update the model and view if (model.isLegal(row, col, value)) { model.set(row, col, value); From 7e5253fb4b7ac94e1002b05e2c6a68c7bbff2f95 Mon Sep 17 00:00:00 2001 From: Imbus Date: Mon, 11 Dec 2023 13:58:05 +0100 Subject: [PATCH 3/9] Slightly less ugly fix for invalid input --- app/src/main/java/gui/SudokuController.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/gui/SudokuController.java b/app/src/main/java/gui/SudokuController.java index 98c2f31..5528349 100644 --- a/app/src/main/java/gui/SudokuController.java +++ b/app/src/main/java/gui/SudokuController.java @@ -103,20 +103,17 @@ public class SudokuController { try { value = Integer.parseInt(cellValue); } catch (NumberFormatException ex) { - model.set(row, col, 0); - view.updateView(model.getBoard()); - view.showErrorMessage("Invalid input. Try again."); - return; // Bail out if the input is invalid + value = 0; } } - // 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()); - } else { + // If the input is invalid + if (!model.isLegal(row, col, value)) { + value = 0; view.showErrorMessage("Invalid input. Try again."); } + model.set(row, col, value); + view.updateView(model.getBoard()); } } } From d056732addea2ffba64a36b6d1a61aed927fb1b9 Mon Sep 17 00:00:00 2001 From: Imbus Date: Mon, 11 Dec 2023 14:25:04 +0100 Subject: [PATCH 4/9] Polishing invalid input handling --- app/src/main/java/gui/SudokuController.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/gui/SudokuController.java b/app/src/main/java/gui/SudokuController.java index 5528349..a95f1a4 100644 --- a/app/src/main/java/gui/SudokuController.java +++ b/app/src/main/java/gui/SudokuController.java @@ -94,24 +94,31 @@ public class SudokuController { int row = view.getSelectedRow(); int col = view.getSelectedColumn(); + // 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 = 0; + value = -1; } } - // If the input is invalid - if (!model.isLegal(row, col, value)) { + // If the input is invalid, value < 0 indicates parse error + if (!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()); } From f9fa515651d3b7d7909167f090f9ce52fbf54bb9 Mon Sep 17 00:00:00 2001 From: dDogge <> Date: Mon, 11 Dec 2023 14:32:51 +0100 Subject: [PATCH 5/9] Extending testcases --- app/sample_sudokus/testfall_3.txt | 9 +++++++++ app/sample_sudokus/testfall_5.txt | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 app/sample_sudokus/testfall_3.txt create mode 100644 app/sample_sudokus/testfall_5.txt 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 From af77468edcbf79d546457d601e2b50b6adbeffbd Mon Sep 17 00:00:00 2001 From: dDogge <> Date: Mon, 11 Dec 2023 14:34:51 +0100 Subject: [PATCH 6/9] Extending testcases --- app/src/test/java/sudoku/SolverTest.java | 33 +++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) 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(); From e6cd5a2915bacd417708a8b702f54f7f54404e46 Mon Sep 17 00:00:00 2001 From: Imbus Date: Mon, 11 Dec 2023 14:35:25 +0100 Subject: [PATCH 7/9] Added bin directory to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) 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 From 270a9f381d86cc8755868f00e57dd6a37b5e3ad7 Mon Sep 17 00:00:00 2001 From: Imbus Date: Mon, 11 Dec 2023 14:58:54 +0100 Subject: [PATCH 8/9] File picker now refuses to load unsolvable files --- app/src/main/java/gui/SudokuController.java | 13 ++++++++++--- app/src/main/java/sudoku/Solver.java | 12 +++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/gui/SudokuController.java b/app/src/main/java/gui/SudokuController.java index a95f1a4..a283ab8 100644 --- a/app/src/main/java/gui/SudokuController.java +++ b/app/src/main/java/gui/SudokuController.java @@ -26,13 +26,13 @@ public class SudokuController { public void actionPerformed(ActionEvent e) { // Solve the board 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 { - // Update the view - view.updateView(model.getBoard()); } } @@ -70,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()); } @@ -113,7 +120,7 @@ public class SudokuController { } // If the input is invalid, value < 0 indicates parse error - if (!model.isLegal(row, col, value) || value < 0) { + if (value != 0 && !model.isLegal(row, col, value) || value < 0) { value = 0; view.showErrorMessage("Invalid input. Try again."); } 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) { From 26df774ca35d68ba7a937c0f77a8ddf59ce68b81 Mon Sep 17 00:00:00 2001 From: Imbus Date: Mon, 11 Dec 2023 14:59:11 +0100 Subject: [PATCH 9/9] Watchexec targets modified in justfile --- Justfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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"