Compare commits
2 Commits
f1d963e546
...
67da77af2e
| Author | SHA1 | Date | |
|---|---|---|---|
| 67da77af2e | |||
| c4becf2d55 |
@@ -27,10 +27,6 @@ public class RenderableMultidoku {
|
||||
this.doku = doku;
|
||||
}
|
||||
|
||||
public boolean isResolved() {
|
||||
return this.doku.isSolved();
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
@@ -51,21 +47,7 @@ public class RenderableMultidoku {
|
||||
return cells.get(index);
|
||||
}
|
||||
|
||||
public boolean setCellValue(Cell cell, int value) {
|
||||
for (Sudoku s : doku.getSubGrids()) {
|
||||
int cellIndex = s.getCells().indexOf(cell);
|
||||
// la cellule existe
|
||||
if (cellIndex != -1) {
|
||||
int cellX = cellIndex % s.getSize();
|
||||
int cellY = cellIndex / s.getSize();
|
||||
if (!s.canBePlaced(cellX, cellY, value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
cell.setSymbolIndex(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static record PositionConstraint(Sudoku sudoku1, Sudoku sudoku2, Coordinate offset) {
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@ public class SudokuRenderer {
|
||||
}
|
||||
} else {
|
||||
if (ImGui.button(Integer.toString(i + 1), cellSize)) {
|
||||
this.doku.setCellValue(currentCell, i);
|
||||
if (this.doku.isResolved())
|
||||
currentCell.trySetValue(i);
|
||||
if (this.doku.getDoku().isSolved())
|
||||
this.onResolve.emit();
|
||||
ImGui.closeCurrentPopup();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package sudoku.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
@@ -15,16 +16,15 @@ import sudoku.structure.Block;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
import sudoku.structure.SudokuFactory;
|
||||
|
||||
public class SudokuSerializer {
|
||||
|
||||
public static JSONObject serializeSudoku(final MultiDoku multidoku) {
|
||||
List<Cell> cellIds = new ArrayList<>();
|
||||
List<Cell> cellIds = new ArrayList<>();
|
||||
List<Block> blockIds = new ArrayList<>();
|
||||
|
||||
JSONObject jsonRoot = new JSONObject();
|
||||
JSONArray jsonCells = new JSONArray();
|
||||
JSONObject jsonRoot = new JSONObject();
|
||||
JSONArray jsonCells = new JSONArray();
|
||||
JSONArray jsonBlocks = new JSONArray();
|
||||
JSONArray jsonSudokus = new JSONArray(multidoku.getNbSubGrids());
|
||||
|
||||
@@ -33,9 +33,10 @@ public class SudokuSerializer {
|
||||
|
||||
// init cells
|
||||
for (Cell cell : sudoku.getCells()) {
|
||||
if (!cellIds.contains(cell)) {
|
||||
cellIds.add(cell);
|
||||
}
|
||||
if (cellIds.contains(cell))
|
||||
continue;
|
||||
|
||||
cellIds.add(cell);
|
||||
|
||||
Block block = cell.getBlock();
|
||||
if (!blockIds.contains(block)) {
|
||||
@@ -43,6 +44,7 @@ public class SudokuSerializer {
|
||||
}
|
||||
|
||||
int blockID = blockIds.indexOf(block);
|
||||
assert(blockID >= 0);
|
||||
int symbolIndex = cell.getSymbolIndex();
|
||||
|
||||
JSONObject cellJsonObject = new JSONObject();
|
||||
@@ -58,16 +60,17 @@ public class SudokuSerializer {
|
||||
|
||||
// init blocks
|
||||
|
||||
for (Block blockId : blockIds) {
|
||||
JSONObject blockJsonObject = new JSONObject();
|
||||
JSONArray cellsJsonArray = new JSONArray();
|
||||
for (Cell cell : blockId.getCells()) {
|
||||
int cellID = cellIds.indexOf(cell);
|
||||
cellsJsonArray.put(cellID);
|
||||
}
|
||||
blockJsonObject.put("cellIDs", cellsJsonArray);
|
||||
jsonBlocks.put(blockJsonObject);
|
||||
}
|
||||
for (Block blockId : blockIds) {
|
||||
JSONObject blockJsonObject = new JSONObject();
|
||||
JSONArray cellsJsonArray = new JSONArray();
|
||||
for (Cell cell : blockId.getCells()) {
|
||||
int cellID = cellIds.indexOf(cell);
|
||||
assert (cellID >= 0);
|
||||
cellsJsonArray.put(cellID);
|
||||
}
|
||||
blockJsonObject.put("cellIDs", cellsJsonArray);
|
||||
jsonBlocks.put(blockJsonObject);
|
||||
}
|
||||
|
||||
for (int i = 0; i < multidoku.getNbSubGrids(); i++) {
|
||||
// serialise sub grid
|
||||
@@ -82,6 +85,7 @@ public class SudokuSerializer {
|
||||
|
||||
for (Cell cell : sudoku.getCells()) {
|
||||
int cellID = cellIds.indexOf(cell);
|
||||
assert (cellID >= 0);
|
||||
cellsJsonArray.put(cellID);
|
||||
}
|
||||
|
||||
@@ -89,6 +93,7 @@ public class SudokuSerializer {
|
||||
|
||||
for (Block block : sudoku.getBlocks()) {
|
||||
int blockID = blockIds.indexOf(block);
|
||||
assert (blockID >= 0);
|
||||
blocksJsonArray.put(blockID);
|
||||
}
|
||||
|
||||
@@ -114,6 +119,7 @@ public class SudokuSerializer {
|
||||
|
||||
/**
|
||||
* Save a serialized MultiDoku in a JSON file.
|
||||
*
|
||||
* @param doku MultiDoku, MultiDoku to save.
|
||||
* @return String, the path of the save.
|
||||
*/
|
||||
@@ -139,6 +145,7 @@ public class SudokuSerializer {
|
||||
|
||||
/**
|
||||
* Get a MultiDoku from a pre-existing json save file.
|
||||
*
|
||||
* @param numberSave int, number of the save file to open.
|
||||
* @return MultiDoku, MultoDoku contained in the file.
|
||||
* @throws Exception when the given save file does not exist.
|
||||
@@ -158,20 +165,6 @@ public class SudokuSerializer {
|
||||
throw new Exception("This save does not exist.");
|
||||
} else {
|
||||
fileContent = new String(Files.readAllBytes(Paths.get("save/" + fileName)));
|
||||
/*
|
||||
try {
|
||||
FileReader file = new FileReader(f);
|
||||
char[] rawFileContent = {};
|
||||
int length = 1000;
|
||||
while (file.read(rawFileContent, 0, length) != -1) {
|
||||
rawFileContent = new char[]{};
|
||||
length = length * 10;
|
||||
}
|
||||
fileContent = new String(rawFileContent);
|
||||
} catch (IOException e) {
|
||||
throw new Exception("Error reading file.");
|
||||
}
|
||||
*/
|
||||
return deserializeSudoku(fileContent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package sudoku.solver;
|
||||
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.Sudoku;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
|
||||
public class Solver {
|
||||
|
||||
/**
|
||||
@@ -46,7 +46,7 @@ public class Solver {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> possibleSymbols = doku.getPossibleSymbolsOfCell(cellToFill);
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
|
||||
while (!possibleSymbols.isEmpty()) {
|
||||
int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size());
|
||||
@@ -68,31 +68,26 @@ public class Solver {
|
||||
* @param oldDoku MultiDoku, MultiDoku dont on veut le nombre de solutions.
|
||||
* @return int, nombre de solutions possibles.
|
||||
*/
|
||||
public static int countSolution(MultiDoku oldDoku) {
|
||||
public static int countSolution(MultiDoku doku) {
|
||||
int result = 0;
|
||||
|
||||
MultiDoku doku = oldDoku.clone();
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Cell cellToFill = doku.getFirstEmptyCell();
|
||||
if (cellToFill == null) {
|
||||
System.out.println("AAAAAAAAAAAAAA");
|
||||
return 0;
|
||||
}
|
||||
assert(cellToFill != null);
|
||||
|
||||
List<Integer> possibleSymbols = doku.getPossibleSymbolsOfCell(cellToFill);
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
|
||||
for (int symbol : possibleSymbols) {
|
||||
doku.getStateManager().pushState();
|
||||
cellToFill.setSymbolIndex(symbol);
|
||||
System.out.println("symbol : "+symbol);
|
||||
System.out.println("doku.isSolved() || Solver.solve(doku) ? "+ (doku.isSolved() || Solver.solve(doku)));
|
||||
if (doku.isSolved() || Solver.solve(doku)) {
|
||||
if (Solver.solve(doku)) {
|
||||
result++;
|
||||
}
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
doku.getStateManager().popState();
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -116,7 +111,7 @@ public class Solver {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> possibleSymbols = doku.getPossibleSymbolsOfCell(cellToFill);
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
if (possibleSymbols.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -156,7 +151,7 @@ public class Solver {
|
||||
boolean blocked = true;
|
||||
for (Cell cellToFill : cellsToFill) {
|
||||
|
||||
List<Integer> possibleSymbols = doku.getPossibleSymbolsOfCell(cellToFill);
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
if (possibleSymbols.size() != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,8 @@ public class StupidSolver {
|
||||
if (!sudoku.getCell(index).isMutable())
|
||||
return solve(sudoku, index + 1);
|
||||
|
||||
Coordinate coords = sudoku.toCoords(index);
|
||||
for (int symbol = 0; symbol < sudoku.getSize(); symbol++) {
|
||||
if (sudoku.tryPlaceCellSymbol(coords.getX(), coords.getY(), symbol)) {
|
||||
if (sudoku.getCell(index).trySetValue(symbol)) {
|
||||
// on tente de placer sur la case suivante
|
||||
if (solve(sudoku, index + 1)) {
|
||||
return true;
|
||||
@@ -34,7 +33,7 @@ public class StupidSolver {
|
||||
}
|
||||
}
|
||||
// on a tout essayé et rien n'a fonctionné
|
||||
sudoku.clearCell(coords.getX(), coords.getY());
|
||||
sudoku.getCell(index).empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,28 +24,21 @@ public class Cell {
|
||||
* Il est initialisé à Cell.NOSYMBOL.
|
||||
*/
|
||||
private int symbolIndex = Cell.NOSYMBOL;
|
||||
/**
|
||||
* Liste des index de symbole possibles pour cette Cell,
|
||||
* en fonction des contraintes de sudoku dans lequel elle est.
|
||||
*/
|
||||
private final List<Integer> possibleSymbols;
|
||||
/**
|
||||
* Si cette Cell peut être modififié ou non.
|
||||
*/
|
||||
private boolean isMutable = true;
|
||||
|
||||
public Cell() {
|
||||
this.possibleSymbols = new ArrayList<>();
|
||||
this(Cell.NOSYMBOL);
|
||||
}
|
||||
|
||||
public Cell(int symbolIndex) {
|
||||
this.symbolIndex = symbolIndex;
|
||||
this.possibleSymbols = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Cell(int symbolIndex, boolean isMutable) {
|
||||
this.symbolIndex = symbolIndex;
|
||||
this.possibleSymbols = new ArrayList<>();
|
||||
this.isMutable = isMutable;
|
||||
}
|
||||
|
||||
@@ -57,11 +50,6 @@ public class Cell {
|
||||
this.symbolIndex = symbolIndex;
|
||||
}
|
||||
|
||||
public void setPossibleSymbols(List<Integer> possibleSymbols) {
|
||||
this.possibleSymbols.clear();
|
||||
this.possibleSymbols.addAll(possibleSymbols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rend la Cell immuable.
|
||||
*/
|
||||
@@ -95,14 +83,6 @@ public class Cell {
|
||||
return this.symbolIndex == Cell.NOSYMBOL;
|
||||
}
|
||||
|
||||
public void removeSymbolFromPossibilities(int indexSymbol) {
|
||||
possibleSymbols.remove(indexSymbol);
|
||||
}
|
||||
|
||||
public List<Integer> getPossibleSymbols() {
|
||||
return this.possibleSymbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie si la Cell est modifiable
|
||||
* @return boolean, true si elle est modifiable ou false sinon.
|
||||
@@ -120,4 +100,35 @@ public class Cell {
|
||||
this.symbolIndex = Cell.NOSYMBOL;
|
||||
return oldSymbol;
|
||||
}
|
||||
|
||||
public boolean canHaveValue(int value) {
|
||||
for (Sudoku s :getBlock().getSudokus()) {
|
||||
int cellIndex = s.getCells().indexOf(this);
|
||||
// la cellule existe
|
||||
if (cellIndex != -1) {
|
||||
int cellX = cellIndex % s.getSize();
|
||||
int cellY = cellIndex / s.getSize();
|
||||
if (!s.canBePlaced(cellX, cellY, value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Integer> getPossibleSymbols() {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (int i = 0; i < getBlock().getSudokus().get(0).getSize(); i++) {
|
||||
if (canHaveValue(i))
|
||||
result.add(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean trySetValue(int newValue) {
|
||||
if (!canHaveValue(newValue))
|
||||
return false;
|
||||
setSymbolIndex(newValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,90 +19,60 @@ public class MultiDoku {
|
||||
*/
|
||||
private final List<Sudoku> subGrids;
|
||||
|
||||
private final StateManager stateManager;
|
||||
|
||||
public MultiDoku(List<Sudoku> subGrids) {
|
||||
this.subGrids = subGrids;
|
||||
}
|
||||
|
||||
public MultiDoku clone() {
|
||||
//TODO: ahhhhhhhhhhhhhhhhhhhhhhh
|
||||
return SudokuSerializer.deserializeSudoku(SudokuSerializer.serializeSudoku(this));
|
||||
this.stateManager = new StateManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie le nombre de sudoku contenu dans ce MultiDoku.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getNbSubGrids(){
|
||||
public int getNbSubGrids() {
|
||||
return subGrids.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la ie sudoku contenue dans ce MultiDoku.
|
||||
*
|
||||
* @param i int, indice du sudoku à renvoyer.
|
||||
* @return Sudoku, ie Sudoku
|
||||
*/
|
||||
public Sudoku getSubGrid(int i){
|
||||
public Sudoku getSubGrid(int i) {
|
||||
return subGrids.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la liste des Cells contenue dans ce MultiDoku,
|
||||
* soit les Cells contenues de chaques sous-Sudoku.
|
||||
*
|
||||
* @return List<Cell>
|
||||
*/
|
||||
public List<Cell> getCells(){
|
||||
public List<Cell> getCells() {
|
||||
Set<Cell> cellsSet = new HashSet<>();
|
||||
for (Sudoku sudoku : subGrids){
|
||||
for (Sudoku sudoku : subGrids) {
|
||||
cellsSet.addAll(sudoku.getCells());
|
||||
}
|
||||
return new ArrayList<>(cellsSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour les symboles possibles de chaque Cell.
|
||||
* @throws Exception, si ce n'est pas possible.
|
||||
*/
|
||||
public void updateSymbolsPossibilities() throws Exception {
|
||||
for (Sudoku sudoku : subGrids){
|
||||
sudoku.updateSymbolsPossibilities();
|
||||
}
|
||||
return new ArrayList<>(cellsSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Multidoku {");
|
||||
for (Sudoku sudoku : subGrids){
|
||||
for (Sudoku sudoku : subGrids) {
|
||||
sb.append("\n\t").append(sudoku.toString());
|
||||
}
|
||||
sb.append("\n}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie les symboles possibles d'une Cell donnée.
|
||||
* @param cellToFill Cell.
|
||||
* @return List<Integer>, liste des symboles possible.
|
||||
*/
|
||||
public List<Integer> getPossibleSymbolsOfCell(Cell cellToFill) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
boolean hasBeenFill = false;
|
||||
|
||||
for (Sudoku sudoku : this.subGrids) {
|
||||
if (sudoku.contains(cellToFill)) {
|
||||
if (!hasBeenFill) {
|
||||
result.addAll(sudoku.getPossibleSymbolsOfCell(cellToFill));
|
||||
hasBeenFill = true;
|
||||
} else {
|
||||
result.retainAll(sudoku.getPossibleSymbolsOfCell(cellToFill));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie les sous-Sudoku
|
||||
*
|
||||
* @return List<Sudoku>
|
||||
*/
|
||||
public List<Sudoku> getSubGrids() {
|
||||
@@ -111,43 +81,26 @@ public class MultiDoku {
|
||||
|
||||
/**
|
||||
* Check si le MultiDoku est valide, en fonction de ses sous-Sudokus.
|
||||
*
|
||||
* @return boolean, true s'il est valide et false sinon.
|
||||
*/
|
||||
public boolean isSolved() {
|
||||
boolean result = true;
|
||||
for (Sudoku sudoku : this.subGrids) {
|
||||
result = sudoku.isSolved() && result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (!(object instanceof MultiDoku)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getNbSubGrids() != ((MultiDoku) object).getNbSubGrids()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.getNbSubGrids(); i++) {
|
||||
if (!this.getSubGrid(i).equals(((MultiDoku) object).getSubGrid(i))) {
|
||||
if (!sudoku.isSolved())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la 1re Cell vide des sous-Sudoku.
|
||||
*
|
||||
* @return Cell, une Cell vide, ou null s'il n'y en a pas.
|
||||
*/
|
||||
public Cell getFirstEmptyCell() {
|
||||
for (Sudoku sudoku : this.subGrids) {
|
||||
Cell cellTmp = sudoku.getFirstEmptyCell();
|
||||
if (cellTmp != null && cellTmp.isEmpty()) {
|
||||
if (cellTmp != null) {
|
||||
return cellTmp;
|
||||
}
|
||||
}
|
||||
@@ -156,11 +109,12 @@ public class MultiDoku {
|
||||
|
||||
/**
|
||||
* Renvoie la liste des Cells préalablement remplies du MultiDoku.
|
||||
*
|
||||
* @return List<Cell>, vide si aucune Cell n'est remplie.
|
||||
*/
|
||||
public List<Cell> getFilledCells() {
|
||||
List<Cell> result = new ArrayList<>();
|
||||
for (Cell cell : this.getCells()){
|
||||
for (Cell cell : this.getCells()) {
|
||||
if (!cell.isEmpty()) {
|
||||
result.add(cell);
|
||||
}
|
||||
@@ -170,11 +124,12 @@ public class MultiDoku {
|
||||
|
||||
/**
|
||||
* Renvoie la liste des Cells vides du MultiDoku.
|
||||
*
|
||||
* @return List<Cell>, vide si aucune Cell ne l'est.
|
||||
*/
|
||||
public List<Cell> getEmptyCells() {
|
||||
List<Cell> result = new ArrayList<>();
|
||||
for (Cell cell : this.getCells()){
|
||||
for (Cell cell : this.getCells()) {
|
||||
if (cell.isEmpty()) {
|
||||
result.add(cell);
|
||||
}
|
||||
@@ -182,9 +137,9 @@ public class MultiDoku {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Vide une Cell donnée.
|
||||
*
|
||||
* @param cell Cell, à vider.
|
||||
*/
|
||||
public void empty(Cell cell) {
|
||||
@@ -195,6 +150,7 @@ public class MultiDoku {
|
||||
|
||||
/**
|
||||
* Renvoie le nombre de Cell contenue dans le MultiDoku.
|
||||
*
|
||||
* @return int, nombre de Cell dans le MultiDoku.
|
||||
*/
|
||||
public int getNbCells() {
|
||||
@@ -209,5 +165,9 @@ public class MultiDoku {
|
||||
filledCell.setImmutable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public StateManager getStateManager() {
|
||||
return stateManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
41
app/src/main/java/sudoku/structure/StateManager.java
Normal file
41
app/src/main/java/sudoku/structure/StateManager.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package sudoku.structure;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
//TODO: doc
|
||||
public class StateManager {
|
||||
|
||||
private final Stack<Map<Cell, Integer>> states;
|
||||
private final MultiDoku doku;
|
||||
|
||||
public StateManager(MultiDoku doku) {
|
||||
this.states = new Stack<>();
|
||||
this.doku = doku;
|
||||
}
|
||||
|
||||
public void pushState() {
|
||||
states.add(new HashMap<>());
|
||||
saveState();
|
||||
}
|
||||
|
||||
public void popState() {
|
||||
assert (states.size() > 0);
|
||||
restoreState();
|
||||
states.pop();
|
||||
}
|
||||
|
||||
private void restoreState() {
|
||||
for (var entry : this.states.getLast().entrySet()) {
|
||||
entry.getKey().setSymbolIndex(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void saveState() {
|
||||
for (Cell cell : this.doku.getCells()) {
|
||||
states.getLast().put(cell, cell.getSymbolIndex());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package sudoku.structure;
|
||||
import sudoku.constraint.BlockConstraint;
|
||||
import sudoku.constraint.Constraint;
|
||||
import sudoku.constraint.IConstraint;
|
||||
import sudoku.io.SudokuPrinter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -89,22 +90,6 @@ public class Sudoku {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tente de placer le symbole value dans la Cell de coordonnées x, y.
|
||||
* @param x int, abscisse de la Cell voulue.
|
||||
* @param y int, coordonnée de la Cell voulue;
|
||||
* @param value int, index du symbole que l'on veut placer.
|
||||
* @return boolean, true si le symbole a été placé, false sinon
|
||||
*/
|
||||
public boolean tryPlaceCellSymbol(int x, int y, int value) {
|
||||
assert (isValidCoords(x, y));
|
||||
if (!canBePlaced(x, y, value))
|
||||
return false;
|
||||
Cell cell = getCell(x, y);
|
||||
cell.setSymbolIndex(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vide la Cell dotn les coordonnées sont renseignées de son symbole.
|
||||
* @param x int, abscisse de la Cell voulue.
|
||||
@@ -194,7 +179,7 @@ public class Sudoku {
|
||||
}
|
||||
|
||||
public Cell getCell(int x, int y) {
|
||||
int index = y * getSize() + x;
|
||||
int index = toIndex(x, y);
|
||||
assert (isValidCoords(x, y));
|
||||
try {
|
||||
return this.cells.get(index);
|
||||
@@ -232,62 +217,6 @@ public class Sudoku {
|
||||
return this.cells.contains(cell);
|
||||
}
|
||||
|
||||
/**
|
||||
* Localise la Cell dans le Sudoku.
|
||||
* @param c Cell, cellule dont on veut les coordonées.
|
||||
* @return Coordinate, coordonnées de la Cell.
|
||||
* @throws Exception si la Cell n'appartient pas au Sudoku.
|
||||
*/
|
||||
private Coordinate getCoordinateCell(Cell c) throws Exception {
|
||||
int x = 0, y = 0;
|
||||
int size = this.getSize();
|
||||
|
||||
if (!this.contains(c)) {
|
||||
throw new Exception("The given cell is not in this sudoku.");
|
||||
}
|
||||
|
||||
// TODO: use this.cells.indexOf();
|
||||
|
||||
for (Cell cell : this.cells) {
|
||||
if (cell == c) {
|
||||
return new Coordinate(x, y);
|
||||
}
|
||||
if (x == size - 1) {
|
||||
y += 1;
|
||||
x = 0;
|
||||
} else {
|
||||
x += 1;
|
||||
}
|
||||
}
|
||||
return new Coordinate(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour les symboles possibles des Cells du Sudoku.
|
||||
*
|
||||
*/
|
||||
public void updateSymbolsPossibilities() {
|
||||
for (Constraint constraint : constraints) {
|
||||
List<Cell> cells = this.getCells();
|
||||
for (Cell cell : cells) {
|
||||
Coordinate coord = null;
|
||||
try {
|
||||
coord = this.getCoordinateCell(cell);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Cas jamais atteint.");
|
||||
}
|
||||
List<Integer> newPossibleSymbols = cell.getPossibleSymbols();
|
||||
newPossibleSymbols.retainAll(constraint.getPossibleSymbols(
|
||||
this,
|
||||
coord.getX(),
|
||||
coord.getY()
|
||||
));
|
||||
|
||||
cell.setPossibleSymbols(newPossibleSymbols);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Sudoku {");
|
||||
@@ -315,30 +244,6 @@ public class Sudoku {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie l'index des symboles possibles de la Cell passée en paramètres.
|
||||
* @param cellToFill Cell, cellule dont on cherche les symboles posisbles.
|
||||
* @return List<Integer>, la liste des index des symboles possibles, vide si la Cell n'appartient pas au Sudoku.
|
||||
*/
|
||||
public List<Integer> getPossibleSymbolsOfCell(Cell cellToFill) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
Coordinate cellCoordinates;
|
||||
try {
|
||||
cellCoordinates = this.getCoordinateCell(cellToFill);
|
||||
} catch (Exception e) {
|
||||
return result;
|
||||
}
|
||||
for (int i = 0; i < this.constraints.size(); i++) {
|
||||
Constraint constraint = this.constraints.get(i);
|
||||
if (i == 0) {
|
||||
result.addAll(constraint.getPossibleSymbols(this, cellCoordinates.getX(), cellCoordinates.getY()));
|
||||
} else {
|
||||
result.retainAll(constraint.getPossibleSymbols(this, cellCoordinates.getX(), cellCoordinates.getY()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le Sudoku est résolue, soit complet et cohérent avec ses contraintes.
|
||||
* @return boolean, valant true si le Sudoku est résolu, false sinon.
|
||||
@@ -362,89 +267,20 @@ public class Sudoku {
|
||||
* @return bollean, true si le Sudoku est valide, false sinon
|
||||
*/
|
||||
private boolean isValid() {
|
||||
for (Cell cell : this.getFilledCells()) {
|
||||
for (Constraint constraint : this.constraints) {
|
||||
try {
|
||||
Coordinate coords = this.getCoordinateCell(cell);
|
||||
for (int i = 0; i < cells.size(); i++) {
|
||||
Cell cell = getCell(i);
|
||||
if (cell.isEmpty())
|
||||
continue;
|
||||
|
||||
int symbolPlaced = cell.empty();
|
||||
List<Integer> possibleSymbols = constraint.getPossibleSymbols(
|
||||
this,
|
||||
coords.getX(),
|
||||
coords.getY()
|
||||
);
|
||||
Coordinate coordinate = toCoords(i);
|
||||
|
||||
cell.setSymbolIndex(symbolPlaced);
|
||||
if (!possibleSymbols.contains(symbolPlaced)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la liste des Cells remplies.
|
||||
* @return List<Cell>
|
||||
*/
|
||||
private List<Cell> getFilledCells() {
|
||||
List<Cell> result = new ArrayList<>();
|
||||
for (Cell cell : getCells()) {
|
||||
if (!cell.isEmpty()) {
|
||||
result.add(cell);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la liste des Cells modifiables.
|
||||
* @return List<Cell>
|
||||
*/
|
||||
private List<Cell> getEmptyCells() {
|
||||
List<Cell> result = new ArrayList<>();
|
||||
for (Cell cell : getCells()) {
|
||||
if (cell.isMutable()) {
|
||||
result.add(cell);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la liste des Cells immuables.
|
||||
* @return List<Cell>
|
||||
*/
|
||||
private List<Cell> getImmutableCells() {
|
||||
List<Cell> result = new ArrayList<>();
|
||||
for (Cell cell : getCells()) {
|
||||
if (!cell.isMutable()) {
|
||||
result.add(cell);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (!(object instanceof Sudoku)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getSize() != ((Sudoku) object).getSize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.getSize(); i++) {
|
||||
if (this.getCell(i).getSymbolIndex() != ((Sudoku) object).getCell(i).getSymbolIndex()) {
|
||||
int symbolPlaced = cell.empty();
|
||||
if (!canBePlaced(coordinate.getX(), coordinate.getY(), symbolPlaced)) {
|
||||
cell.setSymbolIndex(symbolPlaced);
|
||||
return false;
|
||||
}
|
||||
cell.setSymbolIndex(symbolPlaced);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,6 @@ public class SudokuFactory {
|
||||
*/
|
||||
public static boolean newDokuFromFilledOne(MultiDoku doku, int nbCellsToEmpty) throws Exception {
|
||||
|
||||
System.out.println("nbCellsToEmpty : "+nbCellsToEmpty);
|
||||
if (nbCellsToEmpty >= doku.getCells().size()) {
|
||||
throw new Exception();
|
||||
}
|
||||
@@ -141,7 +140,6 @@ public class SudokuFactory {
|
||||
int oldSymbol = cellToEmpty.empty();
|
||||
|
||||
int nbDokuSultions = Solver.countSolution(doku);
|
||||
System.out.println("oldSymbol : "+oldSymbol);
|
||||
if (nbDokuSultions == 1) {
|
||||
if (newDokuFromFilledOne(doku, --nbCellsToEmpty)) {
|
||||
return true;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package sudoku;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -13,24 +16,26 @@ import sudoku.structure.SudokuFactory;
|
||||
|
||||
public class SudokuSerializerTest {
|
||||
|
||||
void testSerializeWithSize(int blockWidth, int blockHeight, Random r) {
|
||||
MultiDoku sudoku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight,
|
||||
void testSerializeWithSize(int blockWidth, int blockHeight) {
|
||||
var sudoku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight,
|
||||
SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
Solver.solveRandom(sudoku, r);
|
||||
Solver.solveRandom(sudoku, new Random());
|
||||
JSONObject data = SudokuSerializer.serializeSudoku(sudoku);
|
||||
MultiDoku multiDoku = SudokuSerializer.deserializeSudoku(data);
|
||||
assert (data.toString().equals(SudokuSerializer.serializeSudoku(multiDoku).toString()));
|
||||
assertTrue(data.toString().equals(SudokuSerializer.serializeSudoku(multiDoku).toString()));
|
||||
}
|
||||
|
||||
void testSaveWithSize(int blockWidth, int blockHeight, Random r) {
|
||||
void testSaveWithSize(int blockWidth, int blockHeight) {
|
||||
MultiDoku doku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight,
|
||||
SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
Solver.solveRandom(doku, r);
|
||||
Solver.solveRandom(doku, new Random());
|
||||
String savePath = SudokuSerializer.saveMultiDoku(doku);
|
||||
MultiDoku otherDoku = null;
|
||||
try {
|
||||
otherDoku = SudokuFactory.fromfile(savePath);
|
||||
assert (otherDoku != null);
|
||||
|
||||
assertEquals(SudokuSerializer.serializeSudoku(doku).toString(), SudokuSerializer.serializeSudoku(otherDoku).toString());
|
||||
// clean file after test
|
||||
File fileToDelete = new File(savePath);
|
||||
fileToDelete.delete();
|
||||
@@ -38,27 +43,35 @@ public class SudokuSerializerTest {
|
||||
e.printStackTrace();
|
||||
assert false;
|
||||
}
|
||||
assert (doku.equals(otherDoku));
|
||||
}
|
||||
|
||||
void testSerializeX(int size) {
|
||||
var sudoku = SudokuFactory.createBasicXShapedMultidoku(size, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
Solver.solveRandom(sudoku, new Random());
|
||||
JSONObject data = SudokuSerializer.serializeSudoku(sudoku);
|
||||
MultiDoku multiDoku = SudokuSerializer.deserializeSudoku(data);
|
||||
|
||||
assertTrue(data.toString().equals(SudokuSerializer.serializeSudoku(multiDoku).toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSerialize() {
|
||||
Random r = new Random();
|
||||
testSerializeWithSize(3, 3, r);
|
||||
|
||||
/**
|
||||
int testCount = 5;
|
||||
int testCount = 20;
|
||||
for (int i = 0; i < testCount; i++) {
|
||||
int blockWidth = r.nextInt(10) + 1;
|
||||
int blockHeight = r.nextInt(10) + 1;
|
||||
testSerializeWithSize(blockWidth, blockHeight, r);
|
||||
int blockWidth = r.nextInt(4) + 1;
|
||||
int blockHeight = r.nextInt(4) + 1;
|
||||
testSerializeWithSize(blockWidth, blockHeight);
|
||||
}
|
||||
for (int i = 0; i < testCount; i++) {
|
||||
int blockWidth = r.nextInt(10) + 1;
|
||||
int blockHeight = r.nextInt(10) + 1;
|
||||
testSaveWithSize(blockWidth, blockHeight, r);
|
||||
int blockWidth = r.nextInt(4) + 1;
|
||||
int blockHeight = r.nextInt(4) + 1;
|
||||
testSaveWithSize(blockWidth, blockHeight);
|
||||
}
|
||||
for (int i = 0; i < testCount; i++) {
|
||||
int size = r.nextInt(2) + 2;
|
||||
testSerializeX(size);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,90 +2,101 @@ package sudoku.solver;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.io.SudokuSerializer;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
import sudoku.structure.SudokuFactory;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
class SolverTest {
|
||||
|
||||
@Test
|
||||
void solveTest() {
|
||||
Random rand = new Random();
|
||||
@Test
|
||||
void solveTest() {
|
||||
Random rand = new Random();
|
||||
|
||||
MultiDoku dokuToTest = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
MultiDoku dokuResult = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
MultiDoku dokuToTest = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
MultiDoku dokuResult = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
|
||||
Sudoku sudokuToTest = dokuToTest.getSubGrid(0);
|
||||
Sudoku sudokuResult = dokuResult.getSubGrid(0);
|
||||
Sudoku sudokuToTest = dokuToTest.getSubGrid(0);
|
||||
Sudoku sudokuResult = dokuResult.getSubGrid(0);
|
||||
|
||||
int ns = Cell.NOSYMBOL;
|
||||
List<Integer> immutableCells = List.of(ns, ns, 0, ns, ns, 2, 8, ns, 1,
|
||||
ns, 3, ns, ns, 5, 6, 7, ns, ns,
|
||||
ns, ns, ns, 8, ns, 7, ns, ns, 6,
|
||||
0, ns, 1, ns, ns, ns, ns, ns, ns,
|
||||
4, 8, 7, 5, 1, ns, 6, ns, ns,
|
||||
6, ns, 3, 2, ns, ns, ns, 8, 0,
|
||||
ns, ns, 6, ns, ns, 8, ns, 7, 5,
|
||||
8, 0, ns, 7, ns, 5, 2, ns, 3,
|
||||
5, ns, ns, ns, 3, 1, 0, ns, ns);
|
||||
int ns = Cell.NOSYMBOL;
|
||||
List<Integer> immutableCells = List.of(ns, ns, 0, ns, ns, 2, 8, ns, 1,
|
||||
ns, 3, ns, ns, 5, 6, 7, ns, ns,
|
||||
ns, ns, ns, 8, ns, 7, ns, ns, 6,
|
||||
0, ns, 1, ns, ns, ns, ns, ns, ns,
|
||||
4, 8, 7, 5, 1, ns, 6, ns, ns,
|
||||
6, ns, 3, 2, ns, ns, ns, 8, 0,
|
||||
ns, ns, 6, ns, ns, 8, ns, 7, 5,
|
||||
8, 0, ns, 7, ns, 5, 2, ns, 3,
|
||||
5, ns, ns, ns, 3, 1, 0, ns, ns);
|
||||
|
||||
assert (sudokuToTest.setImmutableCellsSymbol(immutableCells));
|
||||
assert (sudokuToTest.setImmutableCellsSymbol(immutableCells));
|
||||
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
|
||||
|
||||
List<Integer> correctCells = List.of(7, 6, 0, 3, 4, 2, 8, 5, 1,
|
||||
2, 3, 8, 1, 5, 6, 7, 0, 4,
|
||||
1, 4, 5, 8, 0, 7, 3, 2, 6,
|
||||
0, 2, 1, 6, 8, 3, 5, 4, 7,
|
||||
4, 8, 7, 5, 1, 0, 6, 3, 2,
|
||||
6, 5, 3, 2, 7, 4, 1, 8, 0,
|
||||
3, 1, 6, 0, 2, 8, 4, 7, 5,
|
||||
8, 0, 4, 7, 6, 5, 2, 1, 3,
|
||||
5, 7, 2, 4, 3, 1, 0, 6, 8);
|
||||
List<Integer> correctCells = List.of(7, 6, 0, 3, 4, 2, 8, 5, 1,
|
||||
2, 3, 8, 1, 5, 6, 7, 0, 4,
|
||||
1, 4, 5, 8, 0, 7, 3, 2, 6,
|
||||
0, 2, 1, 6, 8, 3, 5, 4, 7,
|
||||
4, 8, 7, 5, 1, 0, 6, 3, 2,
|
||||
6, 5, 3, 2, 7, 4, 1, 8, 0,
|
||||
3, 1, 6, 0, 2, 8, 4, 7, 5,
|
||||
8, 0, 4, 7, 6, 5, 2, 1, 3,
|
||||
5, 7, 2, 4, 3, 1, 0, 6, 8);
|
||||
|
||||
sudokuResult.setCellsSymbol(correctCells);
|
||||
sudokuResult.setCellsSymbol(correctCells);
|
||||
|
||||
System.out.println("\n****************************Doku Control\n");
|
||||
SudokuPrinter.printRectangleSudoku(sudokuResult, 3, 3);
|
||||
System.out.println("\n****************************Doku Control\n");
|
||||
SudokuPrinter.printRectangleSudoku(sudokuResult, 3, 3);
|
||||
|
||||
assert(dokuResult.isSolved());
|
||||
assert (dokuResult.isSolved());
|
||||
|
||||
Solver.solveRandom(dokuToTest, rand);
|
||||
Solver.solveRandom(dokuToTest, rand);
|
||||
|
||||
System.out.println("\n****************************\nDoku solved");
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
|
||||
System.out.println("\n****************************\nDoku solved");
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
|
||||
|
||||
assert (dokuToTest.isSolved());
|
||||
|
||||
assert(dokuToTest.isSolved());
|
||||
for (Cell cell : sudokuToTest.getCells()) {
|
||||
cell.setImmutable();
|
||||
}
|
||||
|
||||
assert(dokuToTest.equals(dokuResult));
|
||||
for (Cell cell : sudokuResult.getCells()) {
|
||||
cell.setImmutable();
|
||||
}
|
||||
|
||||
MultiDoku dokuToTest2 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
Sudoku sudokuToTest2 = dokuToTest2.getSubGrid(0);
|
||||
assertEquals(SudokuSerializer.serializeSudoku(dokuResult).toString(),
|
||||
SudokuSerializer.serializeSudoku(dokuToTest).toString());
|
||||
|
||||
List<Integer> immutableCells2 = List.of(ns, ns, 0, ns, ns, 2, 8, ns, 1,
|
||||
1, 3, ns, ns, 5, 6, 7, ns, ns,
|
||||
ns, ns, ns, 8, ns, 7, ns, ns, 6,
|
||||
0, ns, 1, ns, ns, ns, ns, ns, ns,
|
||||
4, 8, 7, 5, 1, ns, 6, ns, ns,
|
||||
6, ns, 3, 2, ns, ns, ns, 8, 0,
|
||||
ns, ns, 6, ns, ns, 8, ns, 7, 5,
|
||||
8, 0, ns, 7, ns, 5, 2, ns, 3,
|
||||
5, ns, ns, ns, 3, 1, 0, ns, ns);
|
||||
sudokuToTest2.setImmutableCellsSymbol(immutableCells2);
|
||||
MultiDoku dokuToTest2 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
Sudoku sudokuToTest2 = dokuToTest2.getSubGrid(0);
|
||||
|
||||
boolean isSolved = Solver.solveRandom(dokuToTest2, rand);
|
||||
List<Integer> immutableCells2 = List.of(ns, ns, 0, ns, ns, 2, 8, ns, 1,
|
||||
1, 3, ns, ns, 5, 6, 7, ns, ns,
|
||||
ns, ns, ns, 8, ns, 7, ns, ns, 6,
|
||||
0, ns, 1, ns, ns, ns, ns, ns, ns,
|
||||
4, 8, 7, 5, 1, ns, 6, ns, ns,
|
||||
6, ns, 3, 2, ns, ns, ns, 8, 0,
|
||||
ns, ns, 6, ns, ns, 8, ns, 7, 5,
|
||||
8, 0, ns, 7, ns, 5, 2, ns, 3,
|
||||
5, ns, ns, ns, 3, 1, 0, ns, ns);
|
||||
sudokuToTest2.setImmutableCellsSymbol(immutableCells2);
|
||||
|
||||
assert (!isSolved);
|
||||
boolean isSolved = Solver.solveRandom(dokuToTest2, rand);
|
||||
|
||||
MultiDoku dokuToTest3 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
assert (!isSolved);
|
||||
|
||||
Solver.solveRandom(dokuToTest3, rand);
|
||||
MultiDoku dokuToTest3 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest3.getSubGrid(0), 3, 3);
|
||||
}
|
||||
Solver.solveRandom(dokuToTest3, rand);
|
||||
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest3.getSubGrid(0), 3, 3);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user