package org.sudoku;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.util.*;
public class SudokuBoard {
private final SudokuField[][] board = new SudokuField[9][9];
private final SudokuSolver solver;
private final SudokuColumn[] columnObservers = new SudokuColumn[9];
private final SudokuRow[] rowObservers = new SudokuRow[9];
private final SudokuBox[] boxObservers = new SudokuBox[9];
private boolean state = true;
public SudokuBoard(SudokuSolver solver) {
this.solver = Objects.requireNonNull(solver);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
board[i][j] = new SudokuField();
}
}
for (int y = 0; y < 9; y++) {
List<SudokuField> fields = Arrays.asList(new SudokuField[9]);
for (int i = 0; i < 9; i++) {
fields.set(i, board[y][i]);
}
rowObservers[y] = new SudokuRow(fields);
}
for (int x = 0; x < 9; x++) {
List<SudokuField> fields = Arrays.asList(new SudokuField[9]);
for (int i = 0; i < 9; i++) {
fields.set(i, board[i][x]);
}
columnObservers[x] = new SudokuColumn(fields);
}
int tableIndex = 0;
for (int x = 0; x < 9; x += 3) {
for (int y = 0; y < 9; y += 3) {
List<SudokuField> fields = Arrays.asList(new SudokuField[9]);
int fieldIndex = 0;
for (int i = x; i < x + 3; i++) {
for (int j = y; j < y + 3; j++) {
fields.set(fieldIndex, board[i][j]);
fieldIndex++;
}
}
boxObservers[tableIndex] = new SudokuBox(fields);
tableIndex++;
}
}
int tableIndex2 = 0;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
board[i][j].setObservers(columnObservers[i], rowObservers[j], boxObservers[tableIndex2]);
if (j % 3 == 2) {
tableIndex2++;
}
}
tableIndex2 = i / 3;
}
}
public void solveGame() {
solver.solve(this);
}
public boolean isSafe() {
return checkBoard();
}
public int get(int y, int x) {
return board[y][x].getFieldValue();
}
public void set(int y, int x, int value) {
try {
board[y][x].setFieldValue(value);
} catch (IllegalArgumentException e) {
state = false;
}
}
public SudokuRow getRow(int y) {
return rowObservers[y];
}
public SudokuColumn getColumn(int x) {
return columnObservers[x];
}
public SudokuBox getBox(int y, int x) {
int row = y / 3 * 3;
int col = x / 3 * 3;
return boxObservers[col + 3 * row];
}
private boolean checkBoard() {
if (state) {
return true;
}
state = true;
for (int i = 0; i < 9; i++) {
state &= columnObservers[i].verify() & rowObservers[i].verify() & boxObservers[i].verify();
}
return state;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
stringBuilder.append(board[i][j].getFieldValue());
if (j < 8) {
stringBuilder.append(" ");
}
}
stringBuilder.append("\n");
}
return stringBuilder.toString();
}
}
I tried to write the equals method this way (below) but unfortunately it does not work. I wanted to Override the following methods in all data model classes: toString(), equals() and hashCode() methods.
Using an external library to implement them efficiently.
Apache commons-lang3
implementation of the hashCode() and equals() methods were consistent with each other. When I set two boards with same values, equals method should return true.
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
SudokuBoard otherBoard = (SudokuBoard) obj;
return new EqualsBuilder()
.append(board, otherBoard.board)
.append(solver, otherBoard.solver)
.append(columnObservers, otherBoard.columnObservers)
.append(rowObservers, otherBoard.rowObservers)
.append(boxObservers, otherBoard.boxObservers)
.append(state, otherBoard.state)
.isEquals();
}
}
I think your problem is that one+ field is incompatible with the EqualBuilder. Specifically the class does not itself implement an
equals()properly. As you don't provide the source for these classes we cannot know.I thought perhaps it was the 2D array
SudokuField[][] board. But looking at line 823 of the source of the utility:https://commons.apache.org/proper/commons-lang//jacoco/org.apache.commons.lang3.builder/EqualsBuilder.java.html
it looks as if properly recurses.
So, what I would do is, take each
append()inAnd remove one at a time and see which one is breaking the equality.
The other thing you could do is try
EqualsBuilder.reflectionEquals(this, obj)which ought to traverse the full tree depth using reflection