fix: serialize

This commit is contained in:
2025-01-30 00:51:22 +01:00
committed by Melvyn
parent f1d963e546
commit c4becf2d55
11 changed files with 212 additions and 415 deletions

View File

@@ -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;
}
}

View File

@@ -24,85 +24,57 @@ public class MultiDoku {
}
public MultiDoku clone() {
//TODO: ahhhhhhhhhhhhhhhhhhhhhhh
// TODO: ahhhhhhhhhhhhhhhhhhhhhhh
return SudokuSerializer.deserializeSudoku(SudokuSerializer.serializeSudoku(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 +83,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 +111,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 +126,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 +139,9 @@ public class MultiDoku {
return result;
}
/**
* Vide une Cell donnée.
*
* @param cell Cell, à vider.
*/
public void empty(Cell cell) {
@@ -195,6 +152,7 @@ public class MultiDoku {
/**
* Renvoie le nombre de Cell contenue dans le MultiDoku.
*
* @return int, nombre de Cell dans le MultiDoku.
*/
public int getNbCells() {
@@ -210,4 +168,3 @@ public class MultiDoku {
}
}
}

View File

@@ -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;
}

View File

@@ -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;