diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 6564d52..94a25f7 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2948c5e..c429233 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -8,15 +8,6 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
-
listeners = new LinkedList<>();
-// private SudokuSolver solver;
+// private Default9x9Solver solver;
// private SudokuGenerator generator;
public GameController() {
@@ -36,6 +40,8 @@ public class GameController {
}
}*/
+
+
public void setValue(int row, int col, int value) {
GameCell cell = gameField.getCell(row, col);
if (!cell.isFixed() && isValidNumber(value)) {
@@ -47,13 +53,14 @@ public class GameController {
updateList.addAll(gameField.getRow(cell.getRow()));
updateList.addAll(gameField.getColumn(cell.getCol()));
updateList.addAll(gameField.getSection(cell.getRow(), cell.getCol()));
- deleteNote(updateList, value);
+ deleteNotes(updateList, value);
}
-
}
}
- public void deleteNote(List updateList, int value) {
+
+
+ public void deleteNotes(List updateList, int value) {
for(GameCell c : updateList) {
c.deleteNote(value);
}
@@ -125,6 +132,50 @@ public class GameController {
return errorList;
}
+ public void resetLevel() {
+ gameField.actionOnCells(new ICellAction() {
+ @Override
+ public Boolean action(GameCell gc, Boolean existing) {
+ gc.reset();
+ return true;
+ }
+ }, true);
+ notifyListeners();
+ }
+
+ public boolean deleteValue(int row, int col) {
+ GameCell c = gameField.getCell(row,col);
+ if(!c.isFixed()) {
+ c.setValue(0);
+ notifyListeners();
+ return true;
+ }
+ return false;
+ }
+
+ public void setNote(int row, int col, int value) {
+ GameCell c = gameField.getCell(row,col);
+ c.setNote(value);
+ notifyListeners();
+ }
+
+ public boolean[] getNotes(int row, int col) {
+ GameCell c = gameField.getCell(row,col);
+ return c.getNotes().clone();
+ }
+
+ public void deleteNote(int row, int col, int value) {
+ GameCell c = gameField.getCell(row,col);
+ c.deleteNote(value);
+ notifyListeners();
+ }
+
+ public void toggleNote(int row, int col, int value) {
+ GameCell c = gameField.getCell(row,col);
+ c.toggleNote(value);
+ notifyListeners();
+ }
+
/** Debug only method
*
* @return the Field represented as a String
@@ -132,4 +183,17 @@ public class GameController {
public String getFieldAsString() {
return gameField.toString();
}
+
+ public void registerListener(IModelChangeListener l) {
+ if(!listeners.contains(l)) {
+ listeners.add(l);
+ }
+ }
+
+ public void notifyListeners() {
+ for(IModelChangeListener l : listeners) {
+ l.onModelChanged();
+ }
+ }
+
}
diff --git a/app/src/main/java/tu_darmstadt/sudoku/controller/IModelChangeListener.java b/app/src/main/java/tu_darmstadt/sudoku/controller/IModelChangeListener.java
new file mode 100644
index 0000000..f551e96
--- /dev/null
+++ b/app/src/main/java/tu_darmstadt/sudoku/controller/IModelChangeListener.java
@@ -0,0 +1,8 @@
+package tu_darmstadt.sudoku.controller;
+
+/**
+ * Created by Chris on 11.11.2015.
+ */
+public interface IModelChangeListener {
+ public void onModelChanged();
+}
diff --git a/app/src/main/java/tu_darmstadt/sudoku/game/GameCell.java b/app/src/main/java/tu_darmstadt/sudoku/game/GameCell.java
index 202bf8b..3593041 100644
--- a/app/src/main/java/tu_darmstadt/sudoku/game/GameCell.java
+++ b/app/src/main/java/tu_darmstadt/sudoku/game/GameCell.java
@@ -1,14 +1,17 @@
package tu_darmstadt.sudoku.game;
+import java.util.Arrays;
+
/**
* Created by Chris on 06.11.2015.
*/
-public class GameCell {
+public class GameCell implements Cloneable {
private int row = 0;
private int col = 0;
private int value = 0;
private boolean fixed = false;
+ private int noteCount = 0;
private boolean notes[];
private int size = 0;
@@ -59,18 +62,28 @@ public class GameCell {
* @param val the value to be toggled.
*/
public void toggleNote(int val) {
- if(!isFixed())
+ if(!isFixed()) {
+ noteCount = notes[val - 1] ? noteCount - 1 : noteCount + 1;
notes[val - 1] = !notes[val - 1];
+ }
}
public void setNote(int val) {
- if(!isFixed())
+ if(!isFixed()) {
+ noteCount = notes[val - 1] ? noteCount : noteCount + 1;
notes[val - 1] = true;
+ }
}
public void deleteNote(int val) {
- if(!isFixed())
+ if(!isFixed()) {
+ noteCount = notes[val - 1] ? noteCount - 1 : noteCount;
notes[val - 1] = false;
+ }
+ }
+
+ public int getNoteCount() {
+ return noteCount;
}
public boolean[] getNotes() {
@@ -81,6 +94,7 @@ public class GameCell {
* Clear the notes array (set everything to false).
*/
public void deleteNotes() {
+ noteCount = 0;
notes = new boolean[size];
}
@@ -134,4 +148,19 @@ public class GameCell {
return sb.toString();
}
+
+ public Boolean reset() {
+ if(isFixed()) {
+ return false;
+ }
+ setValue(0);
+ return true;
+ }
+
+ @Override
+ public GameCell clone() throws CloneNotSupportedException {
+ GameCell clone = (GameCell) super.clone();
+ clone.notes = (notes == null) ? null : Arrays.copyOf(notes, notes.length);
+ return clone;
+ }
}
diff --git a/app/src/main/java/tu_darmstadt/sudoku/game/GameField.java b/app/src/main/java/tu_darmstadt/sudoku/game/GameField.java
index bf3b09d..865f016 100644
--- a/app/src/main/java/tu_darmstadt/sudoku/game/GameField.java
+++ b/app/src/main/java/tu_darmstadt/sudoku/game/GameField.java
@@ -1,11 +1,12 @@
package tu_darmstadt.sudoku.game;
+import java.util.Arrays;
import java.util.LinkedList;
/**
* Created by Christopher Beckmann on 06.11.2015.
*/
-public class GameField {
+public class GameField implements Cloneable {
//private int id;
private int sectionHeight;
@@ -49,6 +50,9 @@ public class GameField {
break;
case Unspecified:
default:
+ this.size = 1;
+ this.sectionHeight = 1;
+ this.sectionWidth = 1;
throw new IllegalArgumentException("GameType can not be unspecified.");
}
}
@@ -90,19 +94,15 @@ public class GameField {
return result;
}
- public LinkedList getSection(int sec) {
- LinkedList result = new LinkedList();
- for(int i = 0; i < size ; i++) { // row
- for(int j = 0 ; j < size ; j++) { // col
- if((int)(Math.floor(i/sectionHeight)*sectionHeight + Math.floor(j/sectionWidth)) == sec) {
- result.add(field[i][j]);
+ public LinkedList getSection(final int sec) {
+ return actionOnCells(new ICellAction>() {
+ @Override
+ public LinkedList action(GameCell gc, LinkedList existing) {
+ if((int)(Math.floor(gc.getRow()/sectionHeight)*sectionHeight + Math.floor(gc.getCol()/sectionWidth)) == sec) {
+ existing.add(gc);
}
- if(result.size() >= sectionHeight*sectionWidth) {
- break;
- }
- }
- }
- return result;
+ return existing;
+ }}, new LinkedList());
}
public LinkedList getSection(int row, int col) {
@@ -114,16 +114,40 @@ public class GameField {
return size;
}
+ public T actionOnCells(ICellAction ca, T existing) {
+ for(int i = 0; i < field.length; i++) {
+ for(int j = 0; j < field[i].length; j++) {
+ existing = ca.action(field[i][j], existing);
+ }
+ }
+ return existing;
+ }
+
+ @Override
+ public GameField clone() throws CloneNotSupportedException {
+ GameField clone = (GameField) super.clone();
+
+ GameCell[][] cloneField = new GameCell[size][size];
+ for(int i = 0; i < size; i++) {
+ for(int j = 0; j < size; j++) {
+ cloneField[i][j] = field[i][j].clone();
+ }
+ }
+ clone.field = cloneField;
+
+ return clone;
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("GameField: "); sb.append("\n");
+ sb.append("[GameField: \n");
- for(int i = 0; i < size; i++) {
+ for (int i = 0; i < size; i++) {
- for(int j = 0; j < size; j++) {
- if(j % sectionWidth == 0) {
+ for (int j = 0; j < size; j++) {
+ if (j % sectionWidth == 0) {
sb.append("\t");
}
@@ -131,7 +155,7 @@ public class GameField {
sb.append(" ");
}
- sb.append("\n");
+ sb.append("]");
}
return sb.toString();
}
diff --git a/app/src/main/java/tu_darmstadt/sudoku/game/ICellAction.java b/app/src/main/java/tu_darmstadt/sudoku/game/ICellAction.java
new file mode 100644
index 0000000..f2ee966
--- /dev/null
+++ b/app/src/main/java/tu_darmstadt/sudoku/game/ICellAction.java
@@ -0,0 +1,8 @@
+package tu_darmstadt.sudoku.game;
+
+/**
+ * Created by Chris on 10.11.2015.
+ */
+public interface ICellAction {
+ T action(GameCell gc, T existing);
+}
diff --git a/app/src/main/java/tu_darmstadt/sudoku/game/solver/Default9x9Solver.java b/app/src/main/java/tu_darmstadt/sudoku/game/solver/Default9x9Solver.java
new file mode 100644
index 0000000..f6f77db
--- /dev/null
+++ b/app/src/main/java/tu_darmstadt/sudoku/game/solver/Default9x9Solver.java
@@ -0,0 +1,89 @@
+package tu_darmstadt.sudoku.game.solver;
+
+import tu_darmstadt.sudoku.game.GameCell;
+import tu_darmstadt.sudoku.game.GameField;
+import tu_darmstadt.sudoku.game.ICellAction;
+
+/**
+ * Created by Chris on 10.11.2015.
+ */
+public class Default9x9Solver implements ISolver {
+
+ private GameField gameField = null;
+
+ Default9x9Solver(GameField gameField) {
+ try {
+ if(gameField == null) {
+ throw new IllegalArgumentException("GameField may not be null.");
+ }
+
+ this.gameField = gameField.clone();
+ } catch(CloneNotSupportedException e) {
+ throw new IllegalArgumentException("This GameField is not cloneable.", e);
+ }
+ }
+
+ public boolean solve() {
+
+ checkSolvedCells();
+ /*
+ if(showPossibles()) return solve();
+
+ if(searchHiddenSingles()) return solve();
+
+ if(searchNakedPairsTriples()) return solve();
+
+ if(searchHiddenPairsTriples()) return solve();
+
+ if(searchNakedQuads()) return solve();
+
+ if(searchPointingPairs()) return solve();
+
+ if(searchBoxLineReduction()) return solve();
+
+ selectBestCell();
+ */
+
+
+
+
+
+
+ return true;
+ }
+
+ @Override
+ public boolean calculateNextPossibleStep() {
+ return false;
+ }
+
+ public GameField getGameField() {
+ return gameField;
+ }
+
+ private boolean checkSolvedCells() {
+ return gameField.actionOnCells(new ICellAction() {
+ @Override
+ public Boolean action(GameCell gc, Boolean existing) {
+ boolean oneNote = false;
+ int value = -1;
+ if(gc.getNoteCount() == 1) {
+ for(int i = 0; i < gameField.getSize(); i++) {
+ if(gc.getNotes()[i]) {
+ value = i;
+ break;
+ }
+ }
+ gc.setValue(value);
+ existing = true;
+ }
+ return existing;
+ }}, false);
+ }
+
+ private boolean searchHiddenSingles() {
+ return false;
+ }
+
+
+}
diff --git a/app/src/main/java/tu_darmstadt/sudoku/game/solver/ISolver.java b/app/src/main/java/tu_darmstadt/sudoku/game/solver/ISolver.java
new file mode 100644
index 0000000..5d12da9
--- /dev/null
+++ b/app/src/main/java/tu_darmstadt/sudoku/game/solver/ISolver.java
@@ -0,0 +1,16 @@
+package tu_darmstadt.sudoku.game.solver;
+
+import tu_darmstadt.sudoku.game.GameField;
+
+/**
+ * Created by Chris on 11.11.2015.
+ */
+public interface ISolver {
+
+ public boolean solve();
+
+ public boolean calculateNextPossibleStep();
+
+ public GameField getGameField();
+
+}
diff --git a/app/src/main/java/tu_darmstadt/sudoku/view/MainMenu.java b/app/src/main/java/tu_darmstadt/sudoku/view/MainMenu.java
deleted file mode 100644
index d016c10..0000000
--- a/app/src/main/java/tu_darmstadt/sudoku/view/MainMenu.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package tu_darmstadt.sudoku.view;
-
-import android.os.Bundle;
-import android.support.design.widget.FloatingActionButton;
-import android.support.design.widget.Snackbar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.View;
-import android.view.Menu;
-import android.view.MenuItem;
-
-public class MainMenu extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main_menu);
- //Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- //setSupportActionBar(toolbar);
-
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
- .setAction("Action", null).show();
- }
- });
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_main_menu, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
-
- //noinspection SimplifiableIfStatement
- if (id == R.id.action_settings) {
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-}
diff --git a/app/src/main/res/layout/activity_main_menu.xml b/app/src/main/res/layout/activity_main_menu.xml
deleted file mode 100644
index 7697f78..0000000
--- a/app/src/main/res/layout/activity_main_menu.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/content_main_menu.xml b/app/src/main/res/layout/content_main_menu.xml
deleted file mode 100644
index 7f0cbd7..0000000
--- a/app/src/main/res/layout/content_main_menu.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/menu/menu_main_menu.xml b/app/src/main/res/menu/menu_main_menu.xml
deleted file mode 100644
index 2b4455a..0000000
--- a/app/src/main/res/menu/menu_main_menu.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/app/src/test/java/tu_darmstadt/sudoku/controller/GameControllerTest.java b/app/src/test/java/tu_darmstadt/sudoku/controller/GameControllerTest.java
index df32634..3d76f4a 100644
--- a/app/src/test/java/tu_darmstadt/sudoku/controller/GameControllerTest.java
+++ b/app/src/test/java/tu_darmstadt/sudoku/controller/GameControllerTest.java
@@ -1,11 +1,8 @@
package tu_darmstadt.sudoku.controller;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
-import tu_darmstadt.sudoku.game.GameType;
-
import static org.junit.Assert.*;
/**
@@ -153,4 +150,45 @@ public class GameControllerTest {
assertEquals(2, controller.getErrorList().size());
assertEquals(result, controller.getErrorList().toString());
}
+
+ @Test
+ public void deleteTest() {
+ controller.setValue(1, 2, 5);
+ assertEquals(5, controller.getValue(1, 2));
+ controller.deleteValue(1, 2);
+ assertEquals(0, controller.getValue(1, 2));
+ }
+
+ @Test
+ public void createNoteTest() {
+ controller.setNote(1, 2, 5);
+ controller.setNote(1, 2, 9);
+
+ boolean[] result = {false, false, false, false, true, false, false, false, true};
+
+ assertArrayEquals(result, controller.getNotes(1, 2));
+ }
+
+ @Test
+ public void deleteNoteTest() {
+ controller.setNote(1, 2, 5);
+ controller.setNote(1, 2, 9);
+ controller.deleteNote(1, 2, 5);
+
+ boolean[] result = {false, false, false, false, false, false, false, false, true};
+
+ assertArrayEquals(result, controller.getNotes(1, 2));
+ }
+
+ @Test
+ public void toggleNoteTest() {
+ controller.toggleNote(1,2,5);
+ controller.toggleNote(1,2,9);
+ controller.toggleNote(1,2,5);
+ controller.toggleNote(1,2,4);
+
+ boolean[] result = {false, false, false, true, false, false, false, false, true};
+
+ assertArrayEquals(result, controller.getNotes(1, 2));
+ }
}