package sudoku.structure;
import sudoku.io.SudokuSerializer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @class MultiDoku
* @brief Représente une grille de Multidoku.
* Une grille de sudoku est un multidoku avec un seul sous-sudoku.
*/
public class MultiDoku {
//
/**
* Liste des sous-Sudoku contenue dans le multidoku.
*/
private final List subGrids;
/**
* Pile, qui contient des états du MultiDoku,
* utile pour la résolution.
*/
private final StateManager stateManager;
//
//
public MultiDoku(List subGrids) {
this.subGrids = subGrids;
this.stateManager = new StateManager(this);
}
/**
* Check si le MultiDoku est résolu, c'est à dire complet et cohérent avec ses contraintes.
*
* @return boolean, true s'il est résolu et false sinon.
*/
public boolean isSolved() {
for (Sudoku sudoku : this.subGrids) {
if (!sudoku.isSolved())
return false;
}
return true;
}
/**
* Renvoie la liste des Cells préalablement remplies du MultiDoku.
*
* @return List, vide si aucune Cell n'est remplie.
*/
public List getFilledCells() {
List result = new ArrayList<>();
for (Cell cell : this.getCells()) {
if (!cell.isEmpty()) {
result.add(cell);
}
}
return result;
}
/**
* Renvoie la liste des Cells vides du MultiDoku.
*
* @return List, vide si aucune Cell ne l'est.
*/
public List getEmptyCells() {
List result = new ArrayList<>();
for (Cell cell : this.getCells()) {
if (cell.isEmpty()) {
result.add(cell);
}
}
return result;
}
/**
* 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) {
return cellTmp;
}
}
return null;
}
/**
* Renvoie le nombre de sudoku contenu dans ce MultiDoku.
*
* @return int
*/
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) {
return subGrids.get(i);
}
/**
* Renvoie la liste des Cells contenue dans ce MultiDoku,
* soit les Cells contenues de chaques sous-Sudoku.
*
* @return List
*/
public List getCells() {
Set| cellsSet = new HashSet<>();
for (Sudoku sudoku : subGrids) {
cellsSet.addAll(sudoku.getCells());
}
return new ArrayList<>(cellsSet);
}
/**
* Renvoie le nombre de Cell contenue dans le MultiDoku.
*
* @return int, nombre de Cell dans le MultiDoku.
*/
public int getNbCells() {
return getCells().size();
}
/**
* Change les Cells de ce MultiDoku avec des symboles, en Cells immuables.
*/
public void setFilledCellsImmutable() {
for (Cell filledCell : getFilledCells()) {
filledCell.setImmutable();
}
}
/**
* Vide les Cells modifiable.
*/
public void clearMutableCells() {
for (Sudoku s : getSubGrids()) {
for (Cell cell : s.getCells()) {
if (cell.isMutable())
cell.clearCurrentSymbol();
}
}
}
/**
* Renvoie les sous-Sudoku
*
* @return List
*/
public List getSubGrids() {
return this.subGrids;
}
public StateManager getStateManager() {
return stateManager;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof MultiDoku otherDoku))
return false;
if (this.getNbSubGrids() != otherDoku.getNbSubGrids())
return false;
for (int i = 0; i < this.getNbSubGrids(); i++) {
Sudoku sudoku = this.getSubGrid(i);
Sudoku otherSudoku = otherDoku.getSubGrid(i);
if (sudoku.getSize() != otherSudoku.getSize())
return false;
for (int j = 0; j < sudoku.getSize() * sudoku.getSize(); j++) {
if (sudoku.getCell(i).getSymbolIndex() != otherSudoku.getCell(i).getSymbolIndex())
return false;
}
}
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Multidoku {");
for (Sudoku sudoku : subGrids) {
sb.append("\n\t").append(sudoku.toString());
}
sb.append("\n}");
return sb.toString();
}
public MultiDoku clone() {
// TODO: C'est pas dingue de le faire comme ça...
return SudokuSerializer.deserializeSudoku(SudokuSerializer.serializeSudoku(this));
}
// | | | | | | | | |
}