Fixes #25
This commit is contained in:
@@ -7,9 +7,11 @@ import imgui.ImGui;
|
|||||||
import imgui.ImGuiStyle;
|
import imgui.ImGuiStyle;
|
||||||
import sudoku.io.SudokuSerializer;
|
import sudoku.io.SudokuSerializer;
|
||||||
import sudoku.solver.BacktrackingSolver;
|
import sudoku.solver.BacktrackingSolver;
|
||||||
|
import sudoku.solver.HintHelper;
|
||||||
import sudoku.solver.HumanSolver;
|
import sudoku.solver.HumanSolver;
|
||||||
import sudoku.solver.MixedSolver;
|
import sudoku.solver.MixedSolver;
|
||||||
import sudoku.solver.Solver;
|
import sudoku.solver.Solver;
|
||||||
|
import sudoku.solver.HintHelper.Hint;
|
||||||
import sudoku.structure.MultiDoku;
|
import sudoku.structure.MultiDoku;
|
||||||
|
|
||||||
public class SudokuView extends BaseView {
|
public class SudokuView extends BaseView {
|
||||||
@@ -68,6 +70,16 @@ public class SudokuView extends BaseView {
|
|||||||
stopResolve();
|
stopResolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void renderHintButton() {
|
||||||
|
if (!this.resolved && centeredButton("Indice")) {
|
||||||
|
Hint hint = HintHelper.getHint(this.doku, new BacktrackingSolver());
|
||||||
|
assert (hint != null);
|
||||||
|
hint.cell().setSymbolIndex(hint.newValue());
|
||||||
|
if (this.doku.isSolved())
|
||||||
|
this.sudokuRenderer.onResolve.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void startSolve(Solver solver) {
|
private void startSolve(Solver solver) {
|
||||||
resolveThread = new Thread(() -> {
|
resolveThread = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
@@ -102,7 +114,6 @@ public class SudokuView extends BaseView {
|
|||||||
ImGui.beginDisabled();
|
ImGui.beginDisabled();
|
||||||
|
|
||||||
if (!this.resolved && centeredButton("Résoudre")) {
|
if (!this.resolved && centeredButton("Résoudre")) {
|
||||||
// beginSolve = true;
|
|
||||||
ImGui.openPopup("solve");
|
ImGui.openPopup("solve");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +142,7 @@ public class SudokuView extends BaseView {
|
|||||||
@Override
|
@Override
|
||||||
public void render() {
|
public void render() {
|
||||||
sudokuRenderer.render();
|
sudokuRenderer.render();
|
||||||
|
renderHintButton();
|
||||||
renderSolveButton();
|
renderSolveButton();
|
||||||
renderSaveButton();
|
renderSaveButton();
|
||||||
renderCancelButton();
|
renderCancelButton();
|
||||||
|
|||||||
54
app/src/main/java/sudoku/solver/HintHelper.java
Normal file
54
app/src/main/java/sudoku/solver/HintHelper.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package sudoku.solver;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import sudoku.structure.Cell;
|
||||||
|
import sudoku.structure.MultiDoku;
|
||||||
|
|
||||||
|
public class HintHelper {
|
||||||
|
|
||||||
|
public static record Hint(Cell cell, int newValue) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Hint getHint(MultiDoku doku, Solver solver) {
|
||||||
|
doku.getStateManager().pushState();
|
||||||
|
doku.clearMutableCells();
|
||||||
|
if (!solver.solve(doku))
|
||||||
|
return null;
|
||||||
|
var stateSolved = doku.getStateManager().popAndGetState();
|
||||||
|
// find differences
|
||||||
|
Map<Cell, Integer> newValues = new HashMap<>();
|
||||||
|
for (var entry : stateSolved.entrySet()) {
|
||||||
|
Cell cell = entry.getKey();
|
||||||
|
// we only want the cells that can be filled
|
||||||
|
if (!cell.isMutable())
|
||||||
|
continue;
|
||||||
|
int oldValue = cell.getSymbolIndex();
|
||||||
|
int newValue = stateSolved.get(cell);
|
||||||
|
if (oldValue == newValue)
|
||||||
|
continue;
|
||||||
|
// we have to clear the cell
|
||||||
|
if (newValue == Cell.NOSYMBOL)
|
||||||
|
return new Hint(cell, newValue);
|
||||||
|
// we have to change the cell value
|
||||||
|
if (oldValue != Cell.NOSYMBOL && newValue != oldValue)
|
||||||
|
return new Hint(cell, newValue);
|
||||||
|
|
||||||
|
// there is a valid move
|
||||||
|
newValues.put(cell, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is too complex just for fetching a random entry, but whatever ...
|
||||||
|
Random r = new Random();
|
||||||
|
List<Cell> cells = new ArrayList<>(newValues.keySet());
|
||||||
|
Cell randomCell = cells.get(r.nextInt(cells.size()));
|
||||||
|
int randomCellValue = newValues.get(randomCell);
|
||||||
|
return new Hint(randomCell, randomCellValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,27 +15,35 @@ public class StateManager {
|
|||||||
this.doku = doku;
|
this.doku = doku;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushState() {
|
public Map<Cell, Integer> pushState() {
|
||||||
states.add(new HashMap<>());
|
states.add(saveState());
|
||||||
saveState();
|
return states.getLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void popState() {
|
public void popState() {
|
||||||
assert (states.size() > 0);
|
assert (states.size() > 0);
|
||||||
restoreState();
|
restoreState(states.pop());
|
||||||
states.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restoreState() {
|
public Map<Cell, Integer> popAndGetState() {
|
||||||
for (var entry : this.states.getLast().entrySet()) {
|
assert (states.size() > 0);
|
||||||
|
var currentState = saveState();
|
||||||
|
restoreState(states.pop());
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreState(Map<Cell, Integer> state) {
|
||||||
|
for (var entry : state.entrySet()) {
|
||||||
entry.getKey().setSymbolIndex(entry.getValue());
|
entry.getKey().setSymbolIndex(entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveState() {
|
private Map<Cell, Integer> saveState() {
|
||||||
|
Map<Cell, Integer> state = new HashMap<>();
|
||||||
for (Cell cell : this.doku.getCells()) {
|
for (Cell cell : this.doku.getCells()) {
|
||||||
states.getLast().put(cell, cell.getSymbolIndex());
|
state.put(cell, cell.getSymbolIndex());
|
||||||
}
|
}
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user