diff --git a/app/src/main/java/sudoku/Cell.java b/app/src/main/java/sudoku/Cell.java index c7088a4..674e8f3 100644 --- a/app/src/main/java/sudoku/Cell.java +++ b/app/src/main/java/sudoku/Cell.java @@ -3,11 +3,11 @@ package sudoku; public abstract class Cell { protected static int NOSYMBOLE = -1; - protected int symboleIndex; + protected int symbolIndex; protected Block block = null; - public Cell(int symboleIndex) { - this.symboleIndex = symboleIndex; + public Cell(int symbolIndex) { + this.symbolIndex = symbolIndex; } /** @@ -17,8 +17,8 @@ public abstract class Cell { this(NOSYMBOLE); } - public int getSymboleIndex() { - return symboleIndex; + public int getSymbolIndex() { + return symbolIndex; } public Block getBlock() { @@ -33,7 +33,23 @@ public abstract class Cell { @Override public boolean equals(Object obj) { if (obj instanceof Cell otherCell) - return otherCell.getSymboleIndex() == this.getSymboleIndex(); + return otherCell.getSymbolIndex() == this.getSymbolIndex(); return false; } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("| "); + if (this.symbolIndex != NOSYMBOLE){ + sb.append(this.symbolIndex); + } + else { + sb.append(" "); + } + + sb.append(" |"); + return sb.toString(); + } + } diff --git a/app/src/main/java/sudoku/Coordinate.java b/app/src/main/java/sudoku/Coordinate.java new file mode 100644 index 0000000..668dd85 --- /dev/null +++ b/app/src/main/java/sudoku/Coordinate.java @@ -0,0 +1,33 @@ +package sudoku; + +public class Coordinate { + + private int x; + private int y; + + public Coordinate(int row, int col) { + this.x = row; + this.y = col; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + public int calculateIndex(int size) { + return this.y * size + this.x; + } + +} diff --git a/app/src/main/java/sudoku/MultiDoku.java b/app/src/main/java/sudoku/MultiDoku.java index 1e3a4e5..956f076 100644 --- a/app/src/main/java/sudoku/MultiDoku.java +++ b/app/src/main/java/sudoku/MultiDoku.java @@ -42,4 +42,20 @@ public class MultiDoku { return mutableCells; } + public void updateSymbolsPossibilities() throws Exception { + for (Sudoku sudoku : subGrids){ + sudoku.updateSymbolsPossibilities(); + } + } + + @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(); + } } diff --git a/app/src/main/java/sudoku/MutableCell.java b/app/src/main/java/sudoku/MutableCell.java index ab99658..7994627 100644 --- a/app/src/main/java/sudoku/MutableCell.java +++ b/app/src/main/java/sudoku/MutableCell.java @@ -5,33 +5,38 @@ import java.util.List; public class MutableCell extends Cell{ - private final List hintsSymbolIndex; + private final List possibleSymbols; public MutableCell() { super(); - this.hintsSymbolIndex = new ArrayList<>(); + this.possibleSymbols = new ArrayList<>(); } - public MutableCell(int symboleIndex) { - super(symboleIndex); - this.hintsSymbolIndex = new ArrayList<>(); + public MutableCell(int symbolIndex) { + super(symbolIndex); + this.possibleSymbols = new ArrayList<>(); } - public void setSymboleIndex(int symboleIndex) { - this.symboleIndex = symboleIndex; + public void setSymbolIndex(int symbolIndex) { + this.symbolIndex = symbolIndex; } - public void clear() { - setSymboleIndex(NOSYMBOLE); + /** + * Remove the current symbolIndex and returns it + * @return integer symbolIndex cleared + */ + public int clearCurrentSymbol() { + int i = this.symbolIndex; + setSymbolIndex(NOSYMBOLE); + return i; } - public void clear(int indexSymbol) { - hintsSymbolIndex.remove(indexSymbol); - this.clear(); + public void removeSymbolFromPossibilities(int indexSymbol) { + possibleSymbols.remove(indexSymbol); } - public List getHints() { - return this.hintsSymbolIndex; + public List getPossibleSymbols() { + return this.possibleSymbols; } } diff --git a/app/src/main/java/sudoku/Sudoku.java b/app/src/main/java/sudoku/Sudoku.java index 3b60963..80ab687 100644 --- a/app/src/main/java/sudoku/Sudoku.java +++ b/app/src/main/java/sudoku/Sudoku.java @@ -14,10 +14,12 @@ public class Sudoku { private final List blocks; private final List cells; + private final List constraints; - public Sudoku(List cells, List blocks) { + public Sudoku(List cells, List blocks, List constraints) { this.cells = cells; this.blocks = blocks; + this.constraints = new ArrayList<>(constraints); } public Cell getCell(int x, int y) { @@ -30,6 +32,10 @@ public class Sudoku { return this.cells.get(i); } + public List getConstraints() { + return constraints; + } + public int getSize() { return this.blocks.size(); } @@ -49,4 +55,64 @@ public class Sudoku { } return mutableCells; } + + public boolean contains(Cell cell) { + return this.cells.contains(cell); + } + + 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."); + } + + 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); + } + + public void updateSymbolsPossibilities() throws Exception { + for (IConstraint constraint : constraints) { + List mutableCells = this.getMutableCells(); + for (MutableCell cell : mutableCells) { + Coordinate coord = null; + try { + coord = this.getCoordinateCell(cell); + } catch (Exception e) { + throw new RuntimeException(e); + } + constraint.getPossibleSymbols(this, coord.getX(), coord.getY()); + if (cell.getPossibleSymbols().isEmpty()){ + throw new Exception("Rollback bitch"); + } + } + } + } + + public String toString (){ + StringBuilder sb = new StringBuilder(); + sb.append("Sudoku {"); + for (int i = 0; i < getSize(); i++) { + sb.append("\n\t"); + for (int j = 0; j < getSize(); j++) { + Cell cell = getCell(i, j); + sb.append(cell.toString()).append(" "); + } + } + sb.append("\n}"); + return sb.toString(); + } + } diff --git a/app/src/main/java/sudoku/SudokuFactory.java b/app/src/main/java/sudoku/SudokuFactory.java index dde6f27..dfb0222 100644 --- a/app/src/main/java/sudoku/SudokuFactory.java +++ b/app/src/main/java/sudoku/SudokuFactory.java @@ -1,5 +1,10 @@ package sudoku; +import sudoku.constraint.BlockConstraint; +import sudoku.constraint.ColumnConstraint; +import sudoku.constraint.IConstraint; +import sudoku.constraint.LineConstraint; + import java.util.ArrayList; import java.util.List; @@ -33,14 +38,18 @@ public class SudokuFactory { return blocs; } - public static MultiDoku createBasicEmptyRectangleSudoku(int width, int height) { - int symbolCount = width * height; + public static MultiDoku createBasicEmptyRectangleSudoku(int widthBlock, int heightBlock) { + int symbolCount = widthBlock * heightBlock; List cases = initCells(symbolCount); - List blocs = initRectangleBlocs(cases, width, height); - Sudoku s = new Sudoku(cases, blocs); - List ss = new ArrayList<>(); - ss.add(s); - return new MultiDoku(ss); + List blocs = initRectangleBlocs(cases, widthBlock, heightBlock); + List constraints = new ArrayList<>(); + constraints.add(new ColumnConstraint()); + constraints.add(new LineConstraint()); + constraints.add(new BlockConstraint()); + Sudoku s = new Sudoku(cases, blocs, constraints); + List subSudoku = new ArrayList<>(); + subSudoku.add(s); + return new MultiDoku(subSudoku); } public static MultiDoku createBasicEmptySquareSudoku(int size) { diff --git a/app/src/main/java/sudoku/constraint/BlockConstraint.java b/app/src/main/java/sudoku/constraint/BlockConstraint.java index a600a99..a0fe7c5 100644 --- a/app/src/main/java/sudoku/constraint/BlockConstraint.java +++ b/app/src/main/java/sudoku/constraint/BlockConstraint.java @@ -2,6 +2,7 @@ package sudoku.constraint; import sudoku.Block; import sudoku.Cell; +import sudoku.MutableCell; import sudoku.Sudoku; public class BlockConstraint implements IConstraint{ @@ -9,7 +10,7 @@ public class BlockConstraint implements IConstraint{ @Override public boolean canBePlaced(final Sudoku s, int x, int y, int newSymbolIndex) { Block bloc = s.getCell(x, y).getBlock(); - return !bloc.getCells().contains(new Cell(newSymbolIndex) {}); + return !bloc.getCells().contains(new MutableCell(newSymbolIndex)); } } diff --git a/app/src/main/java/sudoku/constraint/ColumnConstraint.java b/app/src/main/java/sudoku/constraint/ColumnConstraint.java index 4c74ef2..881faab 100644 --- a/app/src/main/java/sudoku/constraint/ColumnConstraint.java +++ b/app/src/main/java/sudoku/constraint/ColumnConstraint.java @@ -7,7 +7,7 @@ public class ColumnConstraint implements IConstraint { @Override public boolean canBePlaced(final Sudoku s, int x, int y, int newSymbolIndex) { for (int i = 0; i < s.getSize(); i++) { - if (s.getCell(x, newSymbolIndex).getSymboleIndex() == newSymbolIndex) + if (s.getCell(x, newSymbolIndex).getSymbolIndex() == newSymbolIndex) return false; } return true; diff --git a/app/src/main/java/sudoku/constraint/LineConstraint.java b/app/src/main/java/sudoku/constraint/LineConstraint.java index 8837229..2f9a81e 100644 --- a/app/src/main/java/sudoku/constraint/LineConstraint.java +++ b/app/src/main/java/sudoku/constraint/LineConstraint.java @@ -7,7 +7,7 @@ public class LineConstraint implements IConstraint { @Override public boolean canBePlaced(final Sudoku s, int x, int y, int newSymbolIndex) { for (int i = 0; i < s.getSize(); i++) { - if (s.getCell(newSymbolIndex, y).getSymboleIndex() == newSymbolIndex) + if (s.getCell(newSymbolIndex, y).getSymbolIndex() == newSymbolIndex) return false; } return true; diff --git a/app/src/main/java/sudoku/solver/Solver.java b/app/src/main/java/sudoku/solver/Solver.java index 9f4376f..b87425c 100644 --- a/app/src/main/java/sudoku/solver/Solver.java +++ b/app/src/main/java/sudoku/solver/Solver.java @@ -1,17 +1,16 @@ package sudoku.solver; -import sudoku.Cell; import sudoku.MultiDoku; import sudoku.MutableCell; -import sudoku.Sudoku; import sudoku.constraint.IConstraint; import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.Stack; public class Solver { - Caretaker stack; + Stack stack; public Solver() { } @@ -26,12 +25,26 @@ public class Solver { while (!remainingCellsToCheck.isEmpty()) { int indexCurrentCell = rand.nextInt(remainingCellsToCheck.size()); MutableCell currentCell = remainingCellsToCheck.get(indexCurrentCell); - if (currentCell.getHints().isEmpty()){ - MutableCell modify = allMutableCells.get(stack.undo()); - modify.clear(modify.getSymboleIndex()); + if (currentCell.getPossibleSymbols().isEmpty()){ + MutableCell modify = stack.pop(); + modify.removeSymbolFromPossibilities(modify.clearCurrentSymbol()); + } else { + int symbol = currentCell.getPossibleSymbols().get(0); + currentCell.setSymbolIndex(symbol); + stack.push(currentCell); + try { + doku.updateSymbolsPossibilities(); + } catch (Exception e) { + //TODO rollback + } + //TODO check constraints integrity in sudoku + + } + + remainingCellsToCheck.remove(indexCurrentCell); } return doku;