diff --git a/app/src/main/java/tu_darmstadt/sudoku/controller/GameController.java b/app/src/main/java/tu_darmstadt/sudoku/controller/GameController.java index b1318e8..6ce286c 100644 --- a/app/src/main/java/tu_darmstadt/sudoku/controller/GameController.java +++ b/app/src/main/java/tu_darmstadt/sudoku/controller/GameController.java @@ -11,14 +11,16 @@ import tu_darmstadt.sudoku.game.CellConflictList; import tu_darmstadt.sudoku.game.GameBoard; import tu_darmstadt.sudoku.game.GameCell; 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.IModelChangedListener; import tu_darmstadt.sudoku.game.solver.Solver; /** * Created by Chris on 06.11.2015. */ -public class GameController { +public class GameController implements IModelChangedListener { private int size; private int sectionHeight; @@ -59,7 +61,7 @@ public class GameController { public void loadNewLevel(GameType type, int difficulty) { switch(type) { case Default_6x6: - loadLevel(new GameInfoContainer(1, GameType.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, @@ -68,7 +70,7 @@ public class GameController { 0,3,0,5,0,1}, null,null)); break; case Default_12x12: - loadLevel(new GameInfoContainer(2, GameType.Default_12x12, + loadLevel(new GameInfoContainer(2, GameDifficulty.Easy, 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, @@ -86,7 +88,7 @@ public class GameController { case Default_9x9: case Unspecified: default: - loadLevel(new GameInfoContainer(3, GameType.Default_9x9, + loadLevel(new GameInfoContainer(3, GameDifficulty.Easy, 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, @@ -234,12 +236,7 @@ public class GameController { } public boolean checkIfBoardIsFilled() { - //if(gameBoard.getEmptyCellCount() == 0) { - // TODO: board is filled. check it for errors. - - //return true; - //} - return false; + return gameBoard.isFilled(); } public void saveGame(Context context) { @@ -395,6 +392,19 @@ public class GameController { return sectionWidth; } + @Override + public void onModelChange(GameCell c) { + if(gameBoard.isFilled()) { + List errorList = new LinkedList<>(); + if(gameBoard.isSolved(errorList)) { + // TODO: WE WON! :D + } else { + // TODO: errorList now holds all the errors + // TODO: display errors .. notify some view? + } + } + } + // public void notifyListeners() { // for(IModelChangeListener l : listeners) { // l.onModelChanged(); diff --git a/app/src/main/java/tu_darmstadt/sudoku/controller/Symbol.java b/app/src/main/java/tu_darmstadt/sudoku/controller/Symbol.java index 95b685e..253d182 100644 --- a/app/src/main/java/tu_darmstadt/sudoku/controller/Symbol.java +++ b/app/src/main/java/tu_darmstadt/sudoku/controller/Symbol.java @@ -8,7 +8,10 @@ public enum Symbol { 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" }); + Fancy(new String[] {"♪", "♫", "☼", "♥", "♦", "♣", "♠", "•", "○", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N" }), + Chinese(new String[] {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二", "十三", "十四", "十五", "十六" }), + Greek(new String[] { "α", "β", "γ", "δ", "ε", "ϛ", "ζ", "η", "θ", "ι", "ια", "ιβ", "ιγ", "ιδ", "ιε", "ιϛ", "ιζ", "ιη", "ιθ", "κ"}), + Indian(new String[] { "१", "२", "३", "४", "५", "६", "७", "८", "९", "१०", "११", "१२", "१३", "१४", "१५", "१६", "१७"}); private String[] map; @@ -26,5 +29,4 @@ public enum Symbol { } return -1; } - } diff --git a/app/src/main/java/tu_darmstadt/sudoku/controller/helper/GameInfoContainer.java b/app/src/main/java/tu_darmstadt/sudoku/controller/helper/GameInfoContainer.java index c6e6af0..c84d5f7 100644 --- a/app/src/main/java/tu_darmstadt/sudoku/controller/helper/GameInfoContainer.java +++ b/app/src/main/java/tu_darmstadt/sudoku/controller/helper/GameInfoContainer.java @@ -2,9 +2,12 @@ package tu_darmstadt.sudoku.controller.helper; import android.util.Log; +import java.util.Date; + import tu_darmstadt.sudoku.controller.GameController; import tu_darmstadt.sudoku.controller.Symbol; import tu_darmstadt.sudoku.game.GameCell; +import tu_darmstadt.sudoku.game.GameDifficulty; import tu_darmstadt.sudoku.game.GameType; import tu_darmstadt.sudoku.game.ICellAction; @@ -15,16 +18,23 @@ public class GameInfoContainer { GameType gameType; int ID; - int time; - int difficulty; + int timePlayed; + Date lastTimePlayed; + GameDifficulty difficulty; int[] fixedValues; int[] setValues; boolean[][] setNotes; public GameInfoContainer() {} - public GameInfoContainer(int ID, GameType gameType, int[] fixedValues, int[] setValues, boolean[][] setNotes) { + public GameInfoContainer(int ID, GameDifficulty difficulty, GameType gameType, int[] fixedValues, int[] setValues, boolean[][] setNotes) { + this(ID, difficulty, new Date(), 0, gameType, fixedValues, setValues, setNotes); + } + public GameInfoContainer(int ID, GameDifficulty difficulty, Date lastTimePlayed, int timePlayed, GameType gameType, int[] fixedValues, int[] setValues, boolean[][] setNotes) { this.ID = ID; + this.difficulty = difficulty; this.gameType = gameType; + this.timePlayed = timePlayed; + this.lastTimePlayed = lastTimePlayed; this.fixedValues = fixedValues; this.setValues = setValues; this.setNotes = setNotes; diff --git a/app/src/main/java/tu_darmstadt/sudoku/game/GameBoard.java b/app/src/main/java/tu_darmstadt/sudoku/game/GameBoard.java index 7b4c099..6266f77 100644 --- a/app/src/main/java/tu_darmstadt/sudoku/game/GameBoard.java +++ b/app/src/main/java/tu_darmstadt/sudoku/game/GameBoard.java @@ -15,6 +15,7 @@ public class GameBoard implements Cloneable { //private List additionalSections private int size; private GameCell[][] field; + private List modelChangedListeners = new LinkedList<>(); public GameBoard(int size, int sectionHeight, int sectionWidth) { this.sectionHeight = sectionHeight; @@ -199,4 +200,40 @@ public class GameBoard implements Cloneable { return sb.toString(); } + public boolean isFilled() { + return actionOnCells(new ICellAction() { + @Override + public Boolean action(GameCell gc, Boolean existing) { + return gc.hasValue() ? existing : false; + } + }, true); + } + + public void registerOnModelChangeListener(final IModelChangedListener listener) { + if(!modelChangedListeners.contains(listener)) { + actionOnCells(new ICellAction() { + + @Override + public Boolean action(GameCell gc, Boolean existing) { + gc.registerOnModelChangeListener(listener); + return existing; + } + }, false); + modelChangedListeners.add(listener); + } + } + + public void deleteOnModelChangeListener(final IModelChangedListener listener) { + if(modelChangedListeners.contains(listener)) { + actionOnCells(new ICellAction() { + + @Override + public Boolean action(GameCell gc, Boolean existing) { + gc.removeOnModelChangeListener(listener); + return existing; + } + }, false); + modelChangedListeners.remove(listener); + } + } } 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 4066f02..eb85c2f 100644 --- a/app/src/main/java/tu_darmstadt/sudoku/game/GameCell.java +++ b/app/src/main/java/tu_darmstadt/sudoku/game/GameCell.java @@ -1,6 +1,8 @@ package tu_darmstadt.sudoku.game; import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; /** * Created by Chris on 06.11.2015. @@ -14,6 +16,7 @@ public class GameCell implements Cloneable { private int noteCount = 0; private boolean notes[]; private int size = 0; + private List modelChangedListeners = new LinkedList(); public GameCell(int row, int col, int size) { this(row,col,size,0); @@ -43,6 +46,7 @@ public class GameCell implements Cloneable { public void setValue(int val) { deleteNotes(); value = val; + notifyListeners(); } public int getValue() { @@ -66,6 +70,7 @@ public class GameCell implements Cloneable { noteCount = notes[val - 1] ? noteCount - 1 : noteCount + 1; notes[val - 1] = !notes[val - 1]; } + notifyListeners(); } public void setNote(int val) { @@ -73,6 +78,7 @@ public class GameCell implements Cloneable { noteCount = notes[val - 1] ? noteCount : noteCount + 1; notes[val - 1] = true; } + notifyListeners(); } public void deleteNote(int val) { @@ -80,6 +86,7 @@ public class GameCell implements Cloneable { noteCount = notes[val - 1] ? noteCount - 1 : noteCount; notes[val - 1] = false; } + notifyListeners(); } public int getNoteCount() { @@ -96,6 +103,7 @@ public class GameCell implements Cloneable { public void deleteNotes() { noteCount = 0; notes = new boolean[size]; + notifyListeners(); } public boolean isFixed() { @@ -164,7 +172,26 @@ public class GameCell implements Cloneable { @Override public GameCell clone() throws CloneNotSupportedException { GameCell clone = (GameCell) super.clone(); + clone.modelChangedListeners = new LinkedList(); clone.notes = (notes == null) ? null : Arrays.copyOf(notes, notes.length); return clone; } + + public void registerOnModelChangeListener(IModelChangedListener listener) { + if(!modelChangedListeners.contains(listener)) { + modelChangedListeners.add(listener); + } + } + + public void removeOnModelChangeListener(IModelChangedListener listener) { + if(modelChangedListeners.contains(listener)) { + modelChangedListeners.remove(listener); + } + } + + public void notifyListeners() { + for(IModelChangedListener m : modelChangedListeners) { + m.onModelChange(this); + } + } } diff --git a/app/src/main/java/tu_darmstadt/sudoku/game/GameDifficulty.java b/app/src/main/java/tu_darmstadt/sudoku/game/GameDifficulty.java new file mode 100644 index 0000000..3433322 --- /dev/null +++ b/app/src/main/java/tu_darmstadt/sudoku/game/GameDifficulty.java @@ -0,0 +1,37 @@ +package tu_darmstadt.sudoku.game; + +import android.support.annotation.StringRes; + +import java.util.LinkedList; + +import tu_darmstadt.sudoku.ui.view.R; + +/** + * Created by Chris on 18.11.2015. + */ +public enum GameDifficulty { + + Easy(R.string.difficulty_easy), + Moderate(R.string.difficulty_moderate), + Hard(R.string.difficulty_hard); + + private int resID; + + GameDifficulty(@StringRes int resID) { + //getResources().getString(resID); + this.resID = resID; + } + + public int getStringResID() { + return resID; + } + + public static LinkedList getValidDifficultyList() { + LinkedList validList = new LinkedList<>(); + validList.add(Easy); + validList.add(Moderate); + validList.add(Hard); + return validList; + } + +} diff --git a/app/src/main/java/tu_darmstadt/sudoku/game/IModelChangedListener.java b/app/src/main/java/tu_darmstadt/sudoku/game/IModelChangedListener.java new file mode 100644 index 0000000..7b1e491 --- /dev/null +++ b/app/src/main/java/tu_darmstadt/sudoku/game/IModelChangedListener.java @@ -0,0 +1,8 @@ +package tu_darmstadt.sudoku.game; + +/** + * Created by Chris on 19.11.2015. + */ +public interface IModelChangedListener { + public void onModelChange(GameCell c); +} diff --git a/app/src/main/java/tu_darmstadt/sudoku/ui/MainActivity.java b/app/src/main/java/tu_darmstadt/sudoku/ui/MainActivity.java index decf4c4..8f25101 100644 --- a/app/src/main/java/tu_darmstadt/sudoku/ui/MainActivity.java +++ b/app/src/main/java/tu_darmstadt/sudoku/ui/MainActivity.java @@ -21,16 +21,19 @@ import android.widget.ImageView; import android.widget.RatingBar; import android.widget.TextView; +import java.util.LinkedList; import java.util.List; import tu_darmstadt.sudoku.controller.SaveLoadController; import tu_darmstadt.sudoku.controller.helper.GameInfoContainer; +import tu_darmstadt.sudoku.game.GameDifficulty; import tu_darmstadt.sudoku.game.GameType; import tu_darmstadt.sudoku.ui.view.R; public class MainActivity extends AppCompatActivity { RatingBar difficultyBar; + TextView difficultyText; SharedPreferences settings; /** @@ -76,6 +79,19 @@ public class MainActivity extends AppCompatActivity { // Set the difficulty Slider to whatever was chosen the last time difficultyBar = (RatingBar)findViewById(R.id.difficultyBar); + difficultyText = (TextView) findViewById(R.id.difficultyText); + final LinkedList difficultyList = GameDifficulty.getValidDifficultyList(); + difficultyBar.setNumStars(difficultyList.size()); + difficultyBar.setMax(difficultyList.size()); + difficultyBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() { + @Override + public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) { + if (rating < 1) { + ratingBar.setRating(1); + } + difficultyText.setText(getString(difficultyList.get((int)ratingBar.getRating()-1).getStringResID())); + } + }); int lastChosenDifficulty = settings.getInt("lastChosenDifficulty", 1); difficultyBar.setProgress(lastChosenDifficulty); diff --git a/app/src/main/res/layout/activity_main_menu.xml b/app/src/main/res/layout/activity_main_menu.xml index dc27433..6a1c239 100644 --- a/app/src/main/res/layout/activity_main_menu.xml +++ b/app/src/main/res/layout/activity_main_menu.xml @@ -61,6 +61,12 @@ android:gravity="center_horizontal" style="?android:buttonBarStyle"> + Spiel starten + + Leicht + Normal + Schwer + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a1d5525..2f07cde 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -36,7 +36,6 @@ Note deletion Automatically remove notes when setting values on connected cells - Privacy friendly Sudoku v0.9 @@ -47,4 +46,9 @@ More information can be found on: https://www.secuso.org + + Easy + Moderate + Hard + 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 a406685..945e18a 100644 --- a/app/src/test/java/tu_darmstadt/sudoku/controller/GameControllerTest.java +++ b/app/src/test/java/tu_darmstadt/sudoku/controller/GameControllerTest.java @@ -4,6 +4,7 @@ import org.junit.Before; import org.junit.Test; import tu_darmstadt.sudoku.controller.helper.GameInfoContainer; +import tu_darmstadt.sudoku.game.GameDifficulty; import tu_darmstadt.sudoku.game.GameType; import static org.junit.Assert.*; @@ -19,7 +20,7 @@ public class GameControllerTest { @Before public void init() { controller = new GameController(); - controller.loadLevel(new GameInfoContainer(3, GameType.Default_9x9, + controller.loadLevel(new GameInfoContainer(3, GameDifficulty.Easy, 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, @@ -31,7 +32,7 @@ public class GameControllerTest { 7, 0, 0, 0, 1, 0, 3, 0, 5} , null, null)); controller2 = new GameController(); - controller2.loadLevel(new GameInfoContainer(2, GameType.Default_12x12, + controller2.loadLevel(new GameInfoContainer(2, GameDifficulty.Easy, 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, diff --git a/app/src/test/java/tu_darmstadt/sudoku/game/solver/SolverTest.java b/app/src/test/java/tu_darmstadt/sudoku/game/solver/SolverTest.java index 3b5487b..3c0bf06 100644 --- a/app/src/test/java/tu_darmstadt/sudoku/game/solver/SolverTest.java +++ b/app/src/test/java/tu_darmstadt/sudoku/game/solver/SolverTest.java @@ -10,6 +10,7 @@ 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.GameDifficulty; import tu_darmstadt.sudoku.game.GameType; import static junit.framework.Assert.assertEquals; @@ -24,7 +25,7 @@ public class SolverTest { @Before public void init() { controller = new GameController(); - controller.loadLevel(new GameInfoContainer(0, GameType.Default_9x9, + controller.loadLevel(new GameInfoContainer(0, GameDifficulty.Easy ,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, @@ -62,7 +63,7 @@ public class SolverTest { @Test public void solveSingleSolution2() { - controller.loadLevel(new GameInfoContainer(0, GameType.Default_9x9, + controller.loadLevel(new GameInfoContainer(0, GameDifficulty.Easy, 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)); @@ -85,7 +86,7 @@ public class SolverTest { @Test public void solveMultipleSolutions1() { - controller.loadLevel(new GameInfoContainer(0, GameType.Default_6x6, + controller.loadLevel(new GameInfoContainer(0, 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,