Rewrote CellConflict Detection.

Added additional JUnit Tests
This commit is contained in:
Christopher Beckmann 2015-11-10 10:53:16 +01:00
parent b5dc145bb7
commit bd474e3280
8 changed files with 195 additions and 273 deletions

View file

@ -1,5 +1,7 @@
package tu_darmstadt.sudoku.controller; package tu_darmstadt.sudoku.controller;
import android.util.Log;
import tu_darmstadt.sudoku.game.*; import tu_darmstadt.sudoku.game.*;
import java.util.LinkedList; import java.util.LinkedList;
@ -13,7 +15,7 @@ public class GameController {
private int size; private int size;
private GameField gameField; private GameField gameField;
private ArrayList<CheckError> errorList = new ArrayList<CheckError>(); private CellConflictList errorList = new CellConflictList();
private GameSettings settings = new GameSettings(); private GameSettings settings = new GameSettings();
// private SudokuSolver solver; // private SudokuSolver solver;
@ -79,8 +81,8 @@ public class GameController {
public boolean isSolved() { public boolean isSolved() {
boolean solved = true; boolean solved = true;
// this will automatically build the CheckError list. so we reset it before we call the checks // this will automatically build the CellConflict list. so we reset it before we call the checks
errorList = new ArrayList<CheckError>(); errorList = new CellConflictList();
for(int i = 0; i < size; i++) { for(int i = 0; i < size; i++) {
if(!checkList(gameField.getRow(i))) solved = false; if(!checkList(gameField.getRow(i))) solved = false;
@ -98,7 +100,7 @@ public class GameController {
*/ */
private boolean checkList(List<GameCell> list) { private boolean checkList(List<GameCell> list) {
boolean isNothingEmpty = true; boolean isNothingEmpty = true;
CheckError lastFound = null; CellConflict lastFound = null;
for(int i = 0; i < list.size(); i++) { for(int i = 0; i < list.size(); i++) {
for(int j = i + 1; j < list.size(); j++) { for(int j = i + 1; j < list.size(); j++) {
@ -112,42 +114,14 @@ public class GameController {
// Same value in one set should not exist // Same value in one set should not exist
if(c1.getValue() != 0 && c1.getValue() == c2.getValue()) { if(c1.getValue() != 0 && c1.getValue() == c2.getValue()) {
// we found an error.. // we found an error..
errorList.add(new CellConflict(c1, c2));
LinkedList<CheckError> removeList = new LinkedList<CheckError>();
// check if one of the cells is already in conflict with something else
if(errorList.size() == 0) {
lastFound = new CheckError(c1, c2);
errorList.add(lastFound);
}
for(CheckError ce : errorList) {
if(ce.contains(c1) || ce.contains(c2)) {
ce.add(c1);
ce.add(c2);
if(lastFound != null && !lastFound.equals(ce)) {
lastFound.merge(ce);
removeList.add(ce);
} else {
lastFound = ce;
}
} else {
lastFound = new CheckError(c1, c2);
errorList.add(lastFound);
}
}
// remove the empty errors, that have been merged.
for(CheckError ce : removeList) {
errorList.remove(ce);
}
} }
} }
} }
return isNothingEmpty ? (errorList.size() == 0) : false; return isNothingEmpty ? (errorList.size() == 0) : false;
} }
public List<CheckError> getErrorList() { public List<CellConflict> getErrorList() {
return errorList; return errorList;
} }

View file

@ -0,0 +1,48 @@
package tu_darmstadt.sudoku.game;
import java.util.LinkedList;
/**
* Created by Chris on 08.11.2015.
*/
public class CellConflict {
/*
* A conflict is created for every cell.
*/
private GameCell c1 = null;
private GameCell c2 = null;
public CellConflict(GameCell first, GameCell second) {
c1 = first;
c2 = second;
}
public boolean contains(GameCell c) {
return c1.equals(c) || c2.equals(c);
}
@Override
public boolean equals(Object other) {
if(!(other instanceof CellConflict)) {
return false;
}
if(!(c1.equals(((CellConflict) other).c1) && c2.equals(((CellConflict) other).c2)
|| c1.equals(((CellConflict) other).c2) && c2.equals(((CellConflict) other).c1))) {
return false;
}
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[Conflict ");
sb.append(c1.toString());
sb.append(" ");
sb.append(c2.toString());
sb.append("]");
return sb.toString();
}
}

View file

@ -0,0 +1,41 @@
package tu_darmstadt.sudoku.game;
import android.support.annotation.NonNull;
import java.util.ArrayList;
/**
* Created by Chris on 10.11.2015.
*/
public class CellConflictList extends ArrayList<CellConflict> {
/**
* Adds the CellConflict to the list.
* We don't allow double entries.
* @param object the object to be added
* @return true if it could be added, false otherwise
*/
@Override
public boolean add(CellConflict object) {
if(!contains(object)) {
return super.add(object);
}
return false;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[List ");
for(int i = 0; i < size(); i++) {
sb.append(get(i).toString());
if(i+1 < size()) {
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
}

View file

@ -1,78 +0,0 @@
package tu_darmstadt.sudoku.game;
import java.util.LinkedList;
/**
* Created by Chris on 08.11.2015.
*/
public class CheckError {
/*
* An Error is created for every cell.
*/
private int value = 0;
private LinkedList<GameCell> list = new LinkedList<GameCell>();
public CheckError(GameCell first, GameCell second) {
add(first);
add(second);
}
public void add(GameCell cell) {
if(value == 0 && cell.getValue() != 0) {
value = cell.getValue();
}
if(!list.contains(cell)) {
list.add(cell);
}
}
public boolean contains(GameCell c) {
return list.contains(c);
}
public void merge(CheckError other) {
// merge the same object? ... why would you do that. This would simply clear the CheckError.
if(equals(other)) return;
for(GameCell c : other.list) {
if(!contains(c)) {
add(c);
}
}
// Empty the other list.... because they are merged now.
other.list = new LinkedList<GameCell>();
}
@Override
public boolean equals(Object other) {
if(!(other instanceof CheckError)) {
return false;
}
if(list.size() != ((CheckError) other).list.size()) return false;
for(int i = 0; i < list.size(); i++) {
if(!list.get(i).equals(((CheckError) other).list.get(i))) {
return false;
}
}
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[CheckError: "); sb.append(value);
for(GameCell c : list) {
sb.append(" (");
sb.append(c.getRow());
sb.append("|");
sb.append(c.getCol());
sb.append(")");
}
sb.append("]");
return sb.toString();
}
}

View file

@ -1,12 +0,0 @@
package tu_darmstadt.sudoku.game;
/**
* Created by Chris on 08.11.2015.
*/
public enum CheckType {
UNSPECIFIED,
ROW,
COLUMN,
SECTION
}

View file

@ -109,10 +109,10 @@ public class GameCell {
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("{("); sb.append(row); sb.append("|"); sb.append(col); sb.append(")");
sb.append(" ");
if(value == 0) {
sb.append("["); sb.append("[");
if(value == 0) {
sb.append("{");
boolean addedNotes = false; boolean addedNotes = false;
for(int i = 0; i < size; i++) { for(int i = 0; i < size; i++) {
if(notes[i]) { if(notes[i]) {
@ -123,11 +123,14 @@ public class GameCell {
addedNotes = true; addedNotes = true;
} }
} }
sb.append("]"); sb.append("}");
} else { } else {
sb.append(value); sb.append(value);
} }
sb.append("}");
sb.append(" ");
sb.append("("); sb.append(row); sb.append("|"); sb.append(col); sb.append(")");
sb.append("]");
return sb.toString(); return sb.toString();
} }

View file

@ -5,6 +5,10 @@ package tu_darmstadt.sudoku.game;
*/ */
public enum GameType { public enum GameType {
Unspecified, Unspecified,
Default_9x9 Default_9x9,
Default_9x6,
Default_12x9,
Default_6x6
} }

View file

@ -50,54 +50,30 @@ public class GameControllerTest {
@Test @Test
public void solveTest1() { public void solveTest1() {
controller.setValue(0, 1, 8); controller.setValue(0, 1, 8); controller.setValue(0, 4, 2);
controller.setValue(0, 4, 2); controller.setValue(0, 5, 6); controller.setValue(0, 6, 7);
controller.setValue(0, 5, 6); controller.setValue(0, 7, 3); controller.setValue(0, 8, 4);
controller.setValue(0, 6, 7); controller.setValue(1, 1, 6); controller.setValue(1, 2, 7);
controller.setValue(0, 7, 3); controller.setValue(1, 3, 1); controller.setValue(1, 4, 3);
controller.setValue(0, 8, 4); controller.setValue(1, 8, 8); controller.setValue(2, 2, 4);
controller.setValue(1, 1, 6); controller.setValue(2, 4, 8); controller.setValue(2, 5, 5);
controller.setValue(1, 2, 7); controller.setValue(2, 6, 1); controller.setValue(3, 0, 9);
controller.setValue(1, 3, 1); controller.setValue(3, 2, 5); controller.setValue(3, 3, 8);
controller.setValue(1, 4, 3); controller.setValue(3, 4, 4); controller.setValue(3, 6, 6);
controller.setValue(1, 8, 8); controller.setValue(4, 0, 4); controller.setValue(4, 1, 1);
controller.setValue(2, 2, 4); controller.setValue(4, 3, 2); controller.setValue(4, 6, 8);
controller.setValue(2, 4, 8); controller.setValue(4, 7, 9); controller.setValue(4, 8, 3);
controller.setValue(2, 5, 5); controller.setValue(5, 0, 8); controller.setValue(5, 3, 3);
controller.setValue(2, 6, 1); controller.setValue(5, 4, 6); controller.setValue(5, 6, 5);
controller.setValue(3, 0, 9); controller.setValue(6, 0, 1); controller.setValue(6, 1, 5);
controller.setValue(3, 2, 5); controller.setValue(6, 2, 3); controller.setValue(6, 3, 6);
controller.setValue(3, 3, 8); controller.setValue(6, 5, 2); controller.setValue(6, 7, 8);
controller.setValue(3, 4, 4); controller.setValue(7, 2, 8); controller.setValue(7, 3, 5);
controller.setValue(3, 6, 6); controller.setValue(7, 4, 9); controller.setValue(7, 5, 3);
controller.setValue(4, 0, 4); controller.setValue(7, 6, 2); controller.setValue(7, 7, 1);
controller.setValue(4, 1, 1); controller.setValue(7, 8, 7); controller.setValue(8, 1, 2);
controller.setValue(4, 3, 2); controller.setValue(8, 2, 9); controller.setValue(8, 3, 4);
controller.setValue(4, 6, 8); controller.setValue(8, 5, 8); controller.setValue(8, 7, 6);
controller.setValue(4, 7, 9);
controller.setValue(4, 8, 3);
controller.setValue(5, 0, 8);
controller.setValue(5, 3, 3);
controller.setValue(5, 4, 6);
controller.setValue(5, 6, 5);
controller.setValue(6, 0, 1);
controller.setValue(6, 1, 5);
controller.setValue(6, 2, 3);
controller.setValue(6, 3, 6);
controller.setValue(6, 5, 2);
controller.setValue(6, 7, 8);
controller.setValue(7, 2, 8);
controller.setValue(7, 3, 5);
controller.setValue(7, 4, 9);
controller.setValue(7, 5, 3);
controller.setValue(7, 6, 2);
controller.setValue(7, 7, 1);
controller.setValue(7, 8, 7);
controller.setValue(8, 1, 2);
controller.setValue(8, 2, 9);
controller.setValue(8, 3, 4);
controller.setValue(8, 5, 8);
controller.setValue(8, 7, 6);
assertTrue(controller.isSolved()); assertTrue(controller.isSolved());
assertEquals(0, controller.getErrorList().size()); assertEquals(0, controller.getErrorList().size());
@ -105,110 +81,76 @@ public class GameControllerTest {
@Test @Test
public void solveTest2() { public void solveTest2() {
controller.setValue(0, 1, 8); controller.setValue(0, 4, 2);
controller.setValue(0, 5, 6); controller.setValue(0, 6, 7);
controller.setValue(0, 7, 3); controller.setValue(0, 8, 4);
controller.setValue(1, 1, 6); controller.setValue(1, 2, 7);
controller.setValue(1, 3, 1); controller.setValue(1, 4, 3);
controller.setValue(1, 8, 8); controller.setValue(2, 2, 4);
controller.setValue(2, 4, 8); controller.setValue(2, 5, 5);
controller.setValue(2, 6, 1); controller.setValue(3, 0, 9);
controller.setValue(3, 2, 5); controller.setValue(3, 3, 8);
controller.setValue(3, 4, 4); controller.setValue(3, 6, 6);
controller.setValue(4, 0, 4); controller.setValue(4, 1, 1);
controller.setValue(4, 3, 2); controller.setValue(4, 6, 8);
controller.setValue(4, 7, 9); controller.setValue(4, 8, 3);
controller.setValue(5, 0, 8); controller.setValue(5, 3, 3);
controller.setValue(5, 4, 6); controller.setValue(5, 6, 5);
controller.setValue(6, 0, 1); controller.setValue(6, 1, 5);
controller.setValue(6, 2, 3); controller.setValue(6, 3, 1);
controller.setValue(6, 5, 2); controller.setValue(6, 7, 8);
controller.setValue(7, 2, 8); controller.setValue(7, 3, 5);
controller.setValue(7, 4, 9); controller.setValue(7, 5, 3);
controller.setValue(7, 6, 2); controller.setValue(7, 7, 1);
controller.setValue(7, 8, 7); controller.setValue(8, 1, 2);
controller.setValue(8, 2, 9); controller.setValue(8, 3, 4);
controller.setValue(8, 5, 8); controller.setValue(8, 7, 6);
controller.setValue(0, 1, 8); String result = "[List [Conflict [1 (1|3)] [1 (6|3)]], [Conflict [1 (6|0)] [1 (6|3)]], [Conflict [1 (6|3)] [1 (8|4)]]]";
controller.setValue(0, 4, 2);
controller.setValue(0, 5, 6);
controller.setValue(0, 6, 7);
controller.setValue(0, 7, 3);
controller.setValue(0, 8, 4);
controller.setValue(1, 1, 6);
controller.setValue(1, 2, 7);
controller.setValue(1, 3, 1);
controller.setValue(1, 4, 3);
controller.setValue(1, 8, 8);
controller.setValue(2, 2, 4);
controller.setValue(2, 4, 8);
controller.setValue(2, 5, 5);
controller.setValue(2, 6, 1);
controller.setValue(3, 0, 9);
controller.setValue(3, 2, 5);
controller.setValue(3, 3, 8);
controller.setValue(3, 4, 4);
controller.setValue(3, 6, 6);
controller.setValue(4, 0, 4);
controller.setValue(4, 1, 1);
controller.setValue(4, 3, 2);
controller.setValue(4, 6, 8);
controller.setValue(4, 7, 9);
controller.setValue(4, 8, 3);
controller.setValue(5, 0, 8);
controller.setValue(5, 3, 3);
controller.setValue(5, 4, 6);
controller.setValue(5, 6, 5);
controller.setValue(6, 0, 1);
controller.setValue(6, 1, 5);
controller.setValue(6, 2, 3);
controller.setValue(6, 3, 1);
controller.setValue(6, 5, 2);
controller.setValue(6, 7, 8);
controller.setValue(7, 2, 8);
controller.setValue(7, 3, 5);
controller.setValue(7, 4, 9);
controller.setValue(7, 5, 3);
controller.setValue(7, 6, 2);
controller.setValue(7, 7, 1);
controller.setValue(7, 8, 7);
controller.setValue(8, 1, 2);
controller.setValue(8, 2, 9);
controller.setValue(8, 3, 4);
controller.setValue(8, 5, 8);
controller.setValue(8, 7, 6);
assertFalse(controller.isSolved()); assertFalse(controller.isSolved());
assertEquals(1, controller.getErrorList().size()); assertEquals(3, controller.getErrorList().size());
assertEquals(result, controller.getErrorList().toString());
} }
@Test @Test
public void solveTest3() { public void solveTest3() {
controller.setValue(0, 4, 2); controller.setValue(0, 4, 2); controller.setValue(0, 5, 6);
controller.setValue(0, 5, 6); controller.setValue(0, 6, 7); controller.setValue(0, 7, 3);
controller.setValue(0, 6, 7); controller.setValue(0, 8, 4); controller.setValue(1, 1, 6);
controller.setValue(0, 7, 3); controller.setValue(1, 2, 7); controller.setValue(1, 3, 1);
controller.setValue(0, 8, 4); controller.setValue(1, 4, 3); controller.setValue(1, 8, 8);
controller.setValue(1, 1, 6); controller.setValue(2, 2, 4); controller.setValue(2, 4, 8);
controller.setValue(1, 2, 7); controller.setValue(2, 5, 5); controller.setValue(2, 6, 1);
controller.setValue(1, 3, 1); controller.setValue(3, 0, 9); controller.setValue(3, 2, 5);
controller.setValue(1, 4, 3); controller.setValue(3, 3, 8); controller.setValue(3, 4, 4);
controller.setValue(1, 8, 8); controller.setValue(3, 6, 6); controller.setValue(4, 0, 4);
controller.setValue(2, 2, 4); controller.setValue(4, 1, 1); controller.setValue(4, 3, 2);
controller.setValue(2, 4, 8); controller.setValue(4, 6, 8); controller.setValue(4, 7, 9);
controller.setValue(2, 5, 5); controller.setValue(4, 8, 3); controller.setValue(5, 0, 8);
controller.setValue(2, 6, 1); controller.setValue(5, 3, 3); controller.setValue(5, 4, 6);
controller.setValue(3, 0, 9); controller.setValue(5, 6, 5); controller.setValue(6, 0, 1);
controller.setValue(3, 2, 5); controller.setValue(6, 1, 5); controller.setValue(6, 2, 3);
controller.setValue(3, 3, 8); controller.setValue(6, 5, 2); controller.setValue(6, 7, 8);
controller.setValue(3, 4, 4); controller.setValue(7, 2, 8); controller.setValue(7, 3, 5);
controller.setValue(3, 6, 6); controller.setValue(7, 4, 9); controller.setValue(7, 5, 3);
controller.setValue(4, 0, 4); controller.setValue(7, 6, 2); controller.setValue(7, 7, 1);
controller.setValue(4, 1, 1); controller.setValue(7, 8, 7); controller.setValue(8, 1, 2);
controller.setValue(4, 3, 2); controller.setValue(8, 2, 9); controller.setValue(8, 3, 4);
controller.setValue(4, 6, 8); controller.setValue(8, 5, 8); controller.setValue(8, 7, 6);
controller.setValue(4, 7, 9);
controller.setValue(4, 8, 3);
controller.setValue(5, 0, 8);
controller.setValue(5, 3, 3);
controller.setValue(5, 4, 6);
controller.setValue(5, 6, 5);
controller.setValue(6, 0, 1);
controller.setValue(6, 1, 5);
controller.setValue(6, 2, 3);
controller.setValue(6, 5, 2);
controller.setValue(6, 7, 8);
controller.setValue(7, 2, 8);
controller.setValue(7, 3, 5);
controller.setValue(7, 4, 9);
controller.setValue(7, 5, 3);
controller.setValue(7, 6, 2);
controller.setValue(7, 7, 1);
controller.setValue(7, 8, 7);
controller.setValue(8, 1, 2);
controller.setValue(8, 2, 9);
controller.setValue(8, 3, 4);
controller.setValue(8, 5, 8);
controller.setValue(8, 7, 6);
assertFalse(controller.isSolved()); assertFalse(controller.isSolved());
assertEquals(0, controller.getErrorList().size()); assertEquals(0, controller.getErrorList().size());
} }
@Test
public void solveTest4() {
controller.setValue(1, 2, 5); // Produces 2 conflicts
String result = "[List [Conflict [5 (0|0)] [5 (1|2)]], [Conflict [5 (1|2)] [5 (1|7)]]]";
assertFalse(controller.isSolved());
assertEquals(2, controller.getErrorList().size());
assertEquals(result, controller.getErrorList().toString());
}
} }