diff --git a/app/src/main/java/gui/RenderableMultidoku.java b/app/src/main/java/gui/RenderableMultidoku.java new file mode 100644 index 0000000..cf3abab --- /dev/null +++ b/app/src/main/java/gui/RenderableMultidoku.java @@ -0,0 +1,134 @@ +package gui; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import sudoku.structure.Block; +import sudoku.structure.Cell; +import sudoku.structure.Coordinate; +import sudoku.structure.MultiDoku; +import sudoku.structure.Sudoku; + +public class RenderableMultidoku { + + private final List cells; + private final List blocks; + private final int width; + private final int height; + + public RenderableMultidoku(List blocks, List cells, int width, int height) { + this.cells = cells; + this.blocks = blocks; + this.width = width; + this.height = height; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public List getBlocks() { + return this.blocks; + } + + public Cell getCell(int x, int y) { + return getCell(y * width + x); + } + + public Cell getCell(int index) { + return cells.get(index); + } + + public boolean setCellValue(int x, int y, int value) { + return false; + } + + private static record PositionConstraint(Sudoku sudoku1, Sudoku sudoku2, Coordinate offset) { + } + + private static Coordinate getConstraint(Sudoku sudoku1, Sudoku sudoku2) { + for (int i = 0; i < sudoku1.getSize(); i++) { + for (int j = 0; j < sudoku2.getSize(); j++) { + Block block1 = sudoku1.getBlocks().get(i); + Block block2 = sudoku2.getBlocks().get(j); + if (block1 == block2) { + int block1X = 0; + int block1Y = 0; + int block2X = 0; + int block2Y = 0; + return new Coordinate(block1X - block2X, block1Y - block2Y); + } + } + } + return null; + } + + private static boolean hasContraint(Sudoku sudoku1, Sudoku sudoku2, List positionConstraints) { + for (PositionConstraint constraint : positionConstraints) { + if ((constraint.sudoku1 == sudoku1 && constraint.sudoku2 == sudoku2) + || (constraint.sudoku1 == sudoku2 && constraint.sudoku2 == sudoku1)) + return true; + } + return false; + } + + private static Coordinate getMinSudokuOffset(Map sudokusOffset) { + // TODO + return null; + } + + public static RenderableMultidoku fromMultidoku(MultiDoku doku) { + if (doku.getNbSubGrids() == 1) { + Sudoku sudoku = doku.getSubGrid(0); + return new RenderableMultidoku(sudoku.getBlocks(), sudoku.getCells(), sudoku.getSize(), sudoku.getSize()); + } + Map sudokusOffset = new HashMap<>(); + List positionConstraints = new ArrayList<>(); + for (Sudoku sudoku1 : doku.getSubGrids()) { + for (Sudoku sudoku2 : doku.getSubGrids()) { + if (sudoku1 == sudoku2) + continue; + + Coordinate constraint = getConstraint(sudoku1, sudoku2); + + if (constraint != null && !hasContraint(sudoku1, sudoku2, positionConstraints)) { + positionConstraints.add(new PositionConstraint(sudoku1, sudoku2, constraint)); + } + } + } + + for (PositionConstraint constraint : positionConstraints) { + if (!sudokusOffset.containsKey(constraint.sudoku1) && !sudokusOffset.containsKey(constraint.sudoku2)) { + sudokusOffset.put(constraint.sudoku1, new Coordinate(0, 0)); + sudokusOffset.put(constraint.sudoku2, constraint.offset()); + } + + if (sudokusOffset.containsKey(constraint.sudoku1)) { + sudokusOffset.put(constraint.sudoku2, constraint.offset.add(sudokusOffset.get(constraint.sudoku1))); + } else { + sudokusOffset.put(constraint.sudoku1, constraint.offset.add(sudokusOffset.get(constraint.sudoku2))); + } + + } + + Coordinate minCoordinate = getMinSudokuOffset(sudokusOffset); + + for (var entry : sudokusOffset.entrySet()) { + entry.setValue(entry.getValue().sub(minCoordinate)); + } + + List blocks = new ArrayList<>(); + List cells = new ArrayList<>(); + + // TODO: dernière étape + + return new RenderableMultidoku(blocks, cells, 0, 0); + } + +} diff --git a/app/src/main/java/gui/SudokuRenderer.java b/app/src/main/java/gui/SudokuRenderer.java index 1d47e6f..03cfa1b 100644 --- a/app/src/main/java/gui/SudokuRenderer.java +++ b/app/src/main/java/gui/SudokuRenderer.java @@ -13,26 +13,23 @@ import imgui.flag.ImGuiStyleVar; import sudoku.structure.Block; import sudoku.structure.Cell; import sudoku.structure.MultiDoku; -import sudoku.structure.Sudoku; public class SudokuRenderer { - private final MultiDoku doku; - private Sudoku currentSudoku; + private final RenderableMultidoku doku; private int currentIndex = -1; private final Map colorPalette; public SudokuRenderer(MultiDoku doku) { - this.doku = doku; - this.currentSudoku = doku.getSubGrid(0); + this.doku = RenderableMultidoku.fromMultidoku(doku); this.colorPalette = initColors(); } private Map initColors() { - List colors = ColorGenerator.greatPalette(currentSudoku.getSize()); + List colors = ColorGenerator.greatPalette(doku.getBlocks().size()); Map colorPalette = new HashMap<>(); int index = 0; - for (Block block : currentSudoku.getBlocks()) { + for (Block block : doku.getBlocks()) { colorPalette.put(block, colors.get(index)); index++; } @@ -41,12 +38,15 @@ public class SudokuRenderer { private void renderPopup() { if (ImGui.beginPopup("editPopup")) { - for (int i = 1; i < currentSudoku.getSize() + 1; i++) { - if (i % (int) (Math.sqrt(currentSudoku.getSize())) != 1) + Cell cell = doku.getCell(currentIndex); + Block block = cell.getBlock(); + int symbolCount = block.getCells().size(); + for (int i = 1; i < symbolCount + 1; i++) { + if (i % (int) (Math.sqrt(symbolCount)) != 1) ImGui.sameLine(); if (ImGui.button(Integer.toString(i), new ImVec2(50, 50))) { - this.currentSudoku.setCellSymbol(currentIndex % currentSudoku.getSize(), - currentIndex / currentSudoku.getSize(), i - 1); + this.doku.setCellValue(currentIndex % symbolCount, + currentIndex / symbolCount, i - 1); ImGui.closeCurrentPopup(); } } @@ -58,21 +58,26 @@ public class SudokuRenderer { ImGui.pushStyleVar(ImGuiStyleVar.FrameBorderSize, 2.0f); ImGui.pushStyleVar(ImGuiStyleVar.ItemSpacing, new ImVec2(0.0f, 0.0f)); ImGui.pushStyleColor(ImGuiCol.Border, new ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); - for (int y = 0; y < currentSudoku.getSize(); y++) { - for (int x = 0; x < currentSudoku.getSize(); x++) { + for (int y = 0; y < doku.getHeight(); y++) { + for (int x = 0; x < doku.getWidth(); x++) { if (x > 0) ImGui.sameLine(); - int index = y * currentSudoku.getSize() + x; - Cell cell = currentSudoku.getCell(x, y); - int symbol = cell.getSymbolIndex(); - Color blockColor = colorPalette.get(cell.getBlock()); - ImGui.pushStyleColor(ImGuiCol.Button, new ImVec4(blockColor.r, blockColor.g, blockColor.b, 1.0f)); - String cellText = ""; - if (symbol != -1) - cellText += Integer.toString(symbol + 1); - if (ImGui.button(cellText + "##" + index, new ImVec2(50, 50))) { - ImGui.openPopup("editPopup"); - currentIndex = index; + int index = y * doku.getWidth() + x; + Cell cell = doku.getCell(x, y); + if (cell == null) { + ImGui.pushStyleColor(ImGuiCol.Button, new ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImGui.button("##" + index, new ImVec2(50, 50)); + } else { + int symbol = cell.getSymbolIndex(); + Color blockColor = colorPalette.get(cell.getBlock()); + ImGui.pushStyleColor(ImGuiCol.Button, new ImVec4(blockColor.r, blockColor.g, blockColor.b, 1.0f)); + String cellText = ""; + if (symbol != -1) + cellText += Integer.toString(symbol + 1); + if (ImGui.button(cellText + "##" + index, new ImVec2(50, 50))) { + ImGui.openPopup("editPopup"); + currentIndex = index; + } } ImGui.popStyleColor(); } diff --git a/app/src/main/java/sudoku/structure/Block.java b/app/src/main/java/sudoku/structure/Block.java index cf76f72..2fe28d4 100644 --- a/app/src/main/java/sudoku/structure/Block.java +++ b/app/src/main/java/sudoku/structure/Block.java @@ -7,6 +7,9 @@ public class Block { private final List cells; + // faster access to the sudoku + private List sudokus; + public Block(List cells) { this.cells = cells; } @@ -39,4 +42,12 @@ public class Block { } return false; } + + public List getSudokus() { + return sudokus; + } + + void setSudokus(List sudokus) { + this.sudokus = sudokus; + } } diff --git a/app/src/main/java/sudoku/structure/Coordinate.java b/app/src/main/java/sudoku/structure/Coordinate.java index bef337a..90164ff 100644 --- a/app/src/main/java/sudoku/structure/Coordinate.java +++ b/app/src/main/java/sudoku/structure/Coordinate.java @@ -30,4 +30,12 @@ public class Coordinate { return this.y * size + this.x; } + public Coordinate add(Coordinate other) { + return new Coordinate(this.x + other.x, this.y + other.y); + } + + public Coordinate sub(Coordinate other) { + return new Coordinate(this.x - other.x, this.y - other.y); + } + } diff --git a/app/src/main/java/sudoku/structure/Sudoku.java b/app/src/main/java/sudoku/structure/Sudoku.java index 8d88bde..854522c 100644 --- a/app/src/main/java/sudoku/structure/Sudoku.java +++ b/app/src/main/java/sudoku/structure/Sudoku.java @@ -15,6 +15,7 @@ public class Sudoku { private final List cells; private final List constraints; private boolean isMutable; + private int blockWidth; public Sudoku(List cells, List blocks, List constraints) { this.cells = cells; @@ -23,7 +24,7 @@ public class Sudoku { } public int[] toCoords(int index) { - return new int[]{index % getSize(), index / getSize()}; + return new int[] { index % getSize(), index / getSize() }; } public int toIndex(int x, int y) { @@ -71,6 +72,10 @@ public class Sudoku { } } + public int getBlockWidth() { + return blockWidth; + } + /** * Try to place a cell at the given coordinate * @@ -162,6 +167,8 @@ public class Sudoku { 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);