Compare commits
9 Commits
696062e9db
...
HAAAAAAAAA
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0795f9256d | ||
| a74bf42e59 | |||
| 1f92c49f3c | |||
| c262007ca8 | |||
| 73f572ee18 | |||
| ec07d88577 | |||
| 6caf5d5c54 | |||
| 7789209651 | |||
| 9b776d4b0f |
@@ -1,6 +1,8 @@
|
||||
package gui;
|
||||
|
||||
import imgui.ImFont;
|
||||
import imgui.ImFontConfig;
|
||||
import imgui.ImFontGlyphRangesBuilder;
|
||||
import imgui.ImGui;
|
||||
|
||||
public class Fonts {
|
||||
@@ -10,14 +12,22 @@ public class Fonts {
|
||||
public static ImFont CHERI;
|
||||
public static ImFont COMIC;
|
||||
public static ImFont INFECTED;
|
||||
public static ImFont EMOJIS;
|
||||
|
||||
private static final String baseDir = "";
|
||||
|
||||
public static void createFonts() {
|
||||
ImFontGlyphRangesBuilder builder = new ImFontGlyphRangesBuilder();
|
||||
builder.addRanges(ImGui.getIO().getFonts().getGlyphRangesDefault());
|
||||
builder.addRanges(ImGui.getIO().getFonts().getGlyphRangesCyrillic());
|
||||
// builder.addRanges(ImGui.getIO().getFonts().getGlyphRangesChineseFull());
|
||||
ImFontConfig cfg = new ImFontConfig();
|
||||
cfg.setGlyphRanges(builder.buildRanges());
|
||||
|
||||
COMIC = ImGui.getIO().getFonts().addFontFromFileTTF(baseDir + "comic.ttf", 50.0f);
|
||||
ARIAL_BOLD = ImGui.getIO().getFonts().addFontFromFileTTF(baseDir + "arial_bold.ttf", 50.0f);
|
||||
ARIAL = ImGui.getIO().getFonts().addFontFromFileTTF(baseDir + "arial.ttf", 50.0f);
|
||||
CHERI = ImGui.getIO().getFonts().addFontFromFileTTF(baseDir + "cheri.ttf", 50.0f);
|
||||
ARIAL_BOLD = ImGui.getIO().getFonts().addFontFromFileTTF(baseDir + "arial_bold.ttf", 50.0f);
|
||||
ARIAL = ImGui.getIO().getFonts().addFontFromFileTTF(baseDir + "arial.ttf", 50.0f, cfg);
|
||||
CHERI = ImGui.getIO().getFonts().addFontFromFileTTF(baseDir + "cheri.ttf", 50.0f);
|
||||
INFECTED = ImGui.getIO().getFonts().addFontFromFileTTF(baseDir + "INFECTED.ttf", 50.0f);
|
||||
}
|
||||
|
||||
|
||||
7
app/src/main/java/gui/Options.java
Normal file
7
app/src/main/java/gui/Options.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package gui;
|
||||
|
||||
public class Options {
|
||||
|
||||
public static Symbols Symboles = Symbols.Numbers;
|
||||
|
||||
}
|
||||
@@ -47,8 +47,6 @@ public class RenderableMultidoku {
|
||||
return cells.get(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static record PositionConstraint(Sudoku sudoku1, Sudoku sudoku2, Coordinate offset) {
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ public class SudokuRenderer {
|
||||
ImGui.closeCurrentPopup();
|
||||
}
|
||||
} else {
|
||||
if (ImGui.button(Integer.toString(i + 1), cellSize)) {
|
||||
if (ImGui.button(Options.Symboles.getSymbols().get(i), cellSize)) {
|
||||
currentCell.trySetValue(i);
|
||||
if (this.doku.getDoku().isSolved())
|
||||
this.onResolve.emit();
|
||||
@@ -88,6 +88,9 @@ public class SudokuRenderer {
|
||||
}
|
||||
|
||||
public void render() {
|
||||
if (Options.Symboles == Symbols.Russian) {
|
||||
ImGui.pushFont(Fonts.ARIAL);
|
||||
}
|
||||
final float sudokuViewWidth = cellSize.x * doku.getWidth();
|
||||
final float displayWidth = ImGui.getIO().getDisplaySizeX();
|
||||
float offsetX = displayWidth / 2.0f - sudokuViewWidth / 2.0f;
|
||||
@@ -123,7 +126,7 @@ public class SudokuRenderer {
|
||||
ImGui.pushStyleColor(ImGuiCol.Button, new ImVec4(blockColor.r, blockColor.g, blockColor.b, 1.0f));
|
||||
String cellText = "";
|
||||
if (symbol != -1)
|
||||
cellText += Integer.toString(symbol + 1);
|
||||
cellText += Options.Symboles.getSymbols().get(symbol);
|
||||
if (ImGui.button(cellText + "##" + index, cellSize) && cell.isMutable()) {
|
||||
ImGui.openPopup("editPopup");
|
||||
currentCell = cell;
|
||||
@@ -135,6 +138,9 @@ public class SudokuRenderer {
|
||||
ImGui.popStyleVar(2);
|
||||
renderPopup();
|
||||
ImGui.endChild();
|
||||
if (Options.Symboles == Symbols.Russian) {
|
||||
ImGui.popFont();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
83
app/src/main/java/gui/Symbols.java
Normal file
83
app/src/main/java/gui/Symbols.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package gui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public enum Symbols {
|
||||
|
||||
Numbers("Nombres", getNumbers()),
|
||||
Letters("Lettres", getLetters()),
|
||||
Russian("Cyrilique", getRussian()),
|
||||
Emojis("Emojis (Console uniquement)", getEmojis());
|
||||
|
||||
String displayName;
|
||||
List<String> symbols;
|
||||
|
||||
private Symbols(String displayName, List<String> symbols) {
|
||||
this.symbols = symbols;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public List<String> getSymbols() {
|
||||
return symbols;
|
||||
}
|
||||
|
||||
private static List<String> getNumbers() {
|
||||
List<String> sym = new ArrayList<>();
|
||||
for (int i = 1; i <= 100; i++) {
|
||||
sym.add(Integer.toString(i));
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
private static List<String> getLetters() {
|
||||
List<String> sym = new ArrayList<>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
int currentOffset = i;
|
||||
String letter = "";
|
||||
while (currentOffset >= 26) {
|
||||
letter += Character.toString((char) ('A' + currentOffset % 26));
|
||||
currentOffset /= 26;
|
||||
currentOffset--;
|
||||
}
|
||||
letter += Character.toString((char) ('A' + currentOffset % 26));
|
||||
sym.add(new StringBuilder(letter).reverse().toString());
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
private static List<String> getRussian() {
|
||||
List<String> sym = new ArrayList<>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
sym.add(new String(Character.toChars(0X0400 + i)));
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
private static List<String> getEmojis() {
|
||||
List<String> sym = new ArrayList<>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
sym.add(new String(Character.toChars(0X1F600 + i)));
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
private static final String[] symbolNames;
|
||||
|
||||
static {
|
||||
Symbols[] symbols = Symbols.values();
|
||||
symbolNames = new String[symbols.length];
|
||||
for (int i = 0; i < symbols.length; i++) {
|
||||
symbolNames[i] = symbols[i].getDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getSymbolsNames() {
|
||||
return symbolNames;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +1,24 @@
|
||||
package gui.menu;
|
||||
|
||||
import gui.Options;
|
||||
import gui.Symbols;
|
||||
import imgui.ImGui;
|
||||
import imgui.type.ImInt;
|
||||
|
||||
public class OptionsMenu extends BaseView {
|
||||
|
||||
private ImInt currentValue = new ImInt();
|
||||
|
||||
public OptionsMenu(StateMachine stateMachine) {
|
||||
super(stateMachine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
// TODO Auto-generated method stub
|
||||
ImGui.text("Options");
|
||||
if(ImGui.combo("Jeu de symboles", currentValue, Symbols.getSymbolsNames())){
|
||||
Options.Symboles = Symbols.values()[currentValue.get()];
|
||||
}
|
||||
renderReturnButton();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package gui.menu;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CancellationException;
|
||||
|
||||
import gui.SudokuRenderer;
|
||||
import imgui.ImGui;
|
||||
import imgui.ImGuiStyle;
|
||||
import sudoku.io.SudokuSerializer;
|
||||
import sudoku.solver.BacktrackingSolver;
|
||||
import sudoku.solver.HumanSolver;
|
||||
import sudoku.solver.MixedSolver;
|
||||
import sudoku.solver.Solver;
|
||||
import sudoku.structure.MultiDoku;
|
||||
|
||||
@@ -66,34 +68,52 @@ public class SudokuView extends BaseView {
|
||||
stopResolve();
|
||||
}
|
||||
|
||||
private void startSolve(Solver solver) {
|
||||
resolveThread = new Thread(() -> {
|
||||
try {
|
||||
solver.solve(this.doku);
|
||||
} catch (CancellationException e) {
|
||||
System.out.println("The user is bored !");
|
||||
}
|
||||
stopResolve();
|
||||
});
|
||||
}
|
||||
|
||||
private void renderSolvePopup() {
|
||||
if (ImGui.beginPopup("solve")) {
|
||||
if (ImGui.button("Résoudre avec backtrace")) {
|
||||
startSolve(new BacktrackingSolver());
|
||||
ImGui.closeCurrentPopup();
|
||||
}
|
||||
if (ImGui.button("Résoudre avec déduction")) {
|
||||
startSolve(new HumanSolver());
|
||||
ImGui.closeCurrentPopup();
|
||||
}
|
||||
if (ImGui.button("Résoudre avec déduction et backtrace")) {
|
||||
startSolve(new MixedSolver());
|
||||
ImGui.closeCurrentPopup();
|
||||
}
|
||||
ImGui.endPopup();
|
||||
}
|
||||
}
|
||||
|
||||
private void renderSolveButton() {
|
||||
if (resolveThread != null)
|
||||
ImGui.beginDisabled();
|
||||
|
||||
boolean beginSolve = false;
|
||||
|
||||
if (!resolved && centeredButton("Résoudre")) {
|
||||
beginSolve = true;
|
||||
if (!this.resolved && centeredButton("Résoudre")) {
|
||||
// beginSolve = true;
|
||||
ImGui.openPopup("solve");
|
||||
}
|
||||
|
||||
if (resolveThread != null)
|
||||
ImGui.endDisabled();
|
||||
|
||||
if (beginSolve) {
|
||||
resolveThread = new Thread(() -> {
|
||||
try {
|
||||
Random rand = new Random();
|
||||
Solver.randomSolve(doku, rand);
|
||||
Thread.sleep(200);
|
||||
} catch (CancellationException | InterruptedException e) {
|
||||
System.out.println("The user is bored !");
|
||||
}
|
||||
stopResolve();
|
||||
});
|
||||
}
|
||||
|
||||
if (resolved) {
|
||||
if (this.resolved) {
|
||||
ImGui.text("Bravo !");
|
||||
}
|
||||
|
||||
renderSolvePopup();
|
||||
}
|
||||
|
||||
private void renderSaveButton() {
|
||||
|
||||
@@ -3,15 +3,40 @@
|
||||
*/
|
||||
package sudoku;
|
||||
|
||||
import gui.RenderableMultidoku;
|
||||
import gui.Symbols;
|
||||
import sudoku.io.ConsoleInterface;
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.solver.RandomSolver;
|
||||
import sudoku.solver.Solver;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.SudokuFactory;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Main {
|
||||
public String getGreeting() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
public static void voidTest(){
|
||||
MultiDoku md = SudokuFactory.createBasicXShapedMultidoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
SudokuPrinter.printMultiDoku(RenderableMultidoku.fromMultidoku(md), Symbols.Numbers, 3, 3);
|
||||
}
|
||||
|
||||
public static void filledTest(){
|
||||
MultiDoku md = SudokuFactory.createBasicXShapedMultidoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
new RandomSolver().solve(md);
|
||||
SudokuPrinter.printMultiDoku(RenderableMultidoku.fromMultidoku(md), Symbols.Numbers, 3, 3);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ConsoleInterface console = new ConsoleInterface();
|
||||
console.start();
|
||||
/*
|
||||
voidTest();
|
||||
filledTest();
|
||||
filledTest();
|
||||
*/
|
||||
console.welcome();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
package sudoku.io;
|
||||
|
||||
import gui.RenderableMultidoku;
|
||||
import gui.Symbols;
|
||||
import sudoku.constraint.*;
|
||||
import sudoku.solver.Solver;
|
||||
import sudoku.solver.RandomSolver;
|
||||
import sudoku.structure.Difficulty;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
import sudoku.structure.SudokuFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class ConsoleInterface {
|
||||
public Scanner reader = new Scanner(System.in);
|
||||
|
||||
public void welcome(){
|
||||
System.out.println("Welcome to our Sudoku Solver!");
|
||||
System.out.println("This is the project of Melvyn Bauvent, Lilas Grenier and Simon Priblyski.");
|
||||
start();
|
||||
}
|
||||
|
||||
public void start(){
|
||||
welcome();
|
||||
System.out.println("First of all, you need to tell me the size of the sudoku you want to generate.");
|
||||
int width = getBlockWidth();
|
||||
int height = getBlockHeight();
|
||||
@@ -28,26 +33,21 @@ public class ConsoleInterface {
|
||||
pickSymbols(listSymbols, numberOfSymbols);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
System.out.println("Simon doit finir sa partie.");
|
||||
assert false;
|
||||
listSymbols = Symbols.Numbers.getSymbols();
|
||||
}
|
||||
List<Constraint> listConstraints = getListConstraints();
|
||||
|
||||
|
||||
System.out.println("Now that we have the size of our sudoku, would you rather have a single grid ('one', default), " +
|
||||
"or a a multidoku composed of 5 subgrids ('multi') ?");
|
||||
List<Sudoku> subGrids = new ArrayList<>();
|
||||
MultiDoku doku;
|
||||
if (reader.next().equalsIgnoreCase("multi")) {
|
||||
doku = SudokuFactory.createBasicEmptyRectangleDoku(width, height, listConstraints);
|
||||
}
|
||||
else {
|
||||
doku = SudokuFactory.createBasicXShapedMultidoku(width, height, listConstraints);
|
||||
}
|
||||
else {
|
||||
doku = SudokuFactory.createBasicEmptyRectangleDoku(width, height, listConstraints);
|
||||
}
|
||||
RenderableMultidoku rm = RenderableMultidoku.fromMultidoku(doku);
|
||||
System.out.println("Your sudoku will look like this:");
|
||||
// TODO printMultiDoku method not yet implemented
|
||||
SudokuPrinter.printMultiDoku(doku, width, height);
|
||||
SudokuPrinter.printMultiDoku(rm, listSymbols, width, height);
|
||||
System.out.println("We now will fill this sudoku.");
|
||||
System.out.println("What level of difficulty would you like? ('very easy', 'easy', 'medium' (default), 'hard', 'full' (sudoku fully completed))");
|
||||
String difficulty = reader.next().toLowerCase();
|
||||
@@ -58,12 +58,7 @@ public class ConsoleInterface {
|
||||
generatePartialDoku(doku, difficulty);
|
||||
}
|
||||
System.out.println("Here's your sudoku !");
|
||||
SudokuPrinter.printMultiDoku(doku, width, height);
|
||||
}
|
||||
|
||||
public void welcome(){
|
||||
System.out.println("Welcome to our Sudoku Solver!");
|
||||
System.out.println("This is the project of Melvyn Bauvent, Lilas Grenier and Simon Priblyski.");
|
||||
SudokuPrinter.printMultiDoku(rm, listSymbols, width, height);
|
||||
}
|
||||
|
||||
public int getBlockWidth() {
|
||||
@@ -133,7 +128,7 @@ public class ConsoleInterface {
|
||||
}
|
||||
|
||||
private void generateFullDoku(MultiDoku doku) {
|
||||
Solver.randomSolve(doku, new Random());
|
||||
new RandomSolver().solve(doku);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,28 +1,89 @@
|
||||
package sudoku.io;
|
||||
|
||||
import gui.RenderableMultidoku;
|
||||
import gui.Symbols;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
|
||||
public class SudokuPrinter {
|
||||
import java.util.List;
|
||||
|
||||
public static void printRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight) {
|
||||
for (int y = 0; y < s.getSize(); y++) {
|
||||
if (y % blockHeight == 0 && y > 0) {
|
||||
System.out.println();
|
||||
}
|
||||
StringBuilder line = new StringBuilder("[ ");
|
||||
for (int x = 0; x < s.getSize(); x++) {
|
||||
line.append((s.getCell(x, y).getSymbolIndex() + 1)).append(" ");
|
||||
if (x % blockWidth == blockWidth - 1 && x != blockWidth * blockHeight - 1) {
|
||||
line.append("| ");
|
||||
}
|
||||
}
|
||||
line.append("]");
|
||||
System.out.println(line);
|
||||
}
|
||||
public class SudokuPrinter {
|
||||
public static final String ANSI_RESET = "\u001B[0m";
|
||||
public static final String ANSI_RED = "\u001B[31m";
|
||||
public static final String ANSI_GREEN = "\u001B[32m";
|
||||
public static final String ANSI_YELLOW = "\u001B[33m";
|
||||
public static final String ANSI_BLUE = "\u001B[34m";
|
||||
public static final String ANSI_PURPLE = "\u001B[35m";
|
||||
public static final String ANSI_CYAN = "\u001B[36m";
|
||||
|
||||
public static void printRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight, Symbols symbols) {
|
||||
printRectangleSudoku(s, blockWidth, blockHeight, symbols.getSymbols());
|
||||
}
|
||||
|
||||
public static String toStringRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight) {
|
||||
public static void printRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight, List<String> listSymbols){
|
||||
for (int y = 0; y < s.getSize(); y++) {
|
||||
if (y % blockHeight == 0 && y > 0) {
|
||||
System.out.println();
|
||||
}
|
||||
StringBuilder line = new StringBuilder("[ ");
|
||||
for (int x = 0; x < s.getSize(); x++) {
|
||||
Cell c = s.getCell(x, y);
|
||||
if (c.getSymbolIndex() == Cell.NOSYMBOL) {
|
||||
line.append(" ");
|
||||
}
|
||||
else {
|
||||
line.append(listSymbols.get(c.getSymbolIndex())).append(" ");
|
||||
}
|
||||
if (x % blockWidth == blockWidth - 1 && x != blockWidth * blockHeight - 1) {
|
||||
line.append("| ");
|
||||
}
|
||||
}
|
||||
line.append("]");
|
||||
System.out.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
public static void printMultiDoku(final RenderableMultidoku rm, Symbols symbols, int blockWidth, int blockHeight) {
|
||||
printMultiDoku(rm, symbols.getSymbols(), blockWidth, blockHeight);
|
||||
}
|
||||
|
||||
public static void printMultiDoku(final RenderableMultidoku rm, List<String> listSymbols, int blockWidth, int blockHeight) {
|
||||
StringBuilder line = new StringBuilder("\n");
|
||||
int nBlockInWidth = rm.getWidth() / blockWidth;
|
||||
for (int y = 0; y < rm.getHeight(); y++) {
|
||||
if (y % blockHeight == 0) {
|
||||
line.append("__".repeat(Math.max(0, rm.getWidth()+nBlockInWidth))).append("_\n");
|
||||
}
|
||||
line.append("[ ");
|
||||
for (int x = 0; x < rm.getWidth(); x++) {
|
||||
if (x % blockWidth == 0 && x > 0) {
|
||||
line.append("| ");
|
||||
}
|
||||
Cell cell = rm.getCell(x, y);
|
||||
if (cell != null) {
|
||||
if (cell.getSymbolIndex() == Cell.NOSYMBOL) {
|
||||
line.append("- ");
|
||||
}
|
||||
else {
|
||||
line.append(listSymbols.get(cell.getSymbolIndex())).append(" ");
|
||||
}
|
||||
}
|
||||
else {
|
||||
line.append(" ");
|
||||
}
|
||||
}
|
||||
line.append("]\n");
|
||||
}
|
||||
line.append("__".repeat(Math.max(0, rm.getWidth()+nBlockInWidth))).append("_\n");
|
||||
System.out.println(line);
|
||||
}
|
||||
|
||||
public static String toStringRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight, Symbols symbols){
|
||||
return toStringRectangleSudoku(s, blockWidth, blockHeight, symbols.getSymbols());
|
||||
}
|
||||
|
||||
public static String toStringRectangleSudoku(final Sudoku s, int blockWidth, int blockHeight, List<String> listSymbols) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int y = 0; y < s.getSize(); y++) {
|
||||
// Ajouter une ligne vide entre les blocs horizontaux
|
||||
@@ -32,7 +93,13 @@ public class SudokuPrinter {
|
||||
StringBuilder line = new StringBuilder("[ ");
|
||||
for (int x = 0; x < s.getSize(); x++) {
|
||||
// Ajouter la valeur de la cellule
|
||||
line.append((s.getCell(x, y).getSymbolIndex() + 1)).append(" ");
|
||||
Cell cell = s.getCell(x, y);
|
||||
if (cell.getSymbolIndex() == Cell.NOSYMBOL) {
|
||||
line.append(" ");
|
||||
}
|
||||
else {
|
||||
line.append(listSymbols.get(cell.getSymbolIndex())).append(" ");
|
||||
}
|
||||
|
||||
// Ajouter un séparateur vertical entre les blocs
|
||||
if (x % blockWidth == blockWidth - 1 && x != s.getSize() - 1) {
|
||||
@@ -45,7 +112,12 @@ public class SudokuPrinter {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static void printMultiDoku(final MultiDoku doku, int blockWidth, int blockHeight){
|
||||
// TODO
|
||||
public static void printMultiDoku(final MultiDoku doku, int blockWidth, int blockHeight, Symbols symbols){
|
||||
if (doku.getNbSubGrids()==1) {
|
||||
printRectangleSudoku(doku.getSubGrid(0), blockWidth, blockHeight, symbols);
|
||||
}
|
||||
else {
|
||||
printMultiDoku(RenderableMultidoku.fromMultidoku(doku), symbols, blockWidth, blockHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
49
app/src/main/java/sudoku/solver/BacktrackingSolver.java
Normal file
49
app/src/main/java/sudoku/solver/BacktrackingSolver.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package sudoku.solver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CancellationException;
|
||||
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
|
||||
public class BacktrackingSolver implements Solver {
|
||||
|
||||
/**
|
||||
* Résout le MultiDoku passé en paramètre, avec backtracking.
|
||||
*
|
||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||
*/
|
||||
@Override
|
||||
public boolean solve(MultiDoku doku) {
|
||||
if (Thread.interrupted())
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Cell cellToFill = doku.getFirstEmptyCell();
|
||||
if (cellToFill == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
if (possibleSymbols.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int symbol : possibleSymbols) {
|
||||
|
||||
cellToFill.setSymbolIndex(symbol);
|
||||
if (this.solve(doku)) {
|
||||
return true;
|
||||
} else {
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
57
app/src/main/java/sudoku/solver/HumanSolver.java
Normal file
57
app/src/main/java/sudoku/solver/HumanSolver.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package sudoku.solver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import gui.Symbols;
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
|
||||
public class HumanSolver implements Solver {
|
||||
|
||||
/**
|
||||
* Résout le MultiDoku passé en paramètre, avec règles de déduction.
|
||||
*
|
||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||
*/
|
||||
@Override
|
||||
public boolean solve(MultiDoku doku) {
|
||||
if (Thread.interrupted())
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
|
||||
Sudoku sudoku = doku.getSubGrid(0);
|
||||
logger.log(Level.FINE,
|
||||
'\n' + SudokuPrinter.toStringRectangleSudoku(sudoku,
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth(),
|
||||
Symbols.Numbers));
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Cell> cellsToFill = doku.getEmptyCells();
|
||||
if (cellsToFill.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Cell cellToFill : cellsToFill) {
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
if (possibleSymbols.size() != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
|
||||
|
||||
return this.solve(doku);
|
||||
}
|
||||
|
||||
return doku.isSolved();
|
||||
}
|
||||
|
||||
}
|
||||
82
app/src/main/java/sudoku/solver/MixedSolver.java
Normal file
82
app/src/main/java/sudoku/solver/MixedSolver.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package sudoku.solver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import gui.Symbols;
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
|
||||
public class MixedSolver implements Solver{
|
||||
|
||||
/**
|
||||
* Résout le MultiDoku passé en paramètre, avec règles de déduction et
|
||||
* backtracking.
|
||||
*
|
||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||
*/
|
||||
@Override
|
||||
public boolean solve(MultiDoku doku) {
|
||||
Random rand = new Random();
|
||||
|
||||
if (Thread.interrupted()) {
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
}
|
||||
|
||||
Sudoku sudoku = doku.getSubGrid(0);
|
||||
logger.log(Level.FINE,
|
||||
'\n' + SudokuPrinter.toStringRectangleSudoku(
|
||||
sudoku,
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth(),
|
||||
Symbols.Numbers));
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Cell> cellsToFill = doku.getEmptyCells();
|
||||
if (cellsToFill.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Règles de déduction
|
||||
for (Cell cellToFill : cellsToFill) {
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
if (possibleSymbols.size() != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
|
||||
|
||||
return this.solve(doku);
|
||||
}
|
||||
|
||||
// Si ça ne marche pas
|
||||
// On fait du backtracking
|
||||
Cell cellToFill = doku.getRandomEmptyCell(rand);
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
|
||||
while (!possibleSymbols.isEmpty()) {
|
||||
int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size());
|
||||
int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex);
|
||||
|
||||
cellToFill.setSymbolIndex(nextSymbol);
|
||||
if (this.solve(doku)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
possibleSymbols.remove(nextPossibleSymbolIndex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
65
app/src/main/java/sudoku/solver/RandomSolver.java
Normal file
65
app/src/main/java/sudoku/solver/RandomSolver.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package sudoku.solver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import gui.Symbols;
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
|
||||
public class RandomSolver implements Solver {
|
||||
|
||||
/**
|
||||
* Résout, si possible, le multidoku passé en paramètre
|
||||
* en testant toutes les possibilités, de manière aléatoire, avec un algorithme
|
||||
* de backtracking.
|
||||
*
|
||||
* @param doku Multidoku, à résoudre
|
||||
* @param rand Random, pour tester aléatoirement les symboles
|
||||
* @return boolean, true s'il est résolu ou false s'il ne l'est pas.
|
||||
*/
|
||||
@Override
|
||||
public boolean solve(MultiDoku doku) {
|
||||
Random rand = new Random();
|
||||
|
||||
if (Thread.interrupted())
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
|
||||
Sudoku sudoku = doku.getSubGrid(0);
|
||||
logger.log(Level.FINE,
|
||||
'\n' + SudokuPrinter.toStringRectangleSudoku(sudoku,
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth(),
|
||||
Symbols.Numbers));
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Cell cellToFill = doku.getFirstEmptyCell();
|
||||
if (cellToFill == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
|
||||
while (!possibleSymbols.isEmpty()) {
|
||||
int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size());
|
||||
int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex);
|
||||
|
||||
cellToFill.setSymbolIndex(nextSymbol);
|
||||
if (this.solve(doku)) {
|
||||
return true;
|
||||
}
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
possibleSymbols.remove(nextPossibleSymbolIndex);
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,236 +1,47 @@
|
||||
package sudoku.solver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.structure.Cell;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
|
||||
public class Solver {
|
||||
public interface Solver {
|
||||
|
||||
/**
|
||||
/**
|
||||
* Log du Solver, qui garde trace des actions réalisées.
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger("SolverLogger");
|
||||
public static final Logger logger = Logger.getLogger("SolverLogger");
|
||||
|
||||
/**
|
||||
* Résout, si possible, le multidoku passé en paramètre
|
||||
* en testant toutes les possibilités, de manière aléatoire, avec un algorithme
|
||||
* de backtracking.
|
||||
*
|
||||
* @param doku Multidoku, à résoudre
|
||||
* @param rand Random, pour tester aléatoirement les symboles
|
||||
* @return boolean, true s'il est résolu ou false s'il ne l'est pas.
|
||||
*/
|
||||
public static boolean randomSolve(MultiDoku doku, Random rand) {
|
||||
if (Thread.interrupted())
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
boolean solve(MultiDoku doku);
|
||||
|
||||
Sudoku sudoku = doku.getSubGrid(0);
|
||||
logger.log(Level.FINE,
|
||||
'\n' + SudokuPrinter.toStringRectangleSudoku(sudoku,
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth()));
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Cell cellToFill = doku.getFirstEmptyCell();
|
||||
if (cellToFill == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
|
||||
while (!possibleSymbols.isEmpty()) {
|
||||
int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size());
|
||||
int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex);
|
||||
|
||||
cellToFill.setSymbolIndex(nextSymbol);
|
||||
if (Solver.randomSolve(doku, rand)) {
|
||||
return true;
|
||||
}
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
possibleSymbols.remove(nextPossibleSymbolIndex);
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Compte le nombre de solutions possibles au MultiDoku passé en paramètres.
|
||||
*
|
||||
* @param doku MultiDoku, MultiDoku dont on veut le nombre de solutions.
|
||||
* @return int, nombre de solutions possibles.
|
||||
*/
|
||||
public static int countSolution(MultiDoku doku) {
|
||||
default int countSolution(MultiDoku doku) {
|
||||
int result = 0;
|
||||
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Cell cellToFill = doku.getFirstEmptyCell();
|
||||
assert(cellToFill != null);
|
||||
assert (cellToFill != null);
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
|
||||
for (int symbol : possibleSymbols) {
|
||||
doku.getStateManager().pushState();
|
||||
cellToFill.setSymbolIndex(symbol);
|
||||
if (Solver.solve(doku)) {
|
||||
if (solve(doku)) {
|
||||
result++;
|
||||
}
|
||||
doku.getStateManager().popState();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Résout le MultiDoku passé en paramètre, avec backtracking.
|
||||
*
|
||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||
*/
|
||||
public static boolean solve(MultiDoku doku) {
|
||||
if (Thread.interrupted())
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Cell cellToFill = doku.getFirstEmptyCell();
|
||||
if (cellToFill == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
if (possibleSymbols.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int symbol : possibleSymbols) {
|
||||
|
||||
cellToFill.setSymbolIndex(symbol);
|
||||
if (Solver.solve(doku)) {
|
||||
return true;
|
||||
} else {
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Résout le MultiDoku passé en paramètre, avec règles de déduction.
|
||||
*
|
||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||
*/
|
||||
public static boolean humanSolve(MultiDoku doku) {
|
||||
if (Thread.interrupted())
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
|
||||
Sudoku sudoku = doku.getSubGrid(0);
|
||||
logger.log(Level.FINE,
|
||||
'\n' + SudokuPrinter.toStringRectangleSudoku(sudoku,
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth()));
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Cell> cellsToFill = doku.getEmptyCells();
|
||||
if (cellsToFill.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Cell cellToFill : cellsToFill) {
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
if (possibleSymbols.size() != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
|
||||
|
||||
return Solver.humanSolve(doku);
|
||||
}
|
||||
|
||||
return doku.isSolved();
|
||||
}
|
||||
|
||||
/**
|
||||
* Résout le MultiDoku passé en paramètre, avec règles de déduction et backtracking.
|
||||
*
|
||||
* @param doku MultiDoku, MultiDoku à résoudre.
|
||||
* @param rand Random, pour tester aléatoirement les symboles, lors du backtracking.
|
||||
* @return boolean, valant true si le MultiDoku est résolu, false sinon.
|
||||
*/
|
||||
public static boolean mixedSolve(MultiDoku doku, Random rand) {
|
||||
if (Thread.interrupted()) {
|
||||
throw new CancellationException("User wants to stop the solver");
|
||||
}
|
||||
|
||||
Sudoku sudoku = doku.getSubGrid(0);
|
||||
logger.log(Level.FINE,
|
||||
'\n' + SudokuPrinter.toStringRectangleSudoku(
|
||||
sudoku,
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getBlockWidth(),
|
||||
sudoku.getBlockWidth() == 0 ? sudoku.getSize() : sudoku.getSize() / sudoku.getBlockWidth())
|
||||
);
|
||||
|
||||
if (doku.isSolved()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Cell> cellsToFill = doku.getEmptyCells();
|
||||
if (cellsToFill.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Règles de déduction
|
||||
for (Cell cellToFill : cellsToFill) {
|
||||
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
if (possibleSymbols.size() != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cellToFill.setSymbolIndex(possibleSymbols.getFirst());
|
||||
|
||||
return Solver.mixedSolve(doku, rand);
|
||||
}
|
||||
|
||||
//Si ça ne marche pas
|
||||
//On fait du backtracking
|
||||
Cell cellToFill = doku.getRandomEmptyCell(rand);
|
||||
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
|
||||
|
||||
while (!possibleSymbols.isEmpty()) {
|
||||
int nextPossibleSymbolIndex = rand.nextInt(possibleSymbols.size());
|
||||
int nextSymbol = possibleSymbols.get(nextPossibleSymbolIndex);
|
||||
|
||||
cellToFill.setSymbolIndex(nextSymbol);
|
||||
if (Solver.mixedSolve(doku, rand)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cellToFill.setSymbolIndex(Cell.NOSYMBOL);
|
||||
possibleSymbols.remove(nextPossibleSymbolIndex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package sudoku.solver;
|
||||
|
||||
import java.util.concurrent.CancellationException;
|
||||
|
||||
import sudoku.structure.Coordinate;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.Sudoku;
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import sudoku.io.SudokuSerializer;
|
||||
|
||||
import sudoku.constraint.Constraint;
|
||||
import sudoku.io.SudokuSerializer;
|
||||
import sudoku.solver.RandomSolver;
|
||||
import sudoku.solver.Solver;
|
||||
|
||||
public class SudokuFactory {
|
||||
@@ -116,7 +116,7 @@ public class SudokuFactory {
|
||||
* @return boolean, valant true si un MultiDoku de difficulté donnée peut être créée, false sinon.
|
||||
* @throws Exception si la difficulté n'est pas compatible avec la taille du MultiDoku.
|
||||
*/
|
||||
public static boolean newDokuFromFilledOne(MultiDoku doku, int nbCellsToEmpty) throws Exception {
|
||||
public static boolean newDokuFromFilledOne(MultiDoku doku, int nbCellsToEmpty, Solver solver) throws Exception {
|
||||
|
||||
if (nbCellsToEmpty >= doku.getCells().size()) {
|
||||
throw new Exception();
|
||||
@@ -134,9 +134,9 @@ public class SudokuFactory {
|
||||
|
||||
int oldSymbol = cellToEmpty.empty();
|
||||
|
||||
int nbDokuSultions = Solver.countSolution(doku);
|
||||
int nbDokuSultions = solver.countSolution(doku);
|
||||
if (nbDokuSultions == 1) {
|
||||
if (newDokuFromFilledOne(doku, --nbCellsToEmpty)) {
|
||||
if (newDokuFromFilledOne(doku, --nbCellsToEmpty, solver)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ public class SudokuFactory {
|
||||
cellsThatCanBeEmptied.remove(cellToEmpty);
|
||||
}
|
||||
|
||||
return newDokuFromFilledOne(doku, --nbCellsToEmpty);
|
||||
return newDokuFromFilledOne(doku, --nbCellsToEmpty, solver);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,9 +272,10 @@ public class SudokuFactory {
|
||||
}
|
||||
|
||||
public static void fillDoku(MultiDoku doku, Difficulty difficulty) throws Exception {
|
||||
Solver.randomSolve(doku, random);
|
||||
Solver solver = new RandomSolver();
|
||||
solver.solve(doku);
|
||||
int nbCellsToEmpty = (int) (difficulty.getFactor() * doku.getNbCells());
|
||||
boolean successfull = newDokuFromFilledOne(doku, nbCellsToEmpty);
|
||||
boolean successfull = newDokuFromFilledOne(doku, nbCellsToEmpty, solver);
|
||||
if (!successfull) {
|
||||
throw new Exception("Canno't create this doku with this difficulty");
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.json.JSONObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import sudoku.io.SudokuSerializer;
|
||||
import sudoku.solver.Solver;
|
||||
import sudoku.solver.RandomSolver;
|
||||
import sudoku.structure.MultiDoku;
|
||||
import sudoku.structure.SudokuFactory;
|
||||
|
||||
@@ -19,7 +19,7 @@ public class SudokuSerializerTest {
|
||||
void testSerializeWithSize(int blockWidth, int blockHeight) {
|
||||
var sudoku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight,
|
||||
SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
Solver.randomSolve(sudoku, new Random());
|
||||
new RandomSolver().solve(sudoku);
|
||||
JSONObject data = SudokuSerializer.serializeSudoku(sudoku);
|
||||
MultiDoku multiDoku = SudokuSerializer.deserializeSudoku(data);
|
||||
assertTrue(data.toString().equals(SudokuSerializer.serializeSudoku(multiDoku).toString()));
|
||||
@@ -28,14 +28,15 @@ public class SudokuSerializerTest {
|
||||
void testSaveWithSize(int blockWidth, int blockHeight) {
|
||||
MultiDoku doku = SudokuFactory.createBasicEmptyRectangleDoku(blockWidth, blockHeight,
|
||||
SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
Solver.randomSolve(doku, new Random());
|
||||
new RandomSolver().solve(doku);
|
||||
String savePath = SudokuSerializer.saveMultiDoku(doku);
|
||||
MultiDoku otherDoku = null;
|
||||
try {
|
||||
otherDoku = SudokuFactory.fromfile(savePath);
|
||||
assert (otherDoku != null);
|
||||
|
||||
assertEquals(SudokuSerializer.serializeSudoku(doku).toString(), SudokuSerializer.serializeSudoku(otherDoku).toString());
|
||||
assertEquals(SudokuSerializer.serializeSudoku(doku).toString(),
|
||||
SudokuSerializer.serializeSudoku(otherDoku).toString());
|
||||
// clean file after test
|
||||
File fileToDelete = new File(savePath);
|
||||
fileToDelete.delete();
|
||||
@@ -47,7 +48,7 @@ public class SudokuSerializerTest {
|
||||
|
||||
void testSerializeX(int size) {
|
||||
var sudoku = SudokuFactory.createBasicXShapedMultidoku(size, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
Solver.randomSolve(sudoku, new Random());
|
||||
new RandomSolver().solve(sudoku);
|
||||
JSONObject data = SudokuSerializer.serializeSudoku(sudoku);
|
||||
MultiDoku multiDoku = SudokuSerializer.deserializeSudoku(data);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package sudoku.solver;
|
||||
|
||||
import gui.Symbols;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sudoku.io.SudokuPrinter;
|
||||
import sudoku.io.SudokuSerializer;
|
||||
@@ -38,7 +39,8 @@ class SolverTest {
|
||||
|
||||
assert (sudokuToTest.setImmutableCellsSymbol(immutableCells));
|
||||
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
|
||||
//SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
|
||||
SudokuPrinter.printMultiDoku(dokuToTest, 3, 3, Symbols.Numbers);
|
||||
|
||||
List<Integer> correctCells = List.of(7, 6, 0, 3, 4, 2, 8, 5, 1,
|
||||
2, 3, 8, 1, 5, 6, 7, 0, 4,
|
||||
@@ -53,14 +55,15 @@ class SolverTest {
|
||||
sudokuResult.setCellsSymbol(correctCells);
|
||||
|
||||
System.out.println("\n****************************Doku Control\n");
|
||||
SudokuPrinter.printRectangleSudoku(sudokuResult, 3, 3);
|
||||
SudokuPrinter.printRectangleSudoku(sudokuResult, 3, 3, Symbols.Russian);
|
||||
|
||||
assert (dokuResult.isSolved());
|
||||
|
||||
Solver.randomSolve(dokuToTest, rand);
|
||||
new RandomSolver().solve(dokuToTest);
|
||||
|
||||
System.out.println("\n****************************\nDoku solved");
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
|
||||
//SudokuPrinter.printRectangleSudoku(dokuToTest.getSubGrid(0), 3, 3);
|
||||
SudokuPrinter.printMultiDoku(dokuToTest, 3, 3, Symbols.Emojis);
|
||||
|
||||
assert (dokuToTest.isSolved());
|
||||
|
||||
@@ -89,14 +92,15 @@ class SolverTest {
|
||||
5, ns, ns, ns, 3, 1, 0, ns, ns);
|
||||
sudokuToTest2.setImmutableCellsSymbol(immutableCells2);
|
||||
|
||||
boolean isSolved = Solver.randomSolve(dokuToTest2, rand);
|
||||
boolean isSolved = new RandomSolver().solve(dokuToTest2);
|
||||
|
||||
assert (!isSolved);
|
||||
|
||||
MultiDoku dokuToTest3 = SudokuFactory.createBasicEmptySquareDoku(3, SudokuFactory.DEFAULT_CONSTRAINTS);
|
||||
|
||||
Solver.randomSolve(dokuToTest3, rand);
|
||||
new RandomSolver().solve(dokuToTest3);
|
||||
|
||||
SudokuPrinter.printRectangleSudoku(dokuToTest3.getSubGrid(0), 3, 3);
|
||||
//SudokuPrinter.printRectangleSudoku(dokuToTest3.getSubGrid(0), 3, 3);
|
||||
SudokuPrinter.printMultiDoku(dokuToTest3, 3, 3, Symbols.Letters);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user