ue6
This commit is contained in:
parent
4b73c1b5e3
commit
9e5e9eb91a
123
uebung06/src/sudoku/Field.java
Normal file
123
uebung06/src/sudoku/Field.java
Normal file
@ -0,0 +1,123 @@
|
||||
package sudoku;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
|
||||
/**
|
||||
* A field of a Sudoku board.
|
||||
*/
|
||||
public class Field {
|
||||
private static final int DEP_LENGTH = 2 * Sudoku.SIZE + 2;
|
||||
public final Sudoku sudoku;
|
||||
public final int x;
|
||||
public final int y;
|
||||
private Value value;
|
||||
private List<Field> dependents;
|
||||
private final Set<Value> domain = EnumSet.allOf(Value.class);
|
||||
|
||||
/**
|
||||
* Creates a field of the specified Sudoku board at the specified coordinates.
|
||||
*
|
||||
* @param sudoku the Sudoku board
|
||||
* @param x x coordinate (0 <= x < 9)
|
||||
* @param y y coordinate (0 <= y < 9)
|
||||
*/
|
||||
public Field(Sudoku sudoku, int x, int y) {
|
||||
if (x < 0 || x >= Sudoku.SIZE || y < 0 || y >= Sudoku.SIZE)
|
||||
throw new IllegalArgumentException("Illegal coordinates " + x + ", " + y);
|
||||
this.sudoku = sudoku;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this field, or null if it is empty.
|
||||
*
|
||||
* @return the value of this field, or null if it is empty.
|
||||
*/
|
||||
public Value getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this field
|
||||
*
|
||||
* @param v the value, or null if this field shall be empty.
|
||||
*/
|
||||
public void setValue(Value v) {
|
||||
value = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the value of this field so that it is empty.
|
||||
*/
|
||||
public void clearValue() {
|
||||
setValue(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this field is empty.
|
||||
*
|
||||
* @return true iff this field is empty.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return value == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this field. As a matter of fact,
|
||||
* its value is returned, or "." if it is empty.
|
||||
*
|
||||
* @return a string representation of this field.
|
||||
*/
|
||||
public String toString() {
|
||||
return isEmpty() ? "." : value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of all values possible for this field that do not violate the Sudoku constraints,
|
||||
* if the field is empty. Otherwise, it returns the empty set. The returned set may be modified if
|
||||
* the field is empty.
|
||||
*
|
||||
* @return the domain of this field.
|
||||
*/
|
||||
public Set<Value> getDomain() {
|
||||
return isEmpty() ? domain : emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of all other fields of this Sudoku field whose values are constrained by the
|
||||
* value of this field.
|
||||
*
|
||||
* @return the list of all dependent fields.
|
||||
*/
|
||||
List<Field> getDependents() {
|
||||
if (dependents == null) {
|
||||
dependents = new ArrayList<>(DEP_LENGTH);
|
||||
|
||||
// fill the list with all fields in the given row and column
|
||||
for (int i = 0; i < Sudoku.SIZE; i++) {
|
||||
if (i != x)
|
||||
dependents.add(sudoku.field(i, y));
|
||||
if (i != y)
|
||||
dependents.add(sudoku.field(x, i));
|
||||
}
|
||||
|
||||
// determine the coordinates of the upper left corner of this field's block
|
||||
final int x0 = 3 * (x / 3);
|
||||
final int y0 = 3 * (y / 3);
|
||||
|
||||
// fill the list with the whole block
|
||||
for (int x1 = x0; x1 < x0 + 3; x1++)
|
||||
if (x1 != x)
|
||||
for (int y1 = y0; y1 < y0 + 3; y1++)
|
||||
if (y1 != y)
|
||||
dependents.add(sudoku.field(x1, y1));
|
||||
}
|
||||
return dependents;
|
||||
}
|
||||
}
|
206
uebung06/src/sudoku/Sudoku.java
Normal file
206
uebung06/src/sudoku/Sudoku.java
Normal file
@ -0,0 +1,206 @@
|
||||
package sudoku;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Sudoku board as a matrix of {@linkplain sudoku.Field} instances.
|
||||
* <p>
|
||||
* Call {@linkplain #solve()} to solve it.
|
||||
*/
|
||||
public class Sudoku {
|
||||
/**
|
||||
* Edge size of the Sudoku board.
|
||||
*/
|
||||
public static final int SIZE = 9;
|
||||
private static final String LS = System.lineSeparator();
|
||||
private final Field[] board = new Field[SIZE * SIZE];
|
||||
|
||||
/**
|
||||
* Creates a Sudoku board with all of its fields being empty.
|
||||
*/
|
||||
public Sudoku() {
|
||||
for (int x = 0; x < SIZE; x++)
|
||||
for (int y = 0; y < SIZE; y++)
|
||||
board[SIZE * y + x] = new Field(this, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field at the specified coordinates
|
||||
*
|
||||
* @param x x coordinate (0 <= x < 9)
|
||||
* @param y y coordinate (0 <= x < 9)
|
||||
* @return the field at the specified coordinates
|
||||
*/
|
||||
public Field field(int x, int y) {
|
||||
return board[SIZE * y + x];
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk operation to set values of the fields.
|
||||
*
|
||||
* @param values a sequence of integers where 0 means empty
|
||||
*/
|
||||
public void initialize(int... values) {
|
||||
if (values.length != board.length)
|
||||
throw new IllegalArgumentException("Wrong Sudoku board with " + values.length + " values");
|
||||
for (int i = 0; i < values.length; i++)
|
||||
if (values[i] != 0)
|
||||
setValue(board[i], Value.of(values[i]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified value of the specified empty field
|
||||
*
|
||||
* @param field the empty field whose value is set
|
||||
* @param value the value of the field
|
||||
* @throws IllegalStateException if the field is not empty
|
||||
* @throws IllegalArgumentException if setting this value would violate the Sudoku constraints
|
||||
* @throws NullPointerException if the value is null
|
||||
*/
|
||||
public void setValue(Field field, Value value) {
|
||||
if (value == null)
|
||||
throw new NullPointerException("value is null");
|
||||
if (!field.isEmpty())
|
||||
throw new IllegalStateException("Value already set: " + field);
|
||||
if (!field.getDomain().contains(value))
|
||||
throw new IllegalArgumentException(value + " is not permitted");
|
||||
for (Field dependent : field.getDependents())
|
||||
dependent.getDomain().remove(value);
|
||||
field.setValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this board.
|
||||
*
|
||||
* @return a string representation of this board
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
if (y == 3 || y == 6) sb.append("---------+---------+---------").append(LS);
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
if (x == 3 || x == 6) sb.append("|");
|
||||
sb.append(" ").append(field(x, y)).append(" ");
|
||||
}
|
||||
sb.append(LS);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for an empty field with minimal domain.
|
||||
*
|
||||
* @return a field with minimal domain, or null no field is empty
|
||||
*/
|
||||
private Field findBestCandidate() {
|
||||
Field best = null;
|
||||
int min = Integer.MAX_VALUE;
|
||||
for (Field f : board)
|
||||
if (f.isEmpty() && f.getDomain().size() < min) {
|
||||
best = f;
|
||||
min = best.getDomain().size();
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to solve the current board. The board is in the solved state if a solution is found,
|
||||
* and unmodified if no solution is found.
|
||||
*
|
||||
* @return true iff a solution has been found.
|
||||
*/
|
||||
public boolean solve() {
|
||||
final Field field = findBestCandidate();
|
||||
if (field == null)
|
||||
// A solution has been found
|
||||
return true;
|
||||
|
||||
// There are empty fields. Try all values of its domain
|
||||
final List<Field> revoke = new ArrayList<>();
|
||||
for (Value v : field.getDomain()) {
|
||||
field.setValue(v);
|
||||
boolean consistent = true;
|
||||
for (Field dependent : field.getDependents())
|
||||
if (dependent.getDomain().contains(v)) {
|
||||
if (dependent.getDomain().size() == 1) {
|
||||
// This is a dead end because field 'dependent'
|
||||
// would have an empty domain
|
||||
consistent = false;
|
||||
break;
|
||||
}
|
||||
revoke.add(dependent);
|
||||
dependent.getDomain().remove(v);
|
||||
}
|
||||
if (consistent && solve())
|
||||
return true;
|
||||
|
||||
// Choosing v as a value lead to a dead end.
|
||||
// Revoke all modifications
|
||||
field.clearValue();
|
||||
for (Field f : revoke)
|
||||
f.getDomain().add(v);
|
||||
revoke.clear();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<Sudoku> solveAll() {
|
||||
List<Sudoku> solutions = new ArrayList<>();
|
||||
solveAll(solutions);
|
||||
return solutions;
|
||||
}
|
||||
|
||||
private void solveAll(List<Sudoku> solutions) {
|
||||
final Field field = findBestCandidate();
|
||||
if (field == null) {
|
||||
// A solution has been found
|
||||
Sudoku copy = new Sudoku();
|
||||
copy.initialize(this.export());
|
||||
solutions.add(copy);
|
||||
return;
|
||||
}
|
||||
|
||||
// There are empty fields. Try all values of its domain
|
||||
final List<Field> revoke = new ArrayList<>();
|
||||
for (Value v : field.getDomain()) {
|
||||
field.setValue(v);
|
||||
boolean consistent = true;
|
||||
for (Field dependent : field.getDependents())
|
||||
if (dependent.getDomain().contains(v)) {
|
||||
if (dependent.getDomain().size() == 1) {
|
||||
// This is a dead end because field 'dependent'
|
||||
// would have an empty domain
|
||||
consistent = false;
|
||||
break;
|
||||
}
|
||||
revoke.add(dependent);
|
||||
dependent.getDomain().remove(v);
|
||||
}
|
||||
|
||||
if (consistent) solveAll(solutions);
|
||||
|
||||
// Revoke all modifications
|
||||
field.clearValue();
|
||||
for (Field f : revoke)
|
||||
f.getDomain().add(v);
|
||||
revoke.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private int[] export() {
|
||||
int[] values = new int[SIZE * SIZE];
|
||||
int idx = 0;
|
||||
while (idx < values.length) {
|
||||
Field f = board[idx];
|
||||
if (f != null) {
|
||||
Value value = f.getValue();
|
||||
if (value != null) values[idx] = value.getId();
|
||||
else values[idx] = 0;
|
||||
}
|
||||
else throw new IllegalStateException("at least one field is not set");
|
||||
++idx;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
68
uebung06/src/sudoku/SudokuApp.java
Normal file
68
uebung06/src/sudoku/SudokuApp.java
Normal file
@ -0,0 +1,68 @@
|
||||
package sudoku;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SudokuApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Sudoku Aufgabenblatt:");
|
||||
System.out.println();
|
||||
final Sudoku boardBlatt = new Sudoku();
|
||||
boardBlatt.initialize(4, 5, 0, 0, 0, 0, 2, 0, 0,
|
||||
6, 0, 0, 0, 2, 4, 8, 0, 0,
|
||||
8, 0, 0, 0, 6, 1, 3, 0, 0,
|
||||
0, 9, 0, 4, 0, 0, 0, 5, 0,
|
||||
0, 1, 0, 2, 0, 8, 0, 7, 0,
|
||||
0, 3, 0, 0, 0, 9, 0, 8, 0,
|
||||
0, 0, 7, 1, 4, 0, 0, 0, 8,
|
||||
0, 0, 2, 7, 9, 0, 0, 0, 6,
|
||||
0, 0, 5, 0, 0, 0, 0, 2, 1);
|
||||
printSolution(boardBlatt);
|
||||
|
||||
System.out.println("Sudoku Handzettel:");
|
||||
System.out.println();
|
||||
final Sudoku boardHandzettel = new Sudoku();
|
||||
boardHandzettel.initialize(7, 0, 0, 0, 2, 5, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 9, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 0, 9, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 6, 0, 0, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 3, 0,
|
||||
8, 2, 0, 0, 0, 0, 5, 0, 0,
|
||||
0, 0, 0, 0, 3, 0, 6, 0, 0,
|
||||
0, 0, 0, 9, 0, 0, 0, 0, 0);
|
||||
printSolution(boardHandzettel);
|
||||
|
||||
System.out.println("Sudoku mit 2 Lösungen:");
|
||||
System.out.println();
|
||||
final Sudoku boardWithTwoSolutions = new Sudoku();
|
||||
boardWithTwoSolutions.initialize(2, 9, 5, 7, 4, 3, 8, 6, 1,
|
||||
4, 3, 1, 8, 6, 5, 9, 0, 0,
|
||||
8, 7, 6, 1, 9, 2, 5, 4, 3,
|
||||
3, 8, 7, 4, 5, 9, 2, 1, 6,
|
||||
6, 1, 2, 3, 8, 7, 4, 9, 5,
|
||||
5, 4, 9, 2, 1, 6, 7, 3, 8,
|
||||
7, 6, 3, 5, 2, 4, 1, 8, 9,
|
||||
9, 2, 8, 6, 7, 1, 3, 5, 4,
|
||||
1, 5, 4, 9, 3, 8, 6, 0, 0);
|
||||
System.out.println(boardWithTwoSolutions);
|
||||
System.out.println("Solutions:");
|
||||
System.out.println();
|
||||
|
||||
List<Sudoku> solutions = boardWithTwoSolutions.solveAll();
|
||||
System.out.println(String.join(System.lineSeparator(), solutions.stream().map(Sudoku::toString).toList()));
|
||||
}
|
||||
|
||||
private static void printSolution(Sudoku sudoku) {
|
||||
System.out.println(sudoku);
|
||||
|
||||
System.out.println();
|
||||
if (sudoku.solve()) {
|
||||
System.out.println("Solution:");
|
||||
System.out.println();
|
||||
System.out.println(sudoku);
|
||||
}
|
||||
else
|
||||
System.out.println("No solution!");
|
||||
}
|
||||
}
|
41
uebung06/src/sudoku/Value.java
Normal file
41
uebung06/src/sudoku/Value.java
Normal file
@ -0,0 +1,41 @@
|
||||
package sudoku;
|
||||
|
||||
/**
|
||||
* The enumeration type of all possible values of a Sudoku field.
|
||||
*/
|
||||
public enum Value {
|
||||
ONE(1), TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT(8), NINE(9);
|
||||
|
||||
private final int id;
|
||||
|
||||
Value(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this value. As a matter of fact, its id is returned.
|
||||
*
|
||||
* @return a string representation of this value.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value with the specified id.
|
||||
*
|
||||
* @param id an id (1 <= id <= 9)
|
||||
* @return the value with the specified id.
|
||||
*/
|
||||
public static Value of(int id) {
|
||||
return values()[id - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of this instance.
|
||||
*
|
||||
* @return the id of this instance.
|
||||
*/
|
||||
public int getId() {return id;}
|
||||
}
|
65
uebung06/test/sudoku/FieldTest.java
Normal file
65
uebung06/test/sudoku/FieldTest.java
Normal file
@ -0,0 +1,65 @@
|
||||
package uebung06.test.sudoku;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import sudoku.*;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class FieldTest {
|
||||
private static final int X = 8;
|
||||
private static final int Y = 5;
|
||||
private static final int NUL = -1;
|
||||
private static final Value VAL = Value.EIGHT;
|
||||
private static Sudoku sudoku;
|
||||
private static Field field;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
sudoku = new Sudoku();
|
||||
field = new Field(sudoku, X, Y);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void illegalXLowerBoundFieldTest() {
|
||||
field = new Field(sudoku, NUL, Y);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void illegalXUpperBoundFieldTest() {
|
||||
field = new Field(sudoku, Sudoku.SIZE, Y);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void illegalYLowerBoundFieldTest() {
|
||||
field = new Field(sudoku, X, NUL);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void illegalYUpperBoundFieldTest() {
|
||||
field = new Field(sudoku, X, Sudoku.SIZE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueFieldTest() {
|
||||
field.setValue(VAL);
|
||||
assertEquals(field.getValue(), VAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearValueFieldTest() {
|
||||
field.setValue(VAL);
|
||||
field.clearValue();
|
||||
assertNull(field.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValueEmptyFieldTest() {
|
||||
field.setValue(VAL);
|
||||
field.clearValue();
|
||||
assertTrue(field.isEmpty());
|
||||
}
|
||||
}
|
129
uebung06/test/sudoku/SudokuAppTest.java
Normal file
129
uebung06/test/sudoku/SudokuAppTest.java
Normal file
@ -0,0 +1,129 @@
|
||||
package uebung06.test.sudoku;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import sudoku.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SudokuAppTest {
|
||||
private static final int MAX = 81;
|
||||
private static final int MIN = 0;
|
||||
private static final int SUDOKU_SIZE = 9;
|
||||
private static Sudoku board;
|
||||
private static int[] init;
|
||||
private static int[] wrongSol;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
board = new Sudoku();
|
||||
init = IntStream.of(4, 5, 0, 0, 0, 0, 2, 0, 0,
|
||||
6, 0, 0, 0, 2, 4, 8, 0, 0,
|
||||
8, 0, 0, 0, 6, 1, 3, 0, 0,
|
||||
0, 9, 0, 4, 0, 0, 0, 5, 0,
|
||||
0, 1, 0, 2, 0, 8, 0, 7, 0,
|
||||
0, 3, 0, 0, 0, 9, 0, 8, 0,
|
||||
0, 0, 7, 1, 4, 0, 0, 0, 8,
|
||||
0, 0, 2, 7, 9, 0, 0, 0, 6,
|
||||
0, 0, 5, 0, 0, 0, 0, 2, 1).toArray();
|
||||
wrongSol = IntStream.of(4, 5, 1, 8, 7, 3, 2, 6, 9,
|
||||
6, 7, 3, 9, 2, 4, 8, 1, 5,
|
||||
8, 2, 9, 5, 6, 1, 3, 4, 7,
|
||||
2, 9, 8, 4, 1, 7, 6, 5, 3,
|
||||
5, 1, 6, 2, 3, 8, 9, 7, 4,
|
||||
7, 3, 4, 6, 5, 9, 1, 8, 2,
|
||||
3, 6, 7, 1, 4, 2, 5, 9, 8,
|
||||
1, 8, 2, 7, 9, 5, 4, 3, 6,
|
||||
9, 5, 4, 3, 8, 6, 7, 2, 1).toArray();
|
||||
}
|
||||
|
||||
//Testing first If-condition in Sudoku.init
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void illegalLowerBoundInitSudokuAppTest() {
|
||||
board.initialize(IntStream.range(MIN, MIN+1).toArray());
|
||||
}
|
||||
|
||||
//Testing first If-condition in Sudoku.init
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void illegalUpperBoundInitSudokuAppTest() {
|
||||
board.initialize(IntStream.range(MIN, MAX+1).toArray());
|
||||
}
|
||||
|
||||
//Testing ArrayIndex of Value
|
||||
@Test(expected = ArrayIndexOutOfBoundsException.class)
|
||||
public void illegalArrayIndexOutOfBoundInitSudokuAppTest() {
|
||||
board.initialize(IntStream.range(MIN, MAX).toArray());
|
||||
}
|
||||
|
||||
//Testing Sudoku.solve()
|
||||
@Test
|
||||
public void correctSolutionSudokuAppTest() {
|
||||
board.initialize(init);
|
||||
board.solve();
|
||||
|
||||
assertTrue(verifySudokuSol());
|
||||
}
|
||||
|
||||
//Just testing verifySudokuSol-Method
|
||||
@Test
|
||||
public void wrongSolutionSudokuAppTest() {
|
||||
try {
|
||||
board.initialize(wrongSol);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
//do nothing, just handling throwing exceptions from Sudoku-class
|
||||
}
|
||||
|
||||
assertFalse(verifySudokuSol());
|
||||
}
|
||||
|
||||
public Boolean verifySudokuSol() {
|
||||
HashSet<Value> rows = new HashSet<>();
|
||||
HashSet<Value> cols = new HashSet<>();
|
||||
|
||||
HashMap<Integer, HashSet<Value>> blocks = new HashMap<>();
|
||||
IntStream.range(0, SUDOKU_SIZE)
|
||||
.forEach(block -> blocks.put(block, new HashSet<>())); //init Hashsets for every block
|
||||
|
||||
for (int y = 0; y < SUDOKU_SIZE; y++) {
|
||||
for (int x = 0; x < SUDOKU_SIZE; x++) {
|
||||
//check column
|
||||
Value val = board.field(x, y).getValue();
|
||||
if (!cols.add(val))
|
||||
return false;
|
||||
if (cols.size() == SUDOKU_SIZE)
|
||||
cols.clear();
|
||||
|
||||
//check row
|
||||
val = board.field(y, x).getValue();
|
||||
if (!rows.add(val))
|
||||
return false;
|
||||
if (rows.size() == SUDOKU_SIZE)
|
||||
rows.clear();
|
||||
|
||||
//check 3x3 block
|
||||
val = board.field(x, y).getValue();
|
||||
if (!blocks.get(getBlockIndex(x, y)).add(val))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getBlockIndex(int x, int y) {
|
||||
return getColIndex(x) + getRowIndex(y);
|
||||
}
|
||||
|
||||
public int getColIndex(int x) {
|
||||
return x / 3;
|
||||
}
|
||||
|
||||
public int getRowIndex(int y) {
|
||||
return (y/3)*3;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user