Compare commits
5 Commits
4c02be3d39
...
0174ec08d7
| Author | SHA1 | Date | |
|---|---|---|---|
| 0174ec08d7 | |||
| c7d3430d21 | |||
| 182f79d4b4 | |||
| e9a77d9826 | |||
| 3a0279afe3 |
211
app/src/main/java/gui/RenderableMultidoku.java
Normal file
211
app/src/main/java/gui/RenderableMultidoku.java
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
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 MultiDoku doku;
|
||||||
|
private final List<Cell> cells;
|
||||||
|
private final List<Block> blocks;
|
||||||
|
private final int width;
|
||||||
|
private final int height;
|
||||||
|
|
||||||
|
private RenderableMultidoku(MultiDoku doku, List<Block> blocks, List<Cell> cells, int width, int height) {
|
||||||
|
this.cells = cells;
|
||||||
|
this.blocks = blocks;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.doku = doku;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Block> 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(Cell cell, int value) {
|
||||||
|
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 = i % blockHeight;
|
||||||
|
int block1Y = i / blockHeight;
|
||||||
|
int block2X = j % blockHeight;
|
||||||
|
int block2Y = j / blockHeight;
|
||||||
|
return new Coordinate((block1X - block2X) * blockWidth, (block1Y - block2Y) * blockHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasContraint(Sudoku sudoku1, Sudoku sudoku2, List<PositionConstraint> 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<Sudoku, Coordinate> sudokusOffset) {
|
||||||
|
Coordinate minCoordinate = null;
|
||||||
|
for (Coordinate coordinate : sudokusOffset.values()) {
|
||||||
|
if (minCoordinate == null)
|
||||||
|
minCoordinate = coordinate;
|
||||||
|
minCoordinate = new Coordinate(Math.min(minCoordinate.getX(), coordinate.getX()),
|
||||||
|
Math.min(minCoordinate.getY(), coordinate.getY()));
|
||||||
|
}
|
||||||
|
return minCoordinate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Coordinate getMaxSudokuCoordinate(Map<Sudoku, Coordinate> sudokusOffset) {
|
||||||
|
Coordinate maxCoordinate = null;
|
||||||
|
Sudoku maxSudoku = null;
|
||||||
|
float maxDistanceSquared = 0;
|
||||||
|
for (var entry : sudokusOffset.entrySet()) {
|
||||||
|
Coordinate coordinate = entry.getValue();
|
||||||
|
float distanceSquared = coordinate.getX() * coordinate.getX() + coordinate.getY() * coordinate.getY();
|
||||||
|
if (maxCoordinate == null) {
|
||||||
|
maxCoordinate = coordinate;
|
||||||
|
maxDistanceSquared = distanceSquared;
|
||||||
|
maxSudoku = entry.getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distanceSquared > maxDistanceSquared) {
|
||||||
|
maxDistanceSquared = distanceSquared;
|
||||||
|
maxSudoku = entry.getKey();
|
||||||
|
maxCoordinate = coordinate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int blockWidth = maxSudoku.getBlockWidth();
|
||||||
|
int blockHeight = maxSudoku.getSize() / blockWidth;
|
||||||
|
|
||||||
|
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(doku, sudoku.getBlocks(), sudoku.getCells(), sudoku.getSize(),
|
||||||
|
sudoku.getSize());
|
||||||
|
}
|
||||||
|
Map<Sudoku, Coordinate> sudokusOffset = new HashMap<>();
|
||||||
|
// coordinates in cell
|
||||||
|
List<PositionConstraint> 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
Coordinate maxCoordinate = getMaxSudokuCoordinate(sudokusOffset);
|
||||||
|
|
||||||
|
List<Block> blocks = new ArrayList<>();
|
||||||
|
List<Cell> 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 (Block block : sudoku.getBlocks()) {
|
||||||
|
if (!blocks.contains(block)) {
|
||||||
|
blocks.add(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RenderableMultidoku(doku, blocks, cells, maxCoordinate.getX(), maxCoordinate.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiDoku getDoku() {
|
||||||
|
return doku;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,26 +13,23 @@ import imgui.flag.ImGuiStyleVar;
|
|||||||
import sudoku.structure.Block;
|
import sudoku.structure.Block;
|
||||||
import sudoku.structure.Cell;
|
import sudoku.structure.Cell;
|
||||||
import sudoku.structure.MultiDoku;
|
import sudoku.structure.MultiDoku;
|
||||||
import sudoku.structure.Sudoku;
|
|
||||||
|
|
||||||
public class SudokuRenderer {
|
public class SudokuRenderer {
|
||||||
|
|
||||||
private final MultiDoku doku;
|
private final RenderableMultidoku doku;
|
||||||
private Sudoku currentSudoku;
|
private Cell currentCell = null;
|
||||||
private int currentIndex = -1;
|
|
||||||
private final Map<Block, Color> colorPalette;
|
private final Map<Block, Color> colorPalette;
|
||||||
|
|
||||||
public SudokuRenderer(MultiDoku doku) {
|
public SudokuRenderer(MultiDoku doku) {
|
||||||
this.doku = doku;
|
this.doku = RenderableMultidoku.fromMultidoku(doku);
|
||||||
this.currentSudoku = doku.getSubGrid(0);
|
|
||||||
this.colorPalette = initColors();
|
this.colorPalette = initColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Block, Color> initColors() {
|
private Map<Block, Color> initColors() {
|
||||||
List<Color> colors = ColorGenerator.greatPalette(currentSudoku.getSize());
|
List<Color> colors = ColorGenerator.greatPalette(doku.getBlocks().size());
|
||||||
Map<Block, Color> colorPalette = new HashMap<>();
|
Map<Block, Color> colorPalette = new HashMap<>();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (Block block : currentSudoku.getBlocks()) {
|
for (Block block : doku.getBlocks()) {
|
||||||
colorPalette.put(block, colors.get(index));
|
colorPalette.put(block, colors.get(index));
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -41,12 +38,13 @@ public class SudokuRenderer {
|
|||||||
|
|
||||||
private void renderPopup() {
|
private void renderPopup() {
|
||||||
if (ImGui.beginPopup("editPopup")) {
|
if (ImGui.beginPopup("editPopup")) {
|
||||||
for (int i = 1; i < currentSudoku.getSize() + 1; i++) {
|
Block block = currentCell.getBlock();
|
||||||
if (i % (int) (Math.sqrt(currentSudoku.getSize())) != 1)
|
int symbolCount = block.getCells().size();
|
||||||
|
for (int i = 1; i < symbolCount + 1; i++) {
|
||||||
|
if (i % (int) (Math.sqrt(symbolCount)) != 1)
|
||||||
ImGui.sameLine();
|
ImGui.sameLine();
|
||||||
if (ImGui.button(Integer.toString(i), new ImVec2(50, 50))) {
|
if (ImGui.button(Integer.toString(i), new ImVec2(50, 50))) {
|
||||||
this.currentSudoku.setCellSymbol(currentIndex % currentSudoku.getSize(),
|
this.doku.setCellValue(currentCell, i - 1);
|
||||||
currentIndex / currentSudoku.getSize(), i - 1);
|
|
||||||
ImGui.closeCurrentPopup();
|
ImGui.closeCurrentPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,21 +56,26 @@ public class SudokuRenderer {
|
|||||||
ImGui.pushStyleVar(ImGuiStyleVar.FrameBorderSize, 2.0f);
|
ImGui.pushStyleVar(ImGuiStyleVar.FrameBorderSize, 2.0f);
|
||||||
ImGui.pushStyleVar(ImGuiStyleVar.ItemSpacing, new ImVec2(0.0f, 0.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));
|
ImGui.pushStyleColor(ImGuiCol.Border, new ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
for (int y = 0; y < currentSudoku.getSize(); y++) {
|
for (int y = 0; y < doku.getHeight(); y++) {
|
||||||
for (int x = 0; x < currentSudoku.getSize(); x++) {
|
for (int x = 0; x < doku.getWidth(); x++) {
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
ImGui.sameLine();
|
ImGui.sameLine();
|
||||||
int index = y * currentSudoku.getSize() + x;
|
int index = y * doku.getWidth() + x;
|
||||||
Cell cell = currentSudoku.getCell(x, y);
|
Cell cell = doku.getCell(x, y);
|
||||||
int symbol = cell.getSymbolIndex();
|
if (cell == null) {
|
||||||
Color blockColor = colorPalette.get(cell.getBlock());
|
ImGui.pushStyleColor(ImGuiCol.Button, new ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
ImGui.pushStyleColor(ImGuiCol.Button, new ImVec4(blockColor.r, blockColor.g, blockColor.b, 1.0f));
|
ImGui.button("##" + index, new ImVec2(50, 50));
|
||||||
String cellText = "";
|
} else {
|
||||||
if (symbol != -1)
|
int symbol = cell.getSymbolIndex();
|
||||||
cellText += Integer.toString(symbol + 1);
|
Color blockColor = colorPalette.get(cell.getBlock());
|
||||||
if (ImGui.button(cellText + "##" + index, new ImVec2(50, 50))) {
|
ImGui.pushStyleColor(ImGuiCol.Button, new ImVec4(blockColor.r, blockColor.g, blockColor.b, 1.0f));
|
||||||
ImGui.openPopup("editPopup");
|
String cellText = "";
|
||||||
currentIndex = index;
|
if (symbol != -1)
|
||||||
|
cellText += Integer.toString(symbol + 1);
|
||||||
|
if (ImGui.button(cellText + "##" + index, new ImVec2(50, 50))) {
|
||||||
|
ImGui.openPopup("editPopup");
|
||||||
|
currentCell = cell;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui.popStyleColor();
|
ImGui.popStyleColor();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class MultiPlayerView extends BaseView {
|
|||||||
} else {
|
} else {
|
||||||
if (ImGui.button("Démarrer")) {
|
if (ImGui.button("Démarrer")) {
|
||||||
// temp
|
// temp
|
||||||
MultiDoku doku = SudokuFactory.createBasicEmptySquareSudoku(5);
|
MultiDoku doku = SudokuFactory.createBasicSquareMultidoku(3);
|
||||||
this.server.startGame(doku);
|
this.server.startGame(doku);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import sudoku.structure.Block;
|
|||||||
import sudoku.structure.Cell;
|
import sudoku.structure.Cell;
|
||||||
import sudoku.structure.MultiDoku;
|
import sudoku.structure.MultiDoku;
|
||||||
import sudoku.structure.Sudoku;
|
import sudoku.structure.Sudoku;
|
||||||
|
import sudoku.structure.SudokuFactory;
|
||||||
|
|
||||||
public class SudokuSerializer {
|
public class SudokuSerializer {
|
||||||
|
|
||||||
@@ -88,6 +89,7 @@ public class SudokuSerializer {
|
|||||||
|
|
||||||
jsonSudoku.put("cells", cellsJsonArray);
|
jsonSudoku.put("cells", cellsJsonArray);
|
||||||
jsonSudoku.put("blocks", blocksJsonArray);
|
jsonSudoku.put("blocks", blocksJsonArray);
|
||||||
|
jsonSudoku.put("blockWidth", sudoku.getBlockWidth());
|
||||||
jsonSudokus.put(i, jsonSudoku);
|
jsonSudokus.put(i, jsonSudoku);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +153,9 @@ public class SudokuSerializer {
|
|||||||
sudokuBlocks.add(blocks.get(blockID));
|
sudokuBlocks.add(blocks.get(blockID));
|
||||||
}
|
}
|
||||||
|
|
||||||
sudokus.add(new Sudoku(sudokuCells, sudokuBlocks, null));
|
Sudoku s = new Sudoku(sudokuCells, sudokuBlocks, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||||
|
s.setBlockWidth(sudokuJsonObject.getInt("blockWidth"));
|
||||||
|
sudokus.add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MultiDoku(sudokus);
|
return new MultiDoku(sudokus);
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ public class Block {
|
|||||||
|
|
||||||
private final List<Cell> cells;
|
private final List<Cell> cells;
|
||||||
|
|
||||||
|
// faster access to the sudoku
|
||||||
|
private List<Sudoku> sudokus;
|
||||||
|
|
||||||
public Block(List<Cell> cells) {
|
public Block(List<Cell> cells) {
|
||||||
this.cells = cells;
|
this.cells = cells;
|
||||||
}
|
}
|
||||||
@@ -39,4 +42,12 @@ public class Block {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Sudoku> getSudokus() {
|
||||||
|
return sudokus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSudokus(List<Sudoku> sudokus) {
|
||||||
|
this.sudokus = sudokus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,12 @@ public class Coordinate {
|
|||||||
return this.y * size + this.x;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public class Sudoku {
|
|||||||
private final List<Cell> cells;
|
private final List<Cell> cells;
|
||||||
private final List<IConstraint> constraints;
|
private final List<IConstraint> constraints;
|
||||||
private boolean isMutable;
|
private boolean isMutable;
|
||||||
|
private int blockWidth;
|
||||||
|
|
||||||
public Sudoku(List<Cell> cells, List<Block> blocks, List<IConstraint> constraints) {
|
public Sudoku(List<Cell> cells, List<Block> blocks, List<IConstraint> constraints) {
|
||||||
this.cells = cells;
|
this.cells = cells;
|
||||||
@@ -23,7 +24,7 @@ public class Sudoku {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int[] toCoords(int index) {
|
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) {
|
public int toIndex(int x, int y) {
|
||||||
@@ -45,13 +46,19 @@ public class Sudoku {
|
|||||||
return index < getSize() * getSize();
|
return index < getSize() * getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean tryPlaceCellSymbol(int x, int y, int value) {
|
public boolean canBePlaced(int x, int y, int value) {
|
||||||
assert (isValidCoords(x, y));
|
|
||||||
for (IConstraint constraint : this.constraints) {
|
for (IConstraint constraint : this.constraints) {
|
||||||
if (!constraint.canBePlaced(this, x, y, value)) {
|
if (!constraint.canBePlaced(this, x, y, value)) {
|
||||||
return false;
|
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 cell = getCell(x, y);
|
||||||
cell.setSymbolIndex(value);
|
cell.setSymbolIndex(value);
|
||||||
return true;
|
return true;
|
||||||
@@ -71,6 +78,10 @@ public class Sudoku {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getBlockWidth() {
|
||||||
|
return blockWidth;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to place a cell at the given coordinate
|
* Try to place a cell at the given coordinate
|
||||||
*
|
*
|
||||||
@@ -162,6 +173,8 @@ public class Sudoku {
|
|||||||
throw new Exception("The given cell is not in this sudoku.");
|
throw new Exception("The given cell is not in this sudoku.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use this.cells.indexOf();
|
||||||
|
|
||||||
for (Cell cell : this.cells) {
|
for (Cell cell : this.cells) {
|
||||||
if (cell == c) {
|
if (cell == c) {
|
||||||
return new Coordinate(x, y);
|
return new Coordinate(x, y);
|
||||||
@@ -288,7 +301,8 @@ public class Sudoku {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void empty(Cell cell) {
|
public void setBlockWidth(int blockWidth) {
|
||||||
|
this.blockWidth = blockWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
package sudoku.structure;
|
package sudoku.structure;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
import sudoku.constraint.BlockConstraint;
|
import sudoku.constraint.BlockConstraint;
|
||||||
import sudoku.constraint.ColumnConstraint;
|
import sudoku.constraint.ColumnConstraint;
|
||||||
import sudoku.constraint.IConstraint;
|
import sudoku.constraint.IConstraint;
|
||||||
import sudoku.constraint.LineConstraint;
|
import sudoku.constraint.LineConstraint;
|
||||||
import sudoku.solver.Solver;
|
import sudoku.solver.Solver;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class SudokuFactory {
|
public class SudokuFactory {
|
||||||
|
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
|
public static List<IConstraint> DEFAULT_CONSTRAINTS = Arrays.asList(new BlockConstraint(), new LineConstraint(), new ColumnConstraint());
|
||||||
|
|
||||||
private static List<Cell> initCells(int size) {
|
private static List<Cell> initCells(int size) {
|
||||||
List<Cell> cells = new ArrayList<>(size * size);
|
List<Cell> cells = new ArrayList<>(size * size);
|
||||||
@@ -47,17 +49,8 @@ public class SudokuFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static MultiDoku createBasicEmptyRectangleSudoku(int widthBlock, int heightBlock) {
|
public static MultiDoku createBasicEmptyRectangleSudoku(int widthBlock, int heightBlock) {
|
||||||
int symbolCount = widthBlock * heightBlock;
|
Sudoku s = createRectangleSudoku(widthBlock, heightBlock);
|
||||||
List<Cell> cases = initCells(symbolCount);
|
return new MultiDoku(Arrays.asList(s));
|
||||||
List<Block> blocs = initRectangleBlocs(cases, widthBlock, heightBlock);
|
|
||||||
List<IConstraint> constraints = new ArrayList<>();
|
|
||||||
constraints.add(new ColumnConstraint());
|
|
||||||
constraints.add(new LineConstraint());
|
|
||||||
constraints.add(new BlockConstraint());
|
|
||||||
Sudoku s = new Sudoku(cases, blocs, constraints);
|
|
||||||
List<Sudoku> subSudoku = new ArrayList<>();
|
|
||||||
subSudoku.add(s);
|
|
||||||
return new MultiDoku(subSudoku);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MultiDoku createBasicEmptySquareSudoku(int size) {
|
public static MultiDoku createBasicEmptySquareSudoku(int size) {
|
||||||
@@ -106,4 +99,70 @@ public class SudokuFactory {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Sudoku createRectangleSudoku(int width, int height) {
|
||||||
|
int symbolCount = width * height;
|
||||||
|
List<Cell> cases = initCells(symbolCount);
|
||||||
|
List<Block> 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user