200 lines
4.3 KiB
Java
200 lines
4.3 KiB
Java
package sudoku.structure;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Random;
|
|
import java.util.Set;
|
|
|
|
import sudoku.io.SudokuSerializer;
|
|
|
|
/**
|
|
* @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<Sudoku> subGrids;
|
|
|
|
private final StateManager stateManager;
|
|
|
|
public MultiDoku(List<Sudoku> subGrids) {
|
|
this.subGrids = subGrids;
|
|
this.stateManager = new StateManager(this);
|
|
}
|
|
|
|
/**
|
|
* 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<Cell>
|
|
*/
|
|
public List<Cell> getCells() {
|
|
Set<Cell> cellsSet = new HashSet<>();
|
|
for (Sudoku sudoku : subGrids) {
|
|
cellsSet.addAll(sudoku.getCells());
|
|
}
|
|
return new ArrayList<>(cellsSet);
|
|
}
|
|
|
|
@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();
|
|
}
|
|
|
|
/**
|
|
* Renvoie les sous-Sudoku
|
|
*
|
|
* @return List<Sudoku>
|
|
*/
|
|
public List<Sudoku> getSubGrids() {
|
|
return this.subGrids;
|
|
}
|
|
|
|
/**
|
|
* 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 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 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()) {
|
|
if (!cell.isEmpty()) {
|
|
result.add(cell);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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()) {
|
|
if (cell.isEmpty()) {
|
|
result.add(cell);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Vide une Cell donnée.
|
|
*
|
|
* @param cell Cell, à vider.
|
|
*/
|
|
public void empty(Cell cell) {
|
|
List<Cell> cells = getCells();
|
|
Cell cellToEmpty = cells.get(cells.indexOf(cell));
|
|
cellToEmpty.setSymbolIndex(Cell.NOSYMBOL);
|
|
}
|
|
|
|
/**
|
|
* 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();
|
|
}
|
|
}
|
|
|
|
public StateManager getStateManager() {
|
|
return stateManager;
|
|
}
|
|
|
|
/**
|
|
* Renvoie une Cell vide choisie aléatoirement.
|
|
*
|
|
* @param rand Random, pour le choix aléatoire.
|
|
* @return Cell, une Cell vide.
|
|
*/
|
|
public Cell getRandomEmptyCell(Random rand) {
|
|
List<Cell> emptyCells = getEmptyCells();
|
|
int randomIndex = rand.nextInt(emptyCells.size());
|
|
return emptyCells.get(randomIndex);
|
|
}
|
|
|
|
public void clearMutableCells() {
|
|
for (Sudoku s : getSubGrids()) {
|
|
for (Cell cell : s.getCells()) {
|
|
if (cell.isMutable())
|
|
cell.clearCurrentSymbol();
|
|
}
|
|
}
|
|
}
|
|
|
|
public MultiDoku clone() {
|
|
// TODO: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah
|
|
return SudokuSerializer.deserializeSudoku(SudokuSerializer.serializeSudoku(this));
|
|
}
|
|
}
|