diff --git a/app/src/main/java/gui/RenderableMultidoku.java b/app/src/main/java/gui/RenderableMultidoku.java index 7b1dc16..aa4350f 100644 --- a/app/src/main/java/gui/RenderableMultidoku.java +++ b/app/src/main/java/gui/RenderableMultidoku.java @@ -13,16 +13,18 @@ import sudoku.structure.Sudoku; public class RenderableMultidoku { + private final MultiDoku doku; 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) { + private RenderableMultidoku(MultiDoku doku, List blocks, List cells, int width, int height) { this.cells = cells; this.blocks = blocks; this.width = width; this.height = height; + this.doku = doku; } public int getWidth() { @@ -45,24 +47,39 @@ public class RenderableMultidoku { return cells.get(index); } - public boolean setCellValue(int x, int y, int value) { - return false; + public boolean setCellValue(Cell cell, int value) { + // TODO: fix constraints + // for (Sudoku s : doku.getSubGrids()) { + // int cellIndex = s.getCells().indexOf(cell); + // // la cellule existe + // if (cellIndex != -1) { + // int cellX = cellIndex % s.getSize(); + // int cellY = cellIndex / s.getSize(); + // if (s.canBePlaced(cellX, cellY, value)) { + // return false; + // } + // } + // } + cell.setSymbolIndex(value); + return true; } private static record PositionConstraint(Sudoku sudoku1, Sudoku sudoku2, Coordinate offset) { } private static Coordinate getConstraint(Sudoku sudoku1, Sudoku sudoku2) { + int blockWidth = sudoku1.getBlockWidth(); + int blockHeight = sudoku1.getSize() / blockWidth; 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); + int block1X = i % blockHeight; + int block1Y = i / blockHeight; + int block2X = j % blockHeight; + int block2Y = j / blockHeight; + return new Coordinate((block1X - block2X) * blockWidth, (block1Y - block2Y) * blockHeight); } } } @@ -111,15 +128,16 @@ public class RenderableMultidoku { int blockWidth = maxSudoku.getBlockWidth(); int blockHeight = maxSudoku.getSize() / blockWidth; - return new Coordinate((maxCoordinate.getX() + blockHeight) * blockWidth, (maxCoordinate.getY() + blockWidth) * blockHeight); + return new Coordinate(maxCoordinate.getX() + maxSudoku.getSize(), maxCoordinate.getY() + maxSudoku.getSize()); } 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()); + return new RenderableMultidoku(doku, sudoku.getBlocks(), sudoku.getCells(), sudoku.getSize(), sudoku.getSize()); } Map sudokusOffset = new HashMap<>(); + // coordinates in cell List positionConstraints = new ArrayList<>(); for (Sudoku sudoku1 : doku.getSubGrids()) { for (Sudoku sudoku2 : doku.getSubGrids()) { @@ -154,24 +172,35 @@ public class RenderableMultidoku { entry.setValue(entry.getValue().sub(minCoordinate)); } - List blocks = new ArrayList<>(); - List cells = new ArrayList<>(); + Coordinate maxCoordinate = getMaxSudokuCoordinate(sudokusOffset); + + List blocks = new ArrayList<>(); + List cells = new ArrayList<>(maxCoordinate.getX() * maxCoordinate.getY()); + for (int i = 0; i < maxCoordinate.getX() * maxCoordinate.getY(); i++) { + cells.add(null); + } + + for (var entry : sudokusOffset.entrySet()) { + Sudoku sudoku = entry.getKey(); + Coordinate offset = entry.getValue(); + + for (int x = 0; x < sudoku.getSize(); x++) { + for (int y = 0; y < sudoku.getSize(); y++) { + Cell cell = sudoku.getCell(x, y); + int absoluteX = x + offset.getX(); + int absoluteY = y + offset.getY(); + cells.set(absoluteY * maxCoordinate.getX() + absoluteX, cell); + } + } - for (Sudoku sudoku : doku.getSubGrids()) { for (Block block : sudoku.getBlocks()) { if (!blocks.contains(block)) { blocks.add(block); } } - for (Cell cell : sudoku.getCells()) { - if (!cells.contains(cell)) - cells.add(cell); - } } - Coordinate maxCoordinate = getMaxSudokuCoordinate(sudokusOffset); - - return new RenderableMultidoku(blocks, cells, maxCoordinate.getX(), maxCoordinate.getY()); + return new RenderableMultidoku(doku, blocks, cells, maxCoordinate.getX(), maxCoordinate.getY()); } } diff --git a/app/src/main/java/gui/SudokuRenderer.java b/app/src/main/java/gui/SudokuRenderer.java index 03cfa1b..525d476 100644 --- a/app/src/main/java/gui/SudokuRenderer.java +++ b/app/src/main/java/gui/SudokuRenderer.java @@ -17,7 +17,7 @@ import sudoku.structure.MultiDoku; public class SudokuRenderer { private final RenderableMultidoku doku; - private int currentIndex = -1; + private Cell currentCell = null; private final Map colorPalette; public SudokuRenderer(MultiDoku doku) { @@ -38,15 +38,13 @@ public class SudokuRenderer { private void renderPopup() { if (ImGui.beginPopup("editPopup")) { - Cell cell = doku.getCell(currentIndex); - Block block = cell.getBlock(); + Block block = currentCell.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.doku.setCellValue(currentIndex % symbolCount, - currentIndex / symbolCount, i - 1); + this.doku.setCellValue(currentCell, i - 1); ImGui.closeCurrentPopup(); } } @@ -76,7 +74,7 @@ public class SudokuRenderer { cellText += Integer.toString(symbol + 1); if (ImGui.button(cellText + "##" + index, new ImVec2(50, 50))) { ImGui.openPopup("editPopup"); - currentIndex = index; + currentCell = cell; } } ImGui.popStyleColor(); diff --git a/app/src/main/java/gui/menu/MultiPlayerView.java b/app/src/main/java/gui/menu/MultiPlayerView.java index dd42809..0f3acf0 100644 --- a/app/src/main/java/gui/menu/MultiPlayerView.java +++ b/app/src/main/java/gui/menu/MultiPlayerView.java @@ -36,7 +36,7 @@ public class MultiPlayerView extends BaseView { } else { if (ImGui.button("Démarrer")) { // temp - MultiDoku doku = SudokuFactory.createBasicEmptySquareSudoku(5); + MultiDoku doku = SudokuFactory.createBasicSquareMultidoku(3); this.server.startGame(doku); } } diff --git a/app/src/main/java/sudoku/io/SudokuSerializer.java b/app/src/main/java/sudoku/io/SudokuSerializer.java index d930d6d..3cceebf 100644 --- a/app/src/main/java/sudoku/io/SudokuSerializer.java +++ b/app/src/main/java/sudoku/io/SudokuSerializer.java @@ -88,6 +88,7 @@ public class SudokuSerializer { jsonSudoku.put("cells", cellsJsonArray); jsonSudoku.put("blocks", blocksJsonArray); + jsonSudoku.put("blockWidth", sudoku.getBlockWidth()); jsonSudokus.put(i, jsonSudoku); } @@ -151,7 +152,9 @@ public class SudokuSerializer { sudokuBlocks.add(blocks.get(blockID)); } - sudokus.add(new Sudoku(sudokuCells, sudokuBlocks, null)); + Sudoku s = new Sudoku(sudokuCells, sudokuBlocks, null); + s.setBlockWidth(sudokuJsonObject.getInt("blockWidth")); + sudokus.add(s); } return new MultiDoku(sudokus); diff --git a/app/src/main/java/sudoku/structure/Sudoku.java b/app/src/main/java/sudoku/structure/Sudoku.java index 854522c..a4eb697 100644 --- a/app/src/main/java/sudoku/structure/Sudoku.java +++ b/app/src/main/java/sudoku/structure/Sudoku.java @@ -46,13 +46,19 @@ public class Sudoku { return index < getSize() * getSize(); } - public boolean tryPlaceCellSymbol(int x, int y, int value) { - assert (isValidCoords(x, y)); + public boolean canBePlaced(int x, int y, int value) { for (IConstraint constraint : this.constraints) { if (!constraint.canBePlaced(this, x, y, value)) { return false; } } + return true; + } + + 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; @@ -293,4 +299,9 @@ public class Sudoku { return true; } + + public void setBlockWidth(int blockWidth) { + this.blockWidth = blockWidth; + } + } diff --git a/app/src/main/java/sudoku/structure/SudokuFactory.java b/app/src/main/java/sudoku/structure/SudokuFactory.java index f235c7a..cb2c560 100644 --- a/app/src/main/java/sudoku/structure/SudokuFactory.java +++ b/app/src/main/java/sudoku/structure/SudokuFactory.java @@ -1,17 +1,19 @@ package sudoku.structure; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + import sudoku.constraint.BlockConstraint; import sudoku.constraint.ColumnConstraint; import sudoku.constraint.IConstraint; import sudoku.constraint.LineConstraint; -import sudoku.structure.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; public class SudokuFactory { + private static List DEFAULT_CONSTRAINTS = Arrays.asList(new BlockConstraint(), new LineConstraint(), new ColumnConstraint()); + private static List initCells(int size) { List cells = new ArrayList<>(size * size); for (int i = 0; i < size * size; i++) { @@ -44,17 +46,8 @@ public class SudokuFactory { } public static MultiDoku createBasicEmptyRectangleSudoku(int widthBlock, int heightBlock) { - int symbolCount = widthBlock * heightBlock; - List cases = initCells(symbolCount); - 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); + Sudoku s = createRectangleSudoku(widthBlock, heightBlock); + return new MultiDoku(Arrays.asList(s)); } public static MultiDoku createBasicEmptySquareSudoku(int size) { @@ -72,4 +65,70 @@ public class SudokuFactory { } }); } + + private static Sudoku createRectangleSudoku(int width, int height) { + int symbolCount = width * height; + List cases = initCells(symbolCount); + List blocs = initRectangleBlocs(cases, width, height); + Sudoku s = new Sudoku(cases, blocs, DEFAULT_CONSTRAINTS); + s.setBlockWidth(width); + return s; + } + + private static Sudoku createSquareSudoku(int size) { + return createRectangleSudoku(size, size); + } + + private static void linkSquareSudokus(Sudoku sudoku1, Sudoku sudoku2, Coordinate offset) { + int blockWidth = sudoku1.getBlockWidth(); + for (int dx = 0; dx < blockWidth; dx++) { + for (int dy = 0; dy < blockWidth; dy++) { + int block1X = dx + offset.getX(); + int block1Y = dy + offset.getY(); + int block2X = dx; + int block2Y = dy; + + if ((block1X < blockWidth) && (block1X >= 0) && (block1Y >= 0) && (block1Y < blockWidth)) { + Block block1 = sudoku1.getBlocks().get(block1Y * blockWidth + block1X); + Block block2 = sudoku2.getBlocks().get(block2Y * blockWidth + block2X); + + // on remplace le bloc + sudoku2.getBlocks().set(block2Y * blockWidth + block2X, block1); + + // on remplace les cellules + for (int i = 0; i < block1.getCells().size(); i++) { + Cell newCell = block1.getCells().get(i); + Cell oldCell = block2.getCells().get(i); + + int oldCellIndex = sudoku2.getCells().indexOf(oldCell); + sudoku2.getCells().set(oldCellIndex, newCell); + } + } + } + } + } + + public static MultiDoku createBasicSquareMultidoku(int size) { + assert (size > 1); + + /** + * 2 3 + * 1 + * 4 5 + */ + + Sudoku sudoku1 = createSquareSudoku(size); + + Sudoku sudoku2 = createSquareSudoku(size); + Sudoku sudoku3 = createSquareSudoku(size); + Sudoku sudoku4 = createSquareSudoku(size); + Sudoku sudoku5 = createSquareSudoku(size); + + linkSquareSudokus(sudoku1, sudoku2, new Coordinate(1 - size, 1 - size)); + linkSquareSudokus(sudoku1, sudoku3, new Coordinate(size - 1, 1 - size)); + linkSquareSudokus(sudoku1, sudoku4, new Coordinate(1 - size, size - 1)); + linkSquareSudokus(sudoku1, sudoku5, new Coordinate(size - 1, size - 1)); + + return new MultiDoku(Arrays.asList(sudoku1, sudoku2, sudoku3, sudoku4, sudoku5)); + } }