Fixes #25
This commit is contained in:
@@ -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();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user