import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream; import java.util.List;
import java.util.LinkedList;
import java.util.Random;
public class Board implements Cloneable, Serializable {
/**
* Number of elements of the Sudoku
*/
public static int ELEMENTS = Field.POSSIBILITIES * Field.POSSIBILITIES;
protected Field[] board;
/**
*
*/
public Board() {
this.board = new Field[ELEMENTS];
for (int i = 0; i < ELEMENTS; i++) {
this.board[i] = new Field();
}
}
/**
* Resolves field addresses.
*
* @param struct
* @param structNr
* @param element
* @return
*/
public Field getField(Structure struct, int structNr, int element) {
return board[getIndex(struct, structNr, element)];
}
protected int getIndex(Structure str, int nr, int ele) {
int sqrt = (int) Math.round(Math.sqrt(Field.POSSIBILITIES));
if (str.name().equals("COL"))
return nr + (ele * Field.POSSIBILITIES);
else if (str.name().equals("ROW"))
return (nr * Field.POSSIBILITIES) + ele;
else if (str.name().equals("BOX"))
return Field.POSSIBILITIES * (nr / sqrt * sqrt + ele / sqrt) + (nr % sqrt * sqrt + ele % sqrt);
else
return -1;
}
public void setField(Structure structure, int structNr, int element, Field f) {
board[getIndex(structure, structNr, element)] = f;
}
//private static final long serialVersionUID = 1L;
public Object clone() throws CloneNotSupportedException {
Board clone = new Board();
for (int i = 0; i < board.length; i++) {
clone.board[i] = (Field) board[i].clone();
}
return clone;
}
private void writeObject(ObjectOutputStream aOutputStream) throws IOException {
aOutputStream.writeObject(board);
aOutputStream.defaultWriteObject();
}
private void readObject(ObjectInputStream aInputStream) throws ClassNotFoundException, IOException {
aInputStream.defaultReadObject();
board = (Field[]) aInputStream.readObject();
}
public boolean isSolved() {
for (int i = 0; i < board.length; i++)
if (!board[i].isSet())
return false;
return true;
}
public boolean trySetField(Structure str, int strIndex, int element, Field f) {
boolean validRemoveAction = removeValueFromStructures(getIndex(str, strIndex, element), f.getValue());
if (validRemoveAction && getField(str, strIndex, element).getRemainingPos().contains((Object) f.getValue())) {
this.setField(str, strIndex, element, f);
return true;
} else
return false;
}
protected boolean removeValueFromStructures(int index, int value) {
List relatedFieldIndices = getRelatedFieldIndices(index);
for (int i = 0; i < relatedFieldIndices.size(); i++) {
if (!board[(Integer) relatedFieldIndices.get(i)].isSet()) {
List remainingPos = board[(Integer) relatedFieldIndices.get(i)].getRemainingPos();
if (remainingPos.contains(value) && remainingPos.size() <= 1)
return false;
remainingPos.remove((Object)value);
board[(Integer) relatedFieldIndices.get(i)] = new Field(remainingPos);
}
}
return true;
}
protected int getStructureIndex(int index, Structure str) {
int sqrt = (int) Math.round(Math.sqrt(Field.POSSIBILITIES));
if (str.name().equals("ROW"))
return index / Field.POSSIBILITIES;
else if (str.name().equals("COL"))
return index % Field.POSSIBILITIES;
else if (str.name().equals("BOX"))
return sqrt * (index / (sqrt * Field.POSSIBILITIES)) + (index % Field.POSSIBILITIES) / sqrt;
else
return -1;
}
protected List getRelatedFieldIndices(int index) {
List indices = new LinkedList();
Structure str;
int strIndex;
int indexProcessing;
for (int i = 0; i < Structure.values().length; i++) {
str = Structure.values()[i];
strIndex = getStructureIndex(index, str);
for (int j = 0; j < Field.POSSIBILITIES; j++) {
indexProcessing = getIndex(str, strIndex, j);
if (! (indices.contains(indexProcessing) || indexProcessing == index)) {
indices.add(indexProcessing);
}
}
}
return indices;
}
public void removeRandomSetField(){
Random r = new Random();
int size = Field.POSSIBILITIES*Field.POSSIBILITIES;
int rIndex = r.nextInt(size);
int counter = 0;
while( (board[rIndex].value <= 0) && counter < size){
rIndex = ((rIndex + counter) % size);
counter++;
}
//rIndex known
//recreate field
Board output = new Board();
for(int i=0;i<Field.POSSIBILITIES;i++){
for(int j=0;j<Field.POSSIBILITIES;j++){
if(getIndex(Structure.ROW, i, j) != rIndex){
Field f = getField(Structure.ROW, i, j);
if(f.isSet())
output.trySetField(Structure.ROW, i, j, new Field(f.getValue()));
}
}
}
board = output.board;
}
}