Implemented the backtracking strategy for the Sudoku Solver.
JUnit tests are running. Still need to add more logic strategies.
This commit is contained in:
parent
6ad5832538
commit
cc92454cc6
18 changed files with 307 additions and 104 deletions
|
@ -8,6 +8,15 @@
|
|||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name="tu_darmstadt.sudoku.ui.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="tu_darmstadt.sudoku.ui.SettingsActivity"
|
||||
android:label="@string/title_activity_settings"
|
||||
|
@ -21,16 +30,6 @@
|
|||
</activity>
|
||||
<activity android:name="tu_darmstadt.sudoku.ui.AboutActivity" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name="tu_darmstadt.sudoku.ui.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="tu_darmstadt.sudoku.ui.LoadGameActivity" >
|
||||
</activity>
|
||||
</application>
|
||||
|
|
|
@ -10,7 +10,7 @@ import tu_darmstadt.sudoku.game.CellConflict;
|
|||
import tu_darmstadt.sudoku.game.CellConflictList;
|
||||
import tu_darmstadt.sudoku.game.GameBoard;
|
||||
import tu_darmstadt.sudoku.game.GameCell;
|
||||
import tu_darmstadt.sudoku.game.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.game.GameType;
|
||||
import tu_darmstadt.sudoku.game.ICellAction;
|
||||
import tu_darmstadt.sudoku.game.solver.Solver;
|
||||
|
@ -25,13 +25,14 @@ public class GameController {
|
|||
private int sectionHeight;
|
||||
private int sectionWidth;
|
||||
private GameBoard gameBoard;
|
||||
private ISolver solver;
|
||||
private Solver solver;
|
||||
private GameType gameType;
|
||||
private int selectedRow;
|
||||
private int selectedCol;
|
||||
private SharedPreferences settings;
|
||||
private int gameID = 0;
|
||||
private CellConflictList errorList = new CellConflictList();
|
||||
private int selectedValue;
|
||||
//private LinkedList<IModelChangeListener> listeners = new LinkedList<>();
|
||||
|
||||
// private Solver solver;
|
||||
|
@ -139,7 +140,7 @@ public class GameController {
|
|||
settings = pref;
|
||||
}
|
||||
|
||||
public GameBoard solve(GameBoard gameBoard) {
|
||||
public LinkedList<GameBoard> solve() {
|
||||
switch(gameType) {
|
||||
case Default_9x9:
|
||||
case Default_6x6:
|
||||
|
@ -150,8 +151,8 @@ public class GameController {
|
|||
throw new UnsupportedOperationException("No Solver for this GameType defined.");
|
||||
}
|
||||
|
||||
if(solver.solve()) {
|
||||
return solver.getGameBoard();
|
||||
if(solver.solve(solver.getGameBoard())) {
|
||||
return solver.getSolutions();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -228,6 +229,15 @@ public class GameController {
|
|||
return gameBoard.actionOnCells(ca,existing);
|
||||
}
|
||||
|
||||
public boolean checkIfBoardIsFilled() {
|
||||
//if(gameBoard.getEmptyCellCount() == 0) {
|
||||
// TODO: board is filled. check it for errors.
|
||||
|
||||
//return true;
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void saveGame(Context context) {
|
||||
if(settings == null) {
|
||||
return;
|
||||
|
@ -312,15 +322,34 @@ public class GameController {
|
|||
return gameBoard.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Controls for the View.
|
||||
* Select methods for Cells and Values.
|
||||
* If a value is selected while a cell is selected the value is put into the cell.
|
||||
* If no cell is selected while a value is being selected, the value gets selected,
|
||||
* and every cell selection after that will automaticly put that value into the cell.
|
||||
*
|
||||
*/
|
||||
public int getSelectedRow() {
|
||||
return selectedRow;
|
||||
}
|
||||
|
||||
public int getSelectedCol() {
|
||||
return selectedCol;
|
||||
}
|
||||
public int getSelectedValue() {
|
||||
return selectedValue;
|
||||
}
|
||||
|
||||
public void selectCell(int row, int col) {
|
||||
// TODO if there is a value selected
|
||||
// TODO should we do this in here or rather in the view?
|
||||
// we set the value directly
|
||||
//if(selectedValue != 0) {
|
||||
//}
|
||||
|
||||
if(selectedRow == row && selectedCol == col) {
|
||||
// if we select the same field 2ce -> deselect it
|
||||
selectedRow = -1;
|
||||
|
@ -332,7 +361,7 @@ public class GameController {
|
|||
}
|
||||
}
|
||||
|
||||
public void setSelectedValue(int value) {
|
||||
public void selectValue(int value) {
|
||||
if(isCellSelected()) setValue(selectedRow, selectedCol, value);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package tu_darmstadt.sudoku.controller;
|
||||
|
||||
/**
|
||||
* Created by Chris on 17.11.2015.
|
||||
*/
|
||||
public class Highscore {
|
||||
|
||||
}
|
|
@ -11,7 +11,7 @@ import java.io.IOException;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import tu_darmstadt.sudoku.game.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
|
||||
|
||||
/**
|
||||
* Created by Chris on 16.11.2015.
|
||||
|
|
|
@ -5,22 +5,24 @@ package tu_darmstadt.sudoku.controller;
|
|||
*/
|
||||
public enum Symbol {
|
||||
|
||||
Default(new char[] {'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N'}),
|
||||
Fancy(new char[] {'♪', '♫', '☼', '♥', '♦', '♣', '♠', '•', '○', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N' });
|
||||
SaveFormat(new String[] {"1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "O", "P"}),
|
||||
Default(new String[] {"1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N"}),
|
||||
Roman(new String[] {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX", "XXI", "XXII"}),
|
||||
Fancy(new String[] {"♪", "♫", "☼", "♥", "♦", "♣", "♠", "•", "○", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N" });
|
||||
|
||||
private char[] map;
|
||||
private String[] map;
|
||||
|
||||
Symbol(char[] map) {
|
||||
Symbol(String[] map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public static String getSymbol(Symbol type, int value) {
|
||||
return String.valueOf(type.map[value]);
|
||||
return (type.map[value]);
|
||||
}
|
||||
|
||||
public static int getValue(Symbol type, char c) {
|
||||
public static int getValue(Symbol type, String c) {
|
||||
for(int i = 0; i < type.map.length; i++) {
|
||||
if(type.map[i] == c) return i;
|
||||
if(type.map[i].equals(c)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package tu_darmstadt.sudoku.game;
|
||||
package tu_darmstadt.sudoku.controller.helper;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import tu_darmstadt.sudoku.controller.GameController;
|
||||
import tu_darmstadt.sudoku.controller.Symbol;
|
||||
import tu_darmstadt.sudoku.game.GameCell;
|
||||
import tu_darmstadt.sudoku.game.GameType;
|
||||
import tu_darmstadt.sudoku.game.ICellAction;
|
||||
|
||||
/**
|
||||
* Created by Chris on 17.11.2015.
|
||||
|
@ -46,7 +49,7 @@ public class GameInfoContainer {
|
|||
}
|
||||
fixedValues = new int[s.length()];
|
||||
for(int i = 0; i < s.length(); i++) {
|
||||
fixedValues[i] = Symbol.getValue(Symbol.Default, s.charAt(i))+1;
|
||||
fixedValues[i] = Symbol.getValue(Symbol.SaveFormat, String.valueOf(s.charAt(i)))+1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +64,7 @@ public class GameInfoContainer {
|
|||
}
|
||||
setValues = new int[s.length()];
|
||||
for(int i = 0; i < s.length(); i++) {
|
||||
setValues[i] = Symbol.getValue(Symbol.Default, s.charAt(i))+1;
|
||||
setValues[i] = Symbol.getValue(Symbol.SaveFormat, String.valueOf(s.charAt(i)))+1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +136,7 @@ public class GameInfoContainer {
|
|||
@Override
|
||||
public StringBuilder action(GameCell gc, StringBuilder existing) {
|
||||
if (gc.isFixed()) {
|
||||
existing.append(Symbol.getSymbol(Symbol.Default, gc.getValue() - 1));
|
||||
existing.append(Symbol.getSymbol(Symbol.SaveFormat, gc.getValue() - 1));
|
||||
} else {
|
||||
existing.append(0);
|
||||
}
|
||||
|
@ -151,7 +154,7 @@ public class GameInfoContainer {
|
|||
if (gc.isFixed() || gc.getValue() == 0) {
|
||||
existing.append(0);
|
||||
} else {
|
||||
existing.append(Symbol.getSymbol(Symbol.Default, gc.getValue() - 1));
|
||||
existing.append(Symbol.getSymbol(Symbol.SaveFormat, gc.getValue() - 1));
|
||||
}
|
||||
return existing;
|
||||
}
|
|
@ -69,6 +69,10 @@ public class GameBoard implements Cloneable {
|
|||
}
|
||||
|
||||
public LinkedList<GameCell> getRow(final int row) {
|
||||
LinkedList<GameCell> result = new LinkedList<GameCell>();
|
||||
for(int i = 0; i < size; i++) {
|
||||
|
||||
}
|
||||
return actionOnCells(new ICellAction<LinkedList<GameCell>>() {
|
||||
@Override
|
||||
public LinkedList<GameCell> action(GameCell gc, LinkedList<GameCell> existing) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import tu_darmstadt.sudoku.game.GameBoard;
|
|||
*/
|
||||
public interface ISolver {
|
||||
|
||||
public boolean solve();
|
||||
public boolean solve(GameBoard gameBoard);
|
||||
|
||||
public boolean calculateNextPossibleStep();
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
package tu_darmstadt.sudoku.game.solver;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import android.graphics.Point;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.game.CellConflict;
|
||||
import tu_darmstadt.sudoku.game.GameBoard;
|
||||
import tu_darmstadt.sudoku.game.GameCell;
|
||||
|
@ -13,6 +18,7 @@ import tu_darmstadt.sudoku.game.ICellAction;
|
|||
public class Solver implements ISolver {
|
||||
|
||||
private GameBoard gameBoard = null;
|
||||
private LinkedList<GameBoard> solutions = new LinkedList<>();
|
||||
|
||||
public Solver(GameBoard gf) {
|
||||
try {
|
||||
|
@ -36,7 +42,7 @@ public class Solver implements ISolver {
|
|||
public void setNotes(GameBoard gameBoard) {
|
||||
for(int i = 0; i < gameBoard.getSize(); i++) {
|
||||
for(int j = 0; j < gameBoard.getSize(); j++) {
|
||||
for(int k = 0; k < gameBoard.getSize(); k++) {
|
||||
for(int k = 1; k <= gameBoard.getSize(); k++) {
|
||||
gameBoard.getCell(i,j).setNote(k);
|
||||
}
|
||||
}
|
||||
|
@ -58,34 +64,92 @@ public class Solver implements ISolver {
|
|||
if(checked.contains(c.getValue())) {
|
||||
return true;
|
||||
}
|
||||
checked.add(c.getValue());
|
||||
if(c.hasValue()) {
|
||||
checked.add(c.getValue());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean solve() {
|
||||
public LinkedList<GameBoard> getSolutions() {
|
||||
return solutions;
|
||||
}
|
||||
|
||||
if(gameBoard.isSolved(new LinkedList<CellConflict>())) {
|
||||
public boolean isDone(GameBoard gameBoard) {
|
||||
for(int i = 0; i < gameBoard.getSize(); i++) {
|
||||
for(int j = 0; j < gameBoard.getSize(); j++) {
|
||||
if(!gameBoard.getCell(i,j).hasValue()) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean solve(final GameBoard gameBoard) {
|
||||
|
||||
checkSolvedCells(gameBoard);
|
||||
|
||||
String string = gameBoard.toString();
|
||||
|
||||
if(isDone(gameBoard)) {
|
||||
solutions.add(gameBoard);
|
||||
return true;
|
||||
}
|
||||
|
||||
checkSolvedCells();
|
||||
if(showPossibles(gameBoard))
|
||||
return solve(gameBoard);
|
||||
|
||||
if(showPossibles()) return solve();
|
||||
if(searchHiddenSingles(gameBoard))
|
||||
return solve(gameBoard);
|
||||
|
||||
if(searchHiddenSingles()) return solve();
|
||||
if(searchNakedPairsTriples(gameBoard))
|
||||
return solve(gameBoard);
|
||||
|
||||
if(searchNakedPairsTriples()) return solve();
|
||||
if(searchHiddenPairsTriples(gameBoard))
|
||||
return solve(gameBoard);
|
||||
|
||||
if(searchHiddenPairsTriples()) return solve();
|
||||
if(searchNakedQuads(gameBoard))
|
||||
return solve(gameBoard);
|
||||
|
||||
if(searchNakedQuads()) return solve();
|
||||
if(searchPointingPairs(gameBoard))
|
||||
return solve(gameBoard);
|
||||
|
||||
if(searchPointingPairs()) return solve();
|
||||
if(searchBoxLineReduction(gameBoard))
|
||||
return solve(gameBoard);
|
||||
|
||||
if(searchBoxLineReduction()) return solve();
|
||||
|
||||
return false;
|
||||
// if every defined strategy fails.. we have to guess
|
||||
// get the best candidate
|
||||
Point p = getBestCandidate(gameBoard);
|
||||
|
||||
// then we test every possible value for that candidate, but we do it on a cloned gameBoard
|
||||
boolean result = false;
|
||||
for(int i = 0; i < gameBoard.getSize(); i++) {
|
||||
GameCell gc = gameBoard.getCell(p.x,p.y);
|
||||
try {
|
||||
if(gc.getNotes()[i]) {
|
||||
GameBoard gameBoardCopy = gameBoard.clone();
|
||||
|
||||
GameCell copyGC = gameBoardCopy.getCell(p.x, p.y);
|
||||
|
||||
copyGC.setValue(i);
|
||||
|
||||
result = solve(gameBoardCopy);
|
||||
|
||||
//if (result) {
|
||||
// stop after we found 1 solution
|
||||
//return true;
|
||||
|
||||
// or keep going to find multiple solutions
|
||||
//}
|
||||
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} catch(CloneNotSupportedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,7 +162,28 @@ public class Solver implements ISolver {
|
|||
return gameBoard;
|
||||
}
|
||||
|
||||
public boolean showPossibles() {
|
||||
private boolean checkSolvedCells(final GameBoard gameBoard) {
|
||||
return gameBoard.actionOnCells(new ICellAction<Boolean>() {
|
||||
@Override
|
||||
public Boolean action(GameCell gc, Boolean existing) {
|
||||
int value = -1;
|
||||
if(!gc.hasValue() && gc.getNoteCount() == 1) {
|
||||
for(int i = 0; i < gameBoard.getSize(); i++) {
|
||||
if(gc.getNotes()[i]) {
|
||||
value = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gc.setValue(value);
|
||||
existing = true;
|
||||
}
|
||||
return existing;
|
||||
}}, false);
|
||||
}
|
||||
|
||||
|
||||
public boolean showPossibles(final GameBoard gameBoard) {
|
||||
boolean deletedSomething = false;
|
||||
LinkedList<GameCell> list = new LinkedList<GameCell>();
|
||||
for(int i = 0; i < gameBoard.getSize(); i++) {
|
||||
for(int j = 0; j < gameBoard.getSize(); j++) {
|
||||
|
@ -108,19 +193,21 @@ public class Solver implements ISolver {
|
|||
list.addAll(gameBoard.getRow(i));
|
||||
list.addAll(gameBoard.getColumn(j));
|
||||
list.addAll(gameBoard.getSection(i,j));
|
||||
for(int k = 0; k < gameBoard.getSize(); k++) {
|
||||
for(GameCell c : list) {
|
||||
gc.deleteNote(c.getValue());
|
||||
for(GameCell c : list) {
|
||||
for(int k = 0; k < gameBoard.getSize(); k++) {
|
||||
if(gc.getNotes()[k] && c.hasValue() && !c.equals(gc) && k+1 == c.getValue()) {
|
||||
gc.deleteNote(c.getValue());
|
||||
deletedSomething = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return deletedSomething;
|
||||
}
|
||||
|
||||
private boolean searchHiddenSingles() {
|
||||
private boolean searchHiddenSingles(final GameBoard gameBoard) {
|
||||
boolean foundHiddenSingles = false;
|
||||
|
||||
LinkedList<GameCell> list = new LinkedList<>();
|
||||
|
@ -183,40 +270,68 @@ public class Solver implements ISolver {
|
|||
return foundHiddenSingles;
|
||||
}
|
||||
|
||||
public boolean searchNakedPairsTriples() {
|
||||
|
||||
public boolean searchNakedPairsTriples(final GameBoard gameBoard) {
|
||||
return false;
|
||||
}
|
||||
public boolean searchHiddenPairsTriples() {
|
||||
public boolean searchHiddenPairsTriples(final GameBoard gameBoard) {
|
||||
return false;
|
||||
}
|
||||
public boolean searchNakedQuads() {
|
||||
public boolean searchNakedQuads(final GameBoard gameBoard) {
|
||||
return false;
|
||||
}
|
||||
public boolean searchPointingPairs() {
|
||||
public boolean searchPointingPairs(final GameBoard gameBoard) {
|
||||
return false;
|
||||
}
|
||||
public boolean searchBoxLineReduction() {
|
||||
public boolean searchBoxLineReduction(final GameBoard gameBoard) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkSolvedCells() {
|
||||
return gameBoard.actionOnCells(new ICellAction<Boolean>() {
|
||||
@Override
|
||||
public Boolean action(GameCell gc, Boolean existing) {
|
||||
int value = -1;
|
||||
if(!gc.hasValue() && gc.getNoteCount() == 1) {
|
||||
for(int i = 0; i < gameBoard.getSize(); i++) {
|
||||
if(gc.getNotes()[i]) {
|
||||
value = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gc.setValue(value);
|
||||
existing = true;
|
||||
}
|
||||
return existing;
|
||||
}}, false);
|
||||
public Point getBestCandidate(GameBoard gameBoard) {
|
||||
Point bestCandidate = new Point();
|
||||
int minimumCount = gameBoard.getSize();
|
||||
int count = 0;
|
||||
Point candidate = new Point();
|
||||
for(int i = 0; i < gameBoard.getSize(); i++) {
|
||||
|
||||
count = countUnsolved(gameBoard.getRow(i),candidate);
|
||||
if(count < minimumCount) {
|
||||
minimumCount = count;
|
||||
bestCandidate.set(candidate.x, candidate.y);
|
||||
}
|
||||
|
||||
count = countUnsolved(gameBoard.getColumn(i),candidate);
|
||||
if(count < minimumCount) {
|
||||
minimumCount = count;
|
||||
bestCandidate.set(candidate.x, candidate.y);
|
||||
}
|
||||
|
||||
count = countUnsolved(gameBoard.getSection(i),candidate);
|
||||
if(count < minimumCount) {
|
||||
minimumCount = count;
|
||||
bestCandidate.set(candidate.x, candidate.y);
|
||||
}
|
||||
|
||||
if(minimumCount == 2) {
|
||||
return bestCandidate;
|
||||
}
|
||||
}
|
||||
return bestCandidate;
|
||||
}
|
||||
|
||||
public int countUnsolved(final List<GameCell> list, Point p) {
|
||||
int count = 0;
|
||||
for(GameCell gc : list) {
|
||||
if(!gc.hasValue()) {
|
||||
count++;
|
||||
p.set(gc.getRow(), gc.getCol());
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package tu_darmstadt.sudoku.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
|
||||
import tu_darmstadt.sudoku.ui.view.R;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import java.util.List;
|
|||
|
||||
import tu_darmstadt.sudoku.controller.SaveLoadController;
|
||||
import tu_darmstadt.sudoku.controller.GameController;
|
||||
import tu_darmstadt.sudoku.game.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.game.GameType;
|
||||
import tu_darmstadt.sudoku.ui.view.R;
|
||||
import tu_darmstadt.sudoku.ui.view.SudokuFieldLayout;
|
||||
|
@ -91,7 +91,7 @@ public class GameActivity extends AppCompatActivity implements NavigationView.On
|
|||
|
||||
//set Special keys
|
||||
specialButtonLayout = (SudokuSpecialButtonLayout) findViewById(R.id.sudokuSpecialLayout);
|
||||
specialButtonLayout.setButtons(p.x,gameController,keyboard);
|
||||
specialButtonLayout.setButtons(p.x, gameController, keyboard);
|
||||
/*
|
||||
// DEBUG
|
||||
String debug = gameController.getFieldAsString();
|
||||
|
|
|
@ -18,7 +18,7 @@ import android.widget.TextView;
|
|||
import java.util.List;
|
||||
|
||||
import tu_darmstadt.sudoku.controller.SaveLoadController;
|
||||
import tu_darmstadt.sudoku.game.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.ui.view.R;
|
||||
|
||||
public class LoadGameActivity extends AppCompatActivity {
|
||||
|
|
|
@ -24,7 +24,7 @@ import android.widget.TextView;
|
|||
import java.util.List;
|
||||
|
||||
import tu_darmstadt.sudoku.controller.SaveLoadController;
|
||||
import tu_darmstadt.sudoku.game.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.game.GameType;
|
||||
import tu_darmstadt.sudoku.ui.view.R;
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ public class SudokuCellView extends View {
|
|||
p.setTextSize(mWidth / 4);
|
||||
p.setTextAlign(Paint.Align.RIGHT);
|
||||
// TODO settings: get SymbolEnum from settings
|
||||
canvas.drawText(String.valueOf(Symbol.getSymbol(symbolsToUse, i)),(mWidth*1/12)*k,(mWidth*1/12)*j,p);
|
||||
canvas.drawText(Symbol.getSymbol(symbolsToUse, i),(mWidth*1/12)*k,(mWidth*1/12)*j,p);
|
||||
/*canvas.drawText(String.valueOf(1), (mWidth * 1 / 12)*3, (mWidth* 1 / 12)*3, p);
|
||||
canvas.drawText(String.valueOf(2),(mWidth*1/12)*7, (mWidth* 1 / 12)*7,p );
|
||||
canvas.drawText(String.valueOf(3),(mWidth*1/12)*11, (mWidth* 1 / 12)*11,p );*/
|
||||
|
@ -152,7 +152,7 @@ public class SudokuCellView extends View {
|
|||
p.setTextSize(Math.min(mHeight * 3 / 4, mHeight * 3 / 4));
|
||||
p.setTextAlign(Paint.Align.CENTER);
|
||||
// TODO settings: get SymbolEnum from settings
|
||||
canvas.drawText(String.valueOf(Symbol.getSymbol(symbolsToUse, mGameCell.getValue()-1)), mHeight / 2, mHeight / 2 + mHeight / 4, p);
|
||||
canvas.drawText(Symbol.getSymbol(symbolsToUse, mGameCell.getValue()-1), mHeight / 2, mHeight / 2 + mHeight / 4, p);
|
||||
}
|
||||
|
||||
public int getRow() {
|
||||
|
|
|
@ -2,7 +2,6 @@ package tu_darmstadt.sudoku.ui.view;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
|
@ -32,7 +31,7 @@ public class SudokuKeyboardLayout extends GridLayout {
|
|||
if(notesEnabled) {
|
||||
gameController.toggleSelectedNote(btn.getValue());
|
||||
} else {
|
||||
gameController.setSelectedValue(btn.getValue());
|
||||
gameController.selectValue(btn.getValue());
|
||||
}
|
||||
gameController.saveGame(getContext());
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
android:text="@string/more_info"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/linkID"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/url"
|
||||
|
|
|
@ -3,7 +3,7 @@ package tu_darmstadt.sudoku.controller;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import tu_darmstadt.sudoku.game.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.game.GameType;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
package tu_darmstadt.sudoku.game.solver;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import tu_darmstadt.sudoku.controller.GameController;
|
||||
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
|
||||
import tu_darmstadt.sudoku.game.GameBoard;
|
||||
import tu_darmstadt.sudoku.game.GameType;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Created by Chris on 12.11.2015.
|
||||
*/
|
||||
|
@ -15,31 +23,63 @@ public class SolverTest {
|
|||
|
||||
@Before
|
||||
public void init() {
|
||||
/*controller = new GameController();
|
||||
int[][] level = {{ 5, 0, 1, 9, 0, 0, 0, 0, 0 },
|
||||
{ 2, 0, 0, 0, 0, 4, 9, 5, 0 },
|
||||
{ 3, 9, 0, 7, 0, 0, 0, 2, 6 },
|
||||
controller = new GameController();
|
||||
controller.loadLevel(new GameInfoContainer(0, GameType.Default_9x9,
|
||||
new int[]{5, 0, 1, 9, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0, 0, 4, 9, 5, 0,
|
||||
3, 9, 0, 7, 0, 0, 0, 2, 6,
|
||||
0, 3, 0, 0, 0, 1, 0, 7, 2,
|
||||
0, 0, 6, 0, 5, 7, 0, 0, 0,
|
||||
0, 7, 2, 0, 0, 9, 0, 4, 1,
|
||||
0, 0, 0, 0, 7, 0, 4, 0, 9,
|
||||
6, 4, 0, 0, 0, 0, 0, 0, 0,
|
||||
7, 0, 0, 0, 1, 0, 3, 0, 5}
|
||||
, null, null));
|
||||
|
||||
{ 0, 3, 0, 0, 0, 1, 0, 7, 2 },
|
||||
{ 0, 0, 6, 0, 5, 7, 0, 0, 0 },
|
||||
{ 0, 7, 2, 0, 0, 9, 0, 4, 1 },
|
||||
|
||||
{ 0, 0, 0, 0, 7, 0, 4, 0, 9 },
|
||||
{ 6, 4, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 7, 0, 0, 0, 1, 0, 3, 0, 5 }};
|
||||
|
||||
controller.loadLevel(GameType.icon_default_9x9,
|
||||
new int[]{0,0,0,0,4,1,0,0,0,0,6,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,3,2,0,6,0,0,0,0,0,0,0,0,0,5,0,0,4,1,7,0,0,0,0,0,0,0,0,0,0,0,2,0,0,3,0,0,0,4,8,0,0,0,0,0,0,5,0,1,0,0,0,0,0,0},
|
||||
null,
|
||||
null);*/
|
||||
/*controller.loadLevel(new GameInfoContainer(3, GameType.Default_9x9,
|
||||
new int[]{0,0,0,0,4,1,0,0,0,0,6,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,3,2,0,6,0,0,0,0,0,0,0,0,0,5,0,0,4,1,7,0,0,0,0,0,0,0,0,0,0,0,2,0,0,3,0,0,0,4,8,0,0,0,0,0,0,5,0,1,0,0,0,0,0,0}
|
||||
, null, null));*/
|
||||
}
|
||||
|
||||
//000041000060000200000000000320600000000050041700000000000200300048000000501000000
|
||||
|
||||
//501900000200004950390700026030001072006057000072009041000070409640000000700010305
|
||||
|
||||
@Test
|
||||
public void solveTest() {
|
||||
public void solveTest1() {
|
||||
LinkedList<GameBoard> result = controller.solve();
|
||||
|
||||
for(GameBoard gb : result) {
|
||||
assertEquals("[GameBoard: \n" +
|
||||
"\t[5 (0|0)] [8 (0|1)] [1 (0|2)] \t[9 (0|3)] [2 (0|4)] [6 (0|5)] \t[7 (0|6)] [3 (0|7)] [4 (0|8)] ]" +
|
||||
"\t[2 (1|0)] [6 (1|1)] [7 (1|2)] \t[1 (1|3)] [3 (1|4)] [4 (1|5)] \t[9 (1|6)] [5 (1|7)] [8 (1|8)] ]" +
|
||||
"\t[3 (2|0)] [9 (2|1)] [4 (2|2)] \t[7 (2|3)] [8 (2|4)] [5 (2|5)] \t[1 (2|6)] [2 (2|7)] [6 (2|8)] ]" +
|
||||
"\t[9 (3|0)] [3 (3|1)] [5 (3|2)] \t[8 (3|3)] [4 (3|4)] [1 (3|5)] \t[6 (3|6)] [7 (3|7)] [2 (3|8)] ]" +
|
||||
"\t[4 (4|0)] [1 (4|1)] [6 (4|2)] \t[2 (4|3)] [5 (4|4)] [7 (4|5)] \t[8 (4|6)] [9 (4|7)] [3 (4|8)] ]" +
|
||||
"\t[8 (5|0)] [7 (5|1)] [2 (5|2)] \t[3 (5|3)] [6 (5|4)] [9 (5|5)] \t[5 (5|6)] [4 (5|7)] [1 (5|8)] ]" +
|
||||
"\t[1 (6|0)] [5 (6|1)] [3 (6|2)] \t[6 (6|3)] [7 (6|4)] [2 (6|5)] \t[4 (6|6)] [8 (6|7)] [9 (6|8)] ]" +
|
||||
"\t[6 (7|0)] [4 (7|1)] [8 (7|2)] \t[5 (7|3)] [9 (7|4)] [3 (7|5)] \t[2 (7|6)] [1 (7|7)] [7 (7|8)] ]" +
|
||||
"\t[7 (8|0)] [2 (8|1)] [9 (8|2)] \t[4 (8|3)] [1 (8|4)] [8 (8|5)] \t[3 (8|6)] [6 (8|7)] [5 (8|8)] ]",
|
||||
gb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void solveTest2() {
|
||||
controller.loadLevel(new GameInfoContainer(0, GameType.Default_9x9,
|
||||
new int[]{0,0,0,0,4,1,0,0,0,0,6,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,3,2,0,6,0,0,0,0,0,0,0,0,0,5,0,0,4,1,7,0,0,0,0,0,0,0,0,0,0,0,2,0,0,3,0,0,0,4,8,0,0,0,0,0,0,5,0,1,0,0,0,0,0,0}
|
||||
, null, null));
|
||||
|
||||
LinkedList<GameBoard> result = controller.solve();
|
||||
|
||||
for(GameBoard gb : result) {
|
||||
assertEquals("[GameBoard: \n" +
|
||||
"\t[8 (0|0)] [7 (0|1)] [2 (0|2)] \t[9 (0|3)] [4 (0|4)] [1 (0|5)] \t[5 (0|6)] [6 (0|7)] [3 (0|8)] ]"+
|
||||
"\t[1 (1|0)] [6 (1|1)] [9 (1|2)] \t[5 (1|3)] [7 (1|4)] [3 (1|5)] \t[2 (1|6)] [8 (1|7)] [4 (1|8)] ]"+
|
||||
"\t[4 (2|0)] [5 (2|1)] [3 (2|2)] \t[8 (2|3)] [2 (2|4)] [6 (2|5)] \t[1 (2|6)] [9 (2|7)] [7 (2|8)] ]" +
|
||||
"\t[3 (3|0)] [2 (3|1)] [4 (3|2)] \t[6 (3|3)] [1 (3|4)] [7 (3|5)] \t[8 (3|6)] [5 (3|7)] [9 (3|8)] ]" +
|
||||
"\t[9 (4|0)] [8 (4|1)] [6 (4|2)] \t[3 (4|3)] [5 (4|4)] [2 (4|5)] \t[7 (4|6)] [4 (4|7)] [1 (4|8)] ]" +
|
||||
"\t[7 (5|0)] [1 (5|1)] [5 (5|2)] \t[4 (5|3)] [9 (5|4)] [8 (5|5)] \t[6 (5|6)] [3 (5|7)] [2 (5|8)] ]" +
|
||||
"\t[6 (6|0)] [9 (6|1)] [7 (6|2)] \t[2 (6|3)] [8 (6|4)] [4 (6|5)] \t[3 (6|6)] [1 (6|7)] [5 (6|8)] ]" +
|
||||
"\t[2 (7|0)] [4 (7|1)] [8 (7|2)] \t[1 (7|3)] [3 (7|4)] [5 (7|5)] \t[9 (7|6)] [7 (7|7)] [6 (7|8)] ]" +
|
||||
"\t[5 (8|0)] [3 (8|1)] [1 (8|2)] \t[7 (8|3)] [6 (8|4)] [9 (8|5)] \t[4 (8|6)] [2 (8|7)] [8 (8|8)] ]",
|
||||
gb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue