Tried to integrate the QQGenerator. It's somehow working for 9x9 Games, but all the others are not working yet. Have to look at that at again.
This commit is contained in:
parent
fc992778a0
commit
2a652c7e12
14 changed files with 2110 additions and 23 deletions
|
@ -9,6 +9,7 @@ import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.logging.Handler;
|
import java.util.logging.Handler;
|
||||||
|
|
||||||
|
import tu_darmstadt.sudoku.controller.qqwing.QQWing;
|
||||||
import tu_darmstadt.sudoku.controller.solver.Solver;
|
import tu_darmstadt.sudoku.controller.solver.Solver;
|
||||||
import tu_darmstadt.sudoku.game.CellConflict;
|
import tu_darmstadt.sudoku.game.CellConflict;
|
||||||
import tu_darmstadt.sudoku.game.CellConflictList;
|
import tu_darmstadt.sudoku.game.CellConflictList;
|
||||||
|
@ -32,6 +33,7 @@ public class GameController implements IModelChangedListener {
|
||||||
private int sectionWidth;
|
private int sectionWidth;
|
||||||
private GameBoard gameBoard;
|
private GameBoard gameBoard;
|
||||||
private Solver solver;
|
private Solver solver;
|
||||||
|
private int[] solution;
|
||||||
private LinkedList<GameBoard> solvedBoards = new LinkedList<>();
|
private LinkedList<GameBoard> solvedBoards = new LinkedList<>();
|
||||||
private GameType gameType;
|
private GameType gameType;
|
||||||
private int selectedRow;
|
private int selectedRow;
|
||||||
|
@ -49,6 +51,7 @@ public class GameController implements IModelChangedListener {
|
||||||
private int time = 0;
|
private int time = 0;
|
||||||
private LinkedList<ITimerListener> timerListeners = new LinkedList<>();
|
private LinkedList<ITimerListener> timerListeners = new LinkedList<>();
|
||||||
private boolean timerRunning = false;
|
private boolean timerRunning = false;
|
||||||
|
private QQWingController qqWingController = new QQWingController();
|
||||||
|
|
||||||
// private Solver solver;
|
// private Solver solver;
|
||||||
// private SudokuGenerator generator;
|
// private SudokuGenerator generator;
|
||||||
|
@ -73,13 +76,15 @@ public class GameController implements IModelChangedListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadNewLevel(GameType type, GameDifficulty difficulty) {
|
public void loadNewLevel(GameType type, GameDifficulty difficulty) {
|
||||||
//Generator generator = new Generator(type, difficulty);
|
//Generator generator = new Generator(type, gameDifficulty);
|
||||||
//GameBoard randomBoard = generator.getGameBoard();
|
//GameBoard randomBoard = generator.getGameBoard();
|
||||||
|
|
||||||
|
|
||||||
// TODO call methods to generate level.
|
// TODO call methods to generate level.
|
||||||
|
int[] generated = qqWingController.generate(type, difficulty);
|
||||||
|
loadLevel(new GameInfoContainer(0, difficulty, type, generated, null, null));
|
||||||
|
|
||||||
switch(type) {
|
/* switch(type) {
|
||||||
case Default_6x6:
|
case Default_6x6:
|
||||||
loadLevel(new GameInfoContainer(1, GameDifficulty.Easy, GameType.Default_6x6,
|
loadLevel(new GameInfoContainer(1, GameDifficulty.Easy, GameType.Default_6x6,
|
||||||
new int[]{1,0,0,0,0,6,
|
new int[]{1,0,0,0,0,6,
|
||||||
|
@ -119,7 +124,7 @@ public class GameController implements IModelChangedListener {
|
||||||
6, 4, 0, 0, 0, 0, 0, 0, 0,
|
6, 4, 0, 0, 0, 0, 0, 0, 0,
|
||||||
7, 0, 0, 0, 1, 0, 3, 0, 5}
|
7, 0, 0, 0, 1, 0, 3, 0, 5}
|
||||||
, null, null));
|
, null, null));
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTime() {
|
public int getTime() {
|
||||||
|
@ -166,24 +171,30 @@ public class GameController implements IModelChangedListener {
|
||||||
gameBoard.registerOnModelChangeListener(this);
|
gameBoard.registerOnModelChangeListener(this);
|
||||||
|
|
||||||
// call the solve function to get the solution of this board
|
// call the solve function to get the solution of this board
|
||||||
solve();
|
//qqWingController.solve(gameBoard);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSettings(SharedPreferences pref) {
|
public void setSettings(SharedPreferences pref) {
|
||||||
settings = pref;
|
settings = pref;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedList<GameBoard> solve() {
|
public int[] solve() {
|
||||||
if(solvedBoards.size() == 0) {
|
|
||||||
|
|
||||||
solver = new Solver(gameBoard);
|
if(solution == null) {
|
||||||
|
solution = qqWingController.solve(gameBoard);
|
||||||
if (solver.solve(solver.getGameBoard())) {
|
|
||||||
solvedBoards.addAll(solver.getSolutions());
|
|
||||||
return solvedBoards;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return solvedBoards;
|
return solution;
|
||||||
|
|
||||||
|
// if(solvedBoards.size() == 0) {
|
||||||
|
//
|
||||||
|
// solver = new Solver(gameBoard);
|
||||||
|
//
|
||||||
|
// if (solver.solve(solver.getGameBoard())) {
|
||||||
|
// solvedBoards.addAll(solver.getSolutions());
|
||||||
|
// return solvedBoards;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return solvedBoards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public boolean loadLevel(GameBoard level) {
|
/*public boolean loadLevel(GameBoard level) {
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
package tu_darmstadt.sudoku.controller;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.atomic.AtomicIntegerArray;
|
||||||
|
|
||||||
|
import tu_darmstadt.sudoku.controller.qqwing.Action;
|
||||||
|
import tu_darmstadt.sudoku.controller.qqwing.PrintStyle;
|
||||||
|
import tu_darmstadt.sudoku.controller.qqwing.QQWing;
|
||||||
|
import tu_darmstadt.sudoku.controller.qqwing.Symmetry;
|
||||||
|
import tu_darmstadt.sudoku.game.GameBoard;
|
||||||
|
import tu_darmstadt.sudoku.game.GameDifficulty;
|
||||||
|
import tu_darmstadt.sudoku.game.GameType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Chris on 21.11.2015.
|
||||||
|
*/
|
||||||
|
public class QQWingController {
|
||||||
|
|
||||||
|
private static final String NL = System.getProperties().getProperty("line.separator");
|
||||||
|
|
||||||
|
final QQWingOptions opts = new QQWingOptions();
|
||||||
|
|
||||||
|
private int[] level;
|
||||||
|
private int[] solution;
|
||||||
|
private int[] generated;
|
||||||
|
private boolean solveImpossible = false;
|
||||||
|
|
||||||
|
public int[] generate(GameType type, GameDifficulty difficulty) {
|
||||||
|
// TODO: GameType options.
|
||||||
|
opts.gameDifficulty = difficulty;
|
||||||
|
opts.action = Action.GENERATE;
|
||||||
|
doAction(type);
|
||||||
|
return generated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] solve(GameBoard gameBoard) {
|
||||||
|
|
||||||
|
level = new int[gameBoard.getSize()*gameBoard.getSize()];
|
||||||
|
solveImpossible = false;
|
||||||
|
|
||||||
|
for(int i = 0; i < gameBoard.getSize(); i++) {
|
||||||
|
for(int j = 0; j < gameBoard.getSize(); j++) {
|
||||||
|
if(gameBoard.getCell(i,j).isFixed()) {
|
||||||
|
level[gameBoard.getSize() * i + j] = gameBoard.getCell(i,j).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.action = Action.SOLVE;
|
||||||
|
opts.printSolution = true;
|
||||||
|
doAction(gameBoard.getGameType());
|
||||||
|
return solution;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doAction(final GameType gameType) {
|
||||||
|
// The number of puzzles solved or generated.
|
||||||
|
final AtomicInteger puzzleCount = new AtomicInteger(0);
|
||||||
|
final AtomicBoolean done = new AtomicBoolean(false);
|
||||||
|
final AtomicIntegerArray result = new AtomicIntegerArray(new int[gameType.getSize()*gameType.getSize()]);
|
||||||
|
|
||||||
|
Thread[] threads = new Thread[opts.threads];
|
||||||
|
for (int threadCount = 0; threadCount < threads.length; threadCount++) {
|
||||||
|
threads[threadCount] = new Thread(
|
||||||
|
new Runnable() {
|
||||||
|
|
||||||
|
// Create a new puzzle board
|
||||||
|
// and set the options
|
||||||
|
private QQWing ss = createQQWing();
|
||||||
|
|
||||||
|
private QQWing createQQWing() {
|
||||||
|
QQWing ss = new QQWing(gameType);
|
||||||
|
ss.setRecordHistory(opts.printHistory || opts.printInstructions || opts.printStats || opts.gameDifficulty != GameDifficulty.Unspecified);
|
||||||
|
ss.setLogHistory(opts.logHistory);
|
||||||
|
ss.setPrintStyle(opts.printStyle);
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Solve puzzle or generate puzzles
|
||||||
|
// until end of input for solving, or
|
||||||
|
// until we have generated the specified number.
|
||||||
|
while (!done.get()) {
|
||||||
|
|
||||||
|
// iff something has been printed for this
|
||||||
|
// particular puzzle
|
||||||
|
StringBuilder output = new StringBuilder();
|
||||||
|
|
||||||
|
// Record whether the puzzle was possible or
|
||||||
|
// not,
|
||||||
|
// so that we don't try to solve impossible
|
||||||
|
// givens.
|
||||||
|
boolean havePuzzle = false;
|
||||||
|
|
||||||
|
if (opts.action == Action.GENERATE) {
|
||||||
|
// Generate a puzzle
|
||||||
|
havePuzzle = ss.generatePuzzleSymmetry(opts.symmetry);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Read the next puzzle on STDIN
|
||||||
|
int[] puzzle = new int[QQWing.BOARD_SIZE];
|
||||||
|
if (getPuzzleToSolve(puzzle)) {
|
||||||
|
havePuzzle = ss.setPuzzle(puzzle);
|
||||||
|
if (havePuzzle) {
|
||||||
|
puzzleCount.getAndDecrement();
|
||||||
|
} else {
|
||||||
|
// TODO: Puzzle to solve is impossible.
|
||||||
|
solveImpossible = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Set loop to terminate when nothing is
|
||||||
|
// left on STDIN
|
||||||
|
havePuzzle = false;
|
||||||
|
done.set(true);
|
||||||
|
}
|
||||||
|
puzzle = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int solutions = 0;
|
||||||
|
|
||||||
|
if (havePuzzle) {
|
||||||
|
|
||||||
|
// Count the solutions if requested.
|
||||||
|
// (Must be done before solving, as it would
|
||||||
|
// mess up the stats.)
|
||||||
|
if (opts.countSolutions) {
|
||||||
|
solutions = ss.countSolutions();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solve the puzzle
|
||||||
|
if (opts.printSolution || opts.printHistory || opts.printStats || opts.printInstructions || opts.gameDifficulty != GameDifficulty.Unspecified) {
|
||||||
|
ss.solve();
|
||||||
|
solution = ss.getSolution();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bail out if it didn't meet the gameDifficulty
|
||||||
|
// standards for generation
|
||||||
|
if (opts.action == Action.GENERATE) {
|
||||||
|
if (opts.gameDifficulty != GameDifficulty.Unspecified && opts.gameDifficulty != ss.getDifficulty()) {
|
||||||
|
havePuzzle = false;
|
||||||
|
// check if other threads have
|
||||||
|
// finished the job
|
||||||
|
if (puzzleCount.get() >= opts.numberToGenerate) {
|
||||||
|
done.set(true);
|
||||||
|
generated = ss.getPuzzle();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int numDone = puzzleCount.incrementAndGet();
|
||||||
|
if (numDone >= opts.numberToGenerate) {
|
||||||
|
done.set(true);
|
||||||
|
generated = ss.getPuzzle();
|
||||||
|
}
|
||||||
|
if (numDone > opts.numberToGenerate)
|
||||||
|
havePuzzle = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("QQWing", "Exception Occured", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
threads[threadCount].start();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < threads.length; i++) {
|
||||||
|
try {
|
||||||
|
threads[i].join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class QQWingOptions {
|
||||||
|
// defaults for options
|
||||||
|
boolean printPuzzle = false;
|
||||||
|
boolean printSolution = false;
|
||||||
|
boolean printHistory = false;
|
||||||
|
boolean printInstructions = false;
|
||||||
|
boolean timer = false;
|
||||||
|
boolean countSolutions = false;
|
||||||
|
Action action = Action.NONE;
|
||||||
|
boolean logHistory = false;
|
||||||
|
PrintStyle printStyle = PrintStyle.READABLE;
|
||||||
|
int numberToGenerate = 1;
|
||||||
|
boolean printStats = false;
|
||||||
|
GameDifficulty gameDifficulty = GameDifficulty.Unspecified;
|
||||||
|
Symmetry symmetry = Symmetry.NONE;
|
||||||
|
int threads = Runtime.getRuntime().availableProcessors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long getMicroseconds() {
|
||||||
|
return new Date().getTime() * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getPuzzleToSolve(int[] puzzle) {
|
||||||
|
if(level != null) {
|
||||||
|
puzzle = level;
|
||||||
|
level = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import tu_darmstadt.sudoku.game.GameDifficulty;
|
||||||
* Created by TMZ_LToP on 19.11.2015.
|
* Created by TMZ_LToP on 19.11.2015.
|
||||||
*/
|
*/
|
||||||
public class SaveLoadStatistics {
|
public class SaveLoadStatistics {
|
||||||
//Difficulty, time, gamemode, #hints, AvTime, amountOf Games per Difficulty,
|
//GameDifficulty, time, gamemode, #hints, AvTime, amountOf Games per GameDifficulty,
|
||||||
public SaveLoadStatistics(TimeContainer t,GameDifficulty difficulty,int hints){
|
public SaveLoadStatistics(TimeContainer t,GameDifficulty difficulty,int hints){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// @formatter:off
|
||||||
|
/*
|
||||||
|
* qqwing - Sudoku solver and generator
|
||||||
|
* Copyright (C) 2014 Stephen Ostermiller
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
// @formatter:on
|
||||||
|
package tu_darmstadt.sudoku.controller.qqwing;
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
|
NONE,
|
||||||
|
GENERATE,
|
||||||
|
SOLVE
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
// @formatter:off
|
||||||
|
/*
|
||||||
|
* qqwing - Sudoku solver and generator
|
||||||
|
* Copyright (C) 2014 Stephen Ostermiller
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
// @formatter:on
|
||||||
|
package tu_darmstadt.sudoku.controller.qqwing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* While solving the puzzle, log steps taken in a log item. This is useful for
|
||||||
|
* later printing out the solve history or gathering statistics about how hard
|
||||||
|
* the puzzle was to solve.
|
||||||
|
*/
|
||||||
|
public class LogItem {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The recursion level at which this item was gathered. Used for backing out
|
||||||
|
* log items solve branches that don't lead to a solution.
|
||||||
|
*/
|
||||||
|
private int round;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of log message that will determine the message printed.
|
||||||
|
*/
|
||||||
|
private LogType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value that was set by the operation (or zero for no value)
|
||||||
|
*/
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* position on the board at which the value (if any) was set.
|
||||||
|
*/
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
public LogItem(int r, LogType t) {
|
||||||
|
init(r, t, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LogItem(int r, LogType t, int v, int p) {
|
||||||
|
init(r, t, v, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(int r, LogType t, int v, int p) {
|
||||||
|
round = r;
|
||||||
|
type = t;
|
||||||
|
value = v;
|
||||||
|
position = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRound() {
|
||||||
|
return round;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of this log item.
|
||||||
|
*/
|
||||||
|
public LogType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print() {
|
||||||
|
System.out.print(toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the row (1 indexed), or -1 if no row
|
||||||
|
*/
|
||||||
|
public int getRow() {
|
||||||
|
if (position <= -1) return -1;
|
||||||
|
return QQWing.cellToRow(position) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the column (1 indexed), or -1 if no column
|
||||||
|
*/
|
||||||
|
public int getColumn() {
|
||||||
|
if (position <= -1) return -1;
|
||||||
|
return QQWing.cellToColumn(position) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position (0-80) on the board or -1 if no position
|
||||||
|
*/
|
||||||
|
public int getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value, or -1 if no value
|
||||||
|
*/
|
||||||
|
public int getValue() {
|
||||||
|
if (value <= 0) return -1;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the current log item. The message used is determined by the type of
|
||||||
|
* log item.
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Round: ").append(getRound());
|
||||||
|
sb.append(" - ");
|
||||||
|
sb.append(getType().getDescription());
|
||||||
|
if (value > 0 || position > -1) {
|
||||||
|
sb.append(" (");
|
||||||
|
if (position > -1) {
|
||||||
|
sb.append("Row: ").append(getRow()).append(" - Column: ").append(getColumn());
|
||||||
|
}
|
||||||
|
if (value > 0) {
|
||||||
|
if (position > -1) sb.append(" - ");
|
||||||
|
sb.append("Value: ").append(getValue());
|
||||||
|
}
|
||||||
|
sb.append(")");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getDescription();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
// @formatter:off
|
||||||
|
/*
|
||||||
|
* qqwing - Sudoku solver and generator
|
||||||
|
* Copyright (C) 2014 Stephen Ostermiller
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
// @formatter:on
|
||||||
|
package tu_darmstadt.sudoku.controller.qqwing;
|
||||||
|
|
||||||
|
public enum LogType {
|
||||||
|
GIVEN("Mark given"),
|
||||||
|
SINGLE("Mark only possibility for cell"),
|
||||||
|
HIDDEN_SINGLE_ROW("Mark single possibility for value in row"),
|
||||||
|
HIDDEN_SINGLE_COLUMN("Mark single possibility for value in column"),
|
||||||
|
HIDDEN_SINGLE_SECTION("Mark single possibility for value in section"),
|
||||||
|
GUESS("Mark guess (start round)"),
|
||||||
|
ROLLBACK("Roll back round"),
|
||||||
|
NAKED_PAIR_ROW("Remove possibilities for naked pair in row"),
|
||||||
|
NAKED_PAIR_COLUMN("Remove possibilities for naked pair in column"),
|
||||||
|
NAKED_PAIR_SECTION("Remove possibilities for naked pair in section"),
|
||||||
|
POINTING_PAIR_TRIPLE_ROW("Remove possibilities for row because all values are in one section"),
|
||||||
|
POINTING_PAIR_TRIPLE_COLUMN("Remove possibilities for column because all values are in one section"),
|
||||||
|
ROW_BOX("Remove possibilities for section because all values are in one row"),
|
||||||
|
COLUMN_BOX("Remove possibilities for section because all values are in one column"),
|
||||||
|
HIDDEN_PAIR_ROW("Remove possibilities from hidden pair in row"),
|
||||||
|
HIDDEN_PAIR_COLUMN("Remove possibilities from hidden pair in column"),
|
||||||
|
HIDDEN_PAIR_SECTION("Remove possibilities from hidden pair in section");
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private LogType(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
// @formatter:off
|
||||||
|
/*
|
||||||
|
* qqwing - Sudoku solver and generator
|
||||||
|
* Copyright (C) 2014 Stephen Ostermiller
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
// @formatter:on
|
||||||
|
package tu_darmstadt.sudoku.controller.qqwing;
|
||||||
|
|
||||||
|
public enum PrintStyle {
|
||||||
|
ONE_LINE,
|
||||||
|
COMPACT,
|
||||||
|
READABLE,
|
||||||
|
CSV
|
||||||
|
};
|
1567
app/src/main/java/tu_darmstadt/sudoku/controller/qqwing/QQWing.java
Normal file
1567
app/src/main/java/tu_darmstadt/sudoku/controller/qqwing/QQWing.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,47 @@
|
||||||
|
// @formatter:off
|
||||||
|
/*
|
||||||
|
* qqwing - Sudoku solver and generator
|
||||||
|
* Copyright (C) 2014 Stephen Ostermiller
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
// @formatter:on
|
||||||
|
package tu_darmstadt.sudoku.controller.qqwing;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public enum Symmetry {
|
||||||
|
NONE,
|
||||||
|
ROTATE90,
|
||||||
|
ROTATE180,
|
||||||
|
MIRROR,
|
||||||
|
FLIP,
|
||||||
|
RANDOM;
|
||||||
|
|
||||||
|
public static Symmetry get(String s) {
|
||||||
|
if (s == null) return null;
|
||||||
|
try {
|
||||||
|
s = s.toUpperCase(Locale.ENGLISH);
|
||||||
|
return valueOf(s);
|
||||||
|
} catch (IllegalArgumentException aix) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
String name = toString();
|
||||||
|
return name.substring(0, 1) + name.substring(1).toLowerCase(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,10 @@ public class GameBoard implements Cloneable {
|
||||||
field = new GameCell[size][size];
|
field = new GameCell[size][size];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GameType getGameType() {
|
||||||
|
return gameType;
|
||||||
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
actionOnCells(new ICellAction<Boolean>() {
|
actionOnCells(new ICellAction<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,6 +11,7 @@ import tu_darmstadt.sudoku.ui.view.R;
|
||||||
*/
|
*/
|
||||||
public enum GameDifficulty {
|
public enum GameDifficulty {
|
||||||
|
|
||||||
|
Unspecified(R.string.gametype_unspecified),
|
||||||
Easy(R.string.difficulty_easy),
|
Easy(R.string.difficulty_easy),
|
||||||
Moderate(R.string.difficulty_moderate),
|
Moderate(R.string.difficulty_moderate),
|
||||||
Hard(R.string.difficulty_hard);
|
Hard(R.string.difficulty_hard);
|
||||||
|
|
|
@ -49,14 +49,11 @@ public class SudokuSpecialButtonLayout extends LinearLayout {
|
||||||
break;
|
break;
|
||||||
case Hint:
|
case Hint:
|
||||||
if(gameController.isValidCellSelected()) {
|
if(gameController.isValidCellSelected()) {
|
||||||
LinkedList<GameBoard> solved = gameController.solve();
|
int[] solved = gameController.solve();
|
||||||
if(solved.size() >= 1) {
|
// TODO test every placed value so far
|
||||||
GameBoard solvedBoard = solved.get(0);
|
|
||||||
// TODO test every placed value so far
|
|
||||||
|
|
||||||
// and reveal the selected value.
|
// and reveal the selected value.
|
||||||
gameController.selectValue(solvedBoard.getCell(row, col).getValue());
|
gameController.selectValue(solved[row * gameController.getSize() + col]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NumberOrCellFirst:
|
case NumberOrCellFirst:
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<!-- New Game -->
|
<!-- New Game -->
|
||||||
<string name="start_game">Spiel starten</string>
|
<string name="start_game">Spiel starten</string>
|
||||||
|
|
||||||
<!-- ###Difficulty### -->
|
<!-- ###GameDifficulty### -->
|
||||||
<string name="difficulty_easy">Leicht</string>
|
<string name="difficulty_easy">Leicht</string>
|
||||||
<string name="difficulty_moderate">Normal</string>
|
<string name="difficulty_moderate">Normal</string>
|
||||||
<string name="difficulty_hard">Schwer</string>
|
<string name="difficulty_hard">Schwer</string>
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
<string name="more_info">More information can be found on:</string>
|
<string name="more_info">More information can be found on:</string>
|
||||||
<string name="url"><a href="https://www.secuso.informatik.tu-darmstadt.de/en/research/results/">https://www.secuso.org</a></string>
|
<string name="url"><a href="https://www.secuso.informatik.tu-darmstadt.de/en/research/results/">https://www.secuso.org</a></string>
|
||||||
|
|
||||||
<!-- ###Difficulty### -->
|
<!-- ###GameDifficulty### -->
|
||||||
<string name="difficulty_easy">Easy</string>
|
<string name="difficulty_easy">Easy</string>
|
||||||
<string name="difficulty_moderate">Moderate</string>
|
<string name="difficulty_moderate">Moderate</string>
|
||||||
<string name="difficulty_hard">Hard</string>
|
<string name="difficulty_hard">Hard</string>
|
||||||
|
|
Loading…
Reference in a new issue