Undo/Redo Feature added. States are not saved through sessions. They build up for every play session you start.

This commit is contained in:
Christopher Beckmann 2015-11-24 23:59:52 +01:00
parent d2bed7b2a5
commit 31144449c7
15 changed files with 193 additions and 617 deletions

View file

@ -0,0 +1,77 @@
package tu_darmstadt.sudoku.controller;
import java.util.LinkedList;
import java.util.List;
import tu_darmstadt.sudoku.game.GameBoard;
/**
* Created by Chris on 24.11.2015.
*/
public class DoUndo {
private int activeState;
private LinkedList<GameBoard> states = new LinkedList<>();
public DoUndo(GameBoard initState) {
// we get the base state and set it as active state.
try {
states.addLast(initState.clone());
activeState = 0;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
public boolean isUnDoAvailable() {
return activeState > 0 && states.size() > 1;
}
public boolean isRedoAvailable() {
return activeState < states.size()-1;
}
public GameBoard UnDo() {
if(isUnDoAvailable()) {
return states.get(--activeState);
} else {
return null;
}
}
public GameBoard ReDo() {
if(isRedoAvailable()) {
return states.get(++activeState);
} else {
return null;
}
}
public void addState(GameBoard gameBoard) {
LinkedList<GameBoard> deleteList = new LinkedList<>();
for(int i = 0; i < states.size(); i++) {
if (i > activeState) { // 3 states // state 1 is active // means 0,[1],2
// delete rest of the list // i > activeState // i > 1 // so i = 2 will be deleted // 0 can not be deleted
deleteList.add(states.get(i));
}
}
for(GameBoard g : deleteList) {
states.removeLastOccurrence(g);
}
// then append the current state
try {
GameBoard board = gameBoard.clone();
states.addLast(board);
activeState = states.size()-1;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

View file

@ -8,7 +8,6 @@ import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import tu_darmstadt.sudoku.controller.solver.Solver;
import tu_darmstadt.sudoku.game.CellConflict;
import tu_darmstadt.sudoku.game.CellConflictList;
import tu_darmstadt.sudoku.game.GameBoard;
@ -17,9 +16,9 @@ import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
import tu_darmstadt.sudoku.game.GameDifficulty;
import tu_darmstadt.sudoku.game.GameType;
import tu_darmstadt.sudoku.game.ICellAction;
import tu_darmstadt.sudoku.game.listeners.IGameSolvedListener;
import tu_darmstadt.sudoku.game.listeners.IModelChangedListener;
import tu_darmstadt.sudoku.game.listeners.ITimerListener;
import tu_darmstadt.sudoku.game.listener.IGameSolvedListener;
import tu_darmstadt.sudoku.game.listener.IModelChangedListener;
import tu_darmstadt.sudoku.game.listener.ITimerListener;
/**
* Created by Chris on 06.11.2015.
@ -30,9 +29,7 @@ public class GameController implements IModelChangedListener {
private int sectionHeight;
private int sectionWidth;
private GameBoard gameBoard;
private Solver solver;
private int[] solution;
private LinkedList<GameBoard> solvedBoards = new LinkedList<>();
private GameType gameType;
private int selectedRow;
private int selectedCol;
@ -40,6 +37,7 @@ public class GameController implements IModelChangedListener {
private int gameID = 0;
private GameDifficulty difficulty;
private CellConflictList errorList = new CellConflictList();
private DoUndo doUndo;
private int selectedValue;
private LinkedList<IGameSolvedListener> solvedListeners = new LinkedList<>();
private boolean notifiedOnSolvedListeners = false;
@ -76,59 +74,13 @@ public class GameController implements IModelChangedListener {
}
public void loadNewLevel(GameType type, GameDifficulty difficulty) {
//Generator generator = new Generator(type, gameDifficulty);
//GameBoard randomBoard = generator.getGameBoard();
SaveLoadLevelManager saveLoadLevelManager = SaveLoadLevelManager.getInstance();
int[] level = saveLoadLevelManager.loadLevel(type, difficulty);
loadLevel(new GameInfoContainer(0, difficulty, type, level, null, null));
saveLoadLevelManager.checkAndRestock();
// TODO call methods to generate level.
//int[] generated = qqWingController.generate(type, difficulty);
//loadLevel(new GameInfoContainer(0, difficulty, type, generated, null, null));
/* switch(type) {
case Default_6x6:
loadLevel(new GameInfoContainer(1, GameDifficulty.Easy, GameType.Default_6x6,
new int[]{1,0,0,0,0,6,
4,0,6,1,0,0,
0,0,2,3,0,5,
0,4,0,0,1,0,
0,6,0,2,0,0,
0,3,0,5,0,1}, null,null));
break;
case Default_12x12:
loadLevel(new GameInfoContainer(2, GameDifficulty.Hard, GameType.Default_12x12,
new int[] {0, 2, 1, 0, 0, 6, 0, 0, 0, 8, 9, 0,
10, 0,12, 0, 0, 2, 1,11, 0, 0, 0, 6,
6, 0, 0, 4, 0,12, 0, 0, 0, 0, 2, 1,
0, 0, 0, 5, 0, 0, 0, 4,11,10, 0, 0,
0,10, 0, 1, 0, 0, 6, 0, 0, 0, 0, 0,
0, 7, 0, 0,11, 0, 0, 0, 0,12, 8, 9,
2, 1,11, 0, 0, 0, 0, 7, 0, 0, 6, 0,
0, 0, 0, 0, 0, 5, 0, 0, 4, 0,10, 0,
0, 0, 7, 3, 9, 0, 0, 0, 1, 0, 0, 0,
1, 5, 0, 0, 0, 0, 4, 0,10, 0, 0,11,
9, 0, 0, 0, 1,10, 2, 0, 0, 6, 0, 7,
0, 6,10, 0, 0, 0, 8, 0, 0, 1,12, 0}
,null, null));
break;
case Default_9x9:
case Unspecified:
default:
loadLevel(new GameInfoContainer(3, GameDifficulty.Moderate, 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));
}*/
}
public int getTime() {
@ -174,6 +126,7 @@ public class GameController implements IModelChangedListener {
gameBoard.registerOnModelChangeListener(this);
doUndo = new DoUndo(gameBoard);
// call the solve function to get the solution of this board
//qqWingController.solve(gameBoard);
}
@ -188,25 +141,8 @@ public class GameController implements IModelChangedListener {
solution = qqWingController.solve(gameBoard);
}
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) {
if(GameBoard.isValid(level)) {
gameBoard = level;
}
}*/
private void setGameType(GameType type) {
this.gameType = type;
this.size = type.getSize();
@ -328,6 +264,7 @@ public class GameController implements IModelChangedListener {
if(!c.isFixed()) {
c.setValue(0);
//notifyListeners();
return true;
}
return false;
@ -358,6 +295,9 @@ public class GameController implements IModelChangedListener {
public void toggleNote(int row, int col, int value) {
GameCell c = gameBoard.getCell(row,col);
if(c.hasValue()) {
c.setValue(0);
}
c.toggleNote(value);
//notifyListeners();
}
@ -410,15 +350,29 @@ public class GameController implements IModelChangedListener {
}
public void selectValue(int value) {
if(isValidCellSelected()) setValue(selectedRow, selectedCol, value);
if(isValidCellSelected() && getSelectedValue() != value) {
setValue(selectedRow, selectedCol, value);
// add state to undo
doUndo.addState(gameBoard);
}
}
public void deleteSelectedValue() {
if(isValidCellSelected()) deleteValue(selectedRow, selectedCol);
if(isValidCellSelected() && getSelectedValue() != 0) {
deleteValue(selectedRow, selectedCol);
// add state to undo
doUndo.addState(gameBoard);
}
}
public void toggleSelectedNote(int value) {
if(isValidCellSelected()) toggleNote(selectedRow, selectedCol, value);
if(isValidCellSelected()) {
toggleNote(selectedRow, selectedCol, value);
// add state to undo
doUndo.addState(gameBoard);
}
}
public boolean isValidCellSelected() {
@ -450,7 +404,6 @@ public class GameController implements IModelChangedListener {
//TODO disable controls and play animation in view. onSolved method is called.
}
} else {
//notifiedOnSolvedListeners = false;
// TODO: errorList now holds all the errors
// TODO: display errors .. notify some view?
@ -520,4 +473,48 @@ public class GameController implements IModelChangedListener {
}
}
public void ReDo() {
updateGameBoard(doUndo.ReDo());
}
public void UnDo() {
updateGameBoard(doUndo.UnDo());
}
public boolean isRedoAvailable() {
return doUndo.isRedoAvailable();
}
public boolean isUndoAvailable() {
return doUndo.isUnDoAvailable();
}
public void updateGameBoard(final GameBoard gameBoard) {
if(gameBoard == null) {
return;
}
for(int i = 0; i < gameBoard.getSize(); i++) {
for(int j = 0; j < gameBoard.getSize(); j++) {
GameCell other_c = gameBoard.getCell(i,j);
GameCell this_c = this.gameBoard.getCell(i,j);
if(other_c.isFixed()) {
continue;
}
if(other_c.hasValue()) {
this_c.setValue(other_c.getValue());
} else {
this_c.setValue(0);
for(int k = 0; k < gameBoard.getSize(); k++) {
if(other_c.getNotes()[k]) {
this_c.setNote(k+1);
} else {
this_c.deleteNote(k+1);
}
}
}
}
}
return;
}
}

View file

@ -1,164 +0,0 @@
package tu_darmstadt.sudoku.controller.generator;
import android.graphics.Point;
import android.support.v7.util.SortedList;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import tu_darmstadt.sudoku.controller.solver.Solver;
import tu_darmstadt.sudoku.game.GameBoard;
import tu_darmstadt.sudoku.game.GameCell;
import tu_darmstadt.sudoku.game.GameDifficulty;
import tu_darmstadt.sudoku.game.GameType;
import tu_darmstadt.sudoku.game.ICellAction;
/**
* Created by Chris on 19.11.2015.
*/
public class Generator {
private Random random;
private int size;
private int sectionHeight;
private int sectionWidth;
private GameBoard gameBoard;
public Generator(GameType type, GameDifficulty difficulty) {
this.size = type.getSize();
this.sectionHeight = type.getSectionHeight();
this.sectionWidth = type.getSectionWidth();
this.gameBoard = new GameBoard(type);
gameBoard.initCells(new int[size*size]);
setNotes(gameBoard);
// generate a random valid board.
gameBoard = generate();
// produce a level out of it.
gameBoard = createLevel(difficulty);
}
public GameBoard createLevel(GameDifficulty difficulty) {
return gameBoard;
}
public GameBoard getGameBoard() {
return gameBoard;
}
public GameBoard generate() {
random = new Random();
GameBoard workingBoard = gameBoard;
GameBoard board = gameBoard;
/*GameCell chosen = gameBoard.getCell(random.nextInt(9), random.nextInt(9));
while(chosen.getNoteCount() <= 2) {
chosen = gameBoard.getCell(random.nextInt(9), random.nextInt(9));
}*/
while(workingBoard != null && !workingBoard.isFilled()) {
// clone board
try {
workingBoard = board.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
// get all candidates
List<GameCell> candidates = getListOfCandidates(workingBoard);
// choose one of them
GameCell chosen = candidates.get(random.nextInt(candidates.size()));
// get all possible values
List<Integer> possibleValues = getPossibleValues(chosen);
// set a random value of that pool
chosen.setValue(possibleValues.get(random.nextInt(possibleValues.size())));
deleteConnectedValues(workingBoard, chosen);
Solver solver = new Solver(workingBoard);
if (solver.solve(solver.getGameBoard())) {
List<GameBoard> solutions = solver.getSolutions();
switch(solutions.size()) {
case 0: // if we get no solution .. revert change
continue;
case 1: // if we get 1 solution we are done and return the solution
return solutions.get(0);
default: // if we get more than 1 solution .. keep setting numbers
board = workingBoard;
continue;
}
} else {
}
}
return null;
}
private boolean deleteConnectedValues(final GameBoard gameBoard, final GameCell cell) {
return gameBoard.actionOnCells(new ICellAction<Boolean>() {
@Override
public Boolean action(GameCell gc, Boolean existing) {
if (!gc.hasValue() && !gc.equals(cell)) {
if (gc.getRow() == cell.getRow()
|| gc.getCol() == cell.getCol()
|| (int) (Math.floor(gc.getRow() / sectionHeight) * sectionHeight + Math.floor(gc.getCol() / sectionWidth)) ==
(int) (Math.floor(cell.getRow() / sectionHeight) * sectionHeight + Math.floor(cell.getCol() / sectionWidth))) {
gc.deleteNote(cell.getValue());
if(gc.getNoteCount() == 0) {
existing = true;
}
}
}
return existing;
}
}, false);
}
private List<Integer> getPossibleValues(GameCell c) {
List<Integer> result = new LinkedList<>();
for(int i = 0; i < size; i++) {
if(c.getNotes()[i]) {
result.add(i+1);
}
}
return result;
}
private List<GameCell> getListOfCandidates(GameBoard gameBoard) {
final ArrayList<GameCell> candidates = new ArrayList<>();
gameBoard.actionOnCells(new ICellAction<ArrayList<GameCell>>() {
@Override
public ArrayList<GameCell> action(GameCell gc, ArrayList<GameCell> existing) {
if(gc.getNoteCount() > 1) {
existing.add(gc);
}
return existing;
}
}, candidates);
return candidates;
}
private void setNotes(GameBoard gameBoard) {
for(int i = 0; i < gameBoard.getSize(); i++) {
for(int j = 0; j < gameBoard.getSize(); j++) {
for(int k = 1; k <= gameBoard.getSize(); k++) {
gameBoard.getCell(i,j).setNote(k);
}
}
}
}
}

View file

@ -1,352 +0,0 @@
package tu_darmstadt.sudoku.controller.solver;
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;
import tu_darmstadt.sudoku.game.ICellAction;
/**
* Created by Chris on 10.11.2015.
*/
public class Solver {
private GameBoard gameBoard = null;
private LinkedList<GameBoard> solutions = new LinkedList<>();
public Solver(GameBoard gf) {
try {
if(gf == null) {
throw new IllegalArgumentException("GameBoard may not be null.");
}
gameBoard = gf.clone();
} catch(CloneNotSupportedException e) {
throw new IllegalArgumentException("This GameBoard is not cloneable.", e);
}
gameBoard.reset();
if(!isSolvable(gameBoard)) {
throw new IllegalArgumentException("This GameBoard is not solveable.");
}
setNotes(gameBoard);
}
public void setNotes(GameBoard gameBoard) {
for(int i = 0; i < gameBoard.getSize(); i++) {
for(int j = 0; j < gameBoard.getSize(); j++) {
for(int k = 1; k <= gameBoard.getSize(); k++) {
gameBoard.getCell(i,j).setNote(k);
}
}
}
}
public boolean isSolvable(GameBoard gameBoard) {
for(int i = 0; i < gameBoard.getSize(); i++) {
if(hasErrors(gameBoard.getRow(i))) return false;
if(hasErrors(gameBoard.getColumn(i))) return false;
if(hasErrors(gameBoard.getSection(i))) return false;
}
return true;
}
public boolean hasErrors(LinkedList<GameCell> list) {
LinkedList<Integer> checked = new LinkedList<Integer>();
for(GameCell c : list) {
if(checked.contains(c.getValue())) {
return true;
}
if(c.hasValue()) {
checked.add(c.getValue());
}
}
return false;
}
public LinkedList<GameBoard> getSolutions() {
return solutions;
}
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;
}
if(showPossibles(gameBoard))
return solve(gameBoard);
if(isImpossible(gameBoard))
return false;
if(searchHiddenSingles(gameBoard))
return solve(gameBoard);
if(searchNakedPairsTriples(gameBoard))
return solve(gameBoard);
if(searchHiddenPairsTriples(gameBoard))
return solve(gameBoard);
if(searchNakedQuads(gameBoard))
return solve(gameBoard);
if(searchPointingPairs(gameBoard))
return solve(gameBoard);
if(searchBoxLineReduction(gameBoard))
return solve(gameBoard);
// 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+1);
result = solve(gameBoardCopy);
if(solutions.size() > 1) {
// don't search for more than 1 solution
return result;
}
//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;
}
public boolean isImpossible(GameBoard gameBoard) {
return gameBoard.actionOnCells(new ICellAction<Boolean>() {
@Override
public Boolean action(GameCell gc, Boolean existing) {
return (gc.getNoteCount() == 0 && !gc.hasValue()) ? true : existing;
}
}, false);
}
public boolean calculateNextPossibleStep() {
return false;
}
public GameBoard getGameBoard() {
return gameBoard;
}
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++) {
GameCell gc = gameBoard.getCell(i,j);
if(!gc.hasValue()) {
list.clear();
list.addAll(gameBoard.getRow(i));
list.addAll(gameBoard.getColumn(j));
list.addAll(gameBoard.getSection(i,j));
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 deletedSomething;
}
private boolean searchHiddenSingles(final GameBoard gameBoard) {
boolean foundHiddenSingles = false;
LinkedList<GameCell> list = new LinkedList<>();
for(int i = 0; i < gameBoard.getSize()*3; i++) {
int index = i % gameBoard.getSize();
int listSelector = (int)Math.floor(i / gameBoard.getSize());
if(listSelector == 0) list = gameBoard.getRow(index);
if(listSelector == 1) list = gameBoard.getColumn(index);
if(listSelector == 2) list = gameBoard.getSection(index);
LinkedList<Integer[]> possibles = new LinkedList<>();
LinkedList<Integer> notPossibles = new LinkedList<Integer>();
for(GameCell c : list) { // check all gameCells in Row
if(c.hasValue()) {
notPossibles.add(c.getValue());
continue;
}
for(int k = 0; k < gameBoard.getSize(); k++) { // check all nodes
if(c.getNotes()[k]) { // if k note active
for(int p = 0; p < possibles.size(); p++) { // check possible list
if(possibles.get(p)[2] == k+1) { // is value in possible list?
// value already exists in possible list
// add to impossibles
if(!notPossibles.contains(k+1)) {
notPossibles.add(k + 1);
}
}
}
if(!notPossibles.contains(k+1)){ // if k node is possible
possibles.add(new Integer[] {c.getRow(), c.getCol(), k+1});
}
}
}
}
// we checked a section/row/column
// now set the remaining possibles that are not impossible
boolean possible = true;
for(int p = 0; p < possibles.size(); p++) {
possible = true;
for(int np = 0; np < notPossibles.size(); np++) {
if(possibles.get(p)[2] == notPossibles.get(np)) {
// found that current possible is impossible
possible = false;
}
}
// if this is still possible then SET IT :D YAY
if(possible) {
gameBoard.getCell(possibles.get(p)[0],possibles.get(p)[1]).setValue(possibles.get(p)[2]);
foundHiddenSingles = true;
}
}
}
return foundHiddenSingles;
}
public boolean searchNakedPairsTriples(final GameBoard gameBoard) {
return false;
}
public boolean searchHiddenPairsTriples(final GameBoard gameBoard) {
return false;
}
public boolean searchNakedQuads(final GameBoard gameBoard) {
return false;
}
public boolean searchPointingPairs(final GameBoard gameBoard) {
return false;
}
public boolean searchBoxLineReduction(final GameBoard gameBoard) {
return 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 != 0 && count < minimumCount) {
minimumCount = count;
bestCandidate.set(candidate.x, candidate.y);
}
count = countUnsolved(gameBoard.getColumn(i),candidate);
if(count != 0 && count < minimumCount) {
minimumCount = count;
bestCandidate.set(candidate.x, candidate.y);
}
count = countUnsolved(gameBoard.getSection(i),candidate);
if(count != 0 && 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;
}
}

View file

@ -3,7 +3,7 @@ package tu_darmstadt.sudoku.game;
import java.util.LinkedList;
import java.util.List;
import tu_darmstadt.sudoku.game.listeners.IModelChangedListener;
import tu_darmstadt.sudoku.game.listener.IModelChangedListener;
/**
* Created by Christopher Beckmann on 06.11.2015.

View file

@ -4,7 +4,7 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import tu_darmstadt.sudoku.game.listeners.IModelChangedListener;
import tu_darmstadt.sudoku.game.listener.IModelChangedListener;
/**
* Created by Chris on 06.11.2015.
@ -174,8 +174,9 @@ public class GameCell implements Cloneable {
@Override
public GameCell clone() throws CloneNotSupportedException {
GameCell clone = (GameCell) super.clone();
clone.modelChangedListeners = new LinkedList<IModelChangedListener>();
// keep listeners .. so we can just replace the board and still have the listeners
clone.notes = (notes == null) ? null : Arrays.copyOf(notes, notes.length);
return clone;
}

View file

@ -0,0 +1,8 @@
package tu_darmstadt.sudoku.game.listener;
/**
* Created by Chris on 19.11.2015.
*/
public interface IGameSolvedListener {
public void onSolved();
}

View file

@ -1,4 +1,4 @@
package tu_darmstadt.sudoku.game.listeners;
package tu_darmstadt.sudoku.game.listener;
import tu_darmstadt.sudoku.game.GameCell;

View file

@ -1,4 +1,4 @@
package tu_darmstadt.sudoku.game.listeners;
package tu_darmstadt.sudoku.game.listener;
/**
* Created by TMZ_LToP on 20.11.2015.

View file

@ -1,11 +0,0 @@
package tu_darmstadt.sudoku.game.listeners;
import tu_darmstadt.sudoku.controller.GameController;
import tu_darmstadt.sudoku.game.GameBoard;
/**
* Created by Chris on 19.11.2015.
*/
public interface IGameSolvedListener {
public void onSolved();
}

View file

@ -23,8 +23,8 @@ import tu_darmstadt.sudoku.controller.GameController;
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
import tu_darmstadt.sudoku.game.GameDifficulty;
import tu_darmstadt.sudoku.game.GameType;
import tu_darmstadt.sudoku.game.listeners.IGameSolvedListener;
import tu_darmstadt.sudoku.game.listeners.ITimerListener;
import tu_darmstadt.sudoku.game.listener.IGameSolvedListener;
import tu_darmstadt.sudoku.game.listener.ITimerListener;
import tu_darmstadt.sudoku.ui.view.R;
import tu_darmstadt.sudoku.ui.view.SudokuFieldLayout;
import tu_darmstadt.sudoku.ui.view.SudokuKeyboardLayout;

View file

@ -13,10 +13,10 @@ import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
@ -32,6 +32,7 @@ import java.util.TimeZone;
import tu_darmstadt.sudoku.controller.SaveLoadGameStateController;
import tu_darmstadt.sudoku.controller.helper.GameInfoContainer;
import tu_darmstadt.sudoku.game.GameDifficulty;
import tu_darmstadt.sudoku.ui.listener.IDeleteDialogFragmentListener;
import tu_darmstadt.sudoku.ui.view.R;
public class LoadGameActivity extends AppCompatActivity implements IDeleteDialogFragmentListener {
@ -46,11 +47,26 @@ public class LoadGameActivity extends AppCompatActivity implements IDeleteDialog
setContentView(R.layout.activity_load_game);
android.support.v7.app.ActionBar actionBar = getSupportActionBar();
actionBar.setTitle(R.string.menu_continue_game);
actionBar.setDisplayHomeAsUpEnabled(true);
settings = PreferenceManager.getDefaultSharedPreferences(this);
init();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
public void init() {
SaveLoadGameStateController saveLoadGameStateController = new SaveLoadGameStateController(this, settings);

View file

@ -1,4 +1,4 @@
package tu_darmstadt.sudoku.ui;
package tu_darmstadt.sudoku.ui.listener;
import android.app.DialogFragment;

View file

@ -42,15 +42,17 @@ public class SudokuSpecialButtonLayout extends LinearLayout {
keyboard.toggleNotesEnabled();
break;
case Do:
// TODO: not implemented
gameController.ReDo();
gameController.saveGame(getContext());
break;
case Undo:
// TODO: not implemented
gameController.UnDo();
gameController.saveGame(getContext());
break;
case Hint:
if(gameController.isValidCellSelected()) {
int[] solved = gameController.solve();
// TODO test every placed value so far
// TODO test every placed value so far? Or just reveal current selected?
// and reveal the selected value.
gameController.selectValue(solved[row * gameController.getSize() + col]);
@ -79,7 +81,7 @@ public class SudokuSpecialButtonLayout extends LinearLayout {
fixedButtons = new SudokuButton[fixedButtonsCount];
LayoutParams p;
int i = 0;
ArrayList<SudokuButtonType> type = (ArrayList<SudokuButtonType>) SudokuButtonType.getSpecialButtons();
//ArrayList<SudokuButtonType> type = (ArrayList<SudokuButtonType>) SudokuButtonType.getSpecialButtons();
for (SudokuButtonType t : SudokuButtonType.getSpecialButtons()){
fixedButtons[i] = new SudokuButton(getContext(),null);
p = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,1);

View file

@ -67,4 +67,6 @@
<string name="loadgame_delete_confirm">Delete</string>
<string name="loadgame_delete_cancel">Cancel</string>
</resources>