This commit is contained in:
2025-02-01 20:45:56 +01:00
parent 52ca8b208c
commit 9e2421accf
3 changed files with 84 additions and 10 deletions

View File

@@ -7,9 +7,11 @@ import imgui.ImGui;
import imgui.ImGuiStyle;
import sudoku.io.SudokuSerializer;
import sudoku.solver.BacktrackingSolver;
import sudoku.solver.HintHelper;
import sudoku.solver.HumanSolver;
import sudoku.solver.MixedSolver;
import sudoku.solver.Solver;
import sudoku.solver.HintHelper.Hint;
import sudoku.structure.MultiDoku;
public class SudokuView extends BaseView {
@@ -68,6 +70,16 @@ public class SudokuView extends BaseView {
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) {
resolveThread = new Thread(() -> {
try {
@@ -102,7 +114,6 @@ public class SudokuView extends BaseView {
ImGui.beginDisabled();
if (!this.resolved && centeredButton("Résoudre")) {
// beginSolve = true;
ImGui.openPopup("solve");
}
@@ -131,6 +142,7 @@ public class SudokuView extends BaseView {
@Override
public void render() {
sudokuRenderer.render();
renderHintButton();
renderSolveButton();
renderSaveButton();
renderCancelButton();

View 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);
}
}

View File

@@ -15,27 +15,35 @@ public class StateManager {
this.doku = doku;
}
public void pushState() {
states.add(new HashMap<>());
saveState();
public Map<Cell, Integer> pushState() {
states.add(saveState());
return states.getLast();
}
public void popState() {
assert (states.size() > 0);
restoreState();
states.pop();
restoreState(states.pop());
}
private void restoreState() {
for (var entry : this.states.getLast().entrySet()) {
public Map<Cell, Integer> popAndGetState() {
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());
}
}
private void saveState() {
private Map<Cell, Integer> saveState() {
Map<Cell, Integer> state = new HashMap<>();
for (Cell cell : this.doku.getCells()) {
states.getLast().put(cell, cell.getSymbolIndex());
state.put(cell, cell.getSymbolIndex());
}
return state;
}
}