60 lines
1.8 KiB
Java
60 lines
1.8 KiB
Java
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 record Hint(Cell cell, int newValue) {}
|
|
|
|
/**
|
|
* Si possible, donne un indice sur la résolution du doku passé en paramètre,
|
|
* selon la méthode de résolution rensaignée.
|
|
* @param doku MultiDoku, multidoku pour lequel on veut un indice
|
|
* @param solver Solver, méthode de résolution souhaitée
|
|
* @return Hint, indice sur une case à remplir, valant null si le doku n'a pas de solution.
|
|
*/
|
|
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)
|
|
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);
|
|
}
|
|
|
|
}
|