Please criticize the classes GameJudgeImpl
and GameInfo
so that I could make them clearer.
public interface GameJudge {
public GameInfo gameInfo();
}
public enum GameResult {
UNKNOWN, DRAW, PLAYER_WINS, OPPONENT_WINS
}
public enum Cell {
EMPTY, PLAYER, OPPONENT
}
↓
public class GameInfo {
private final GameResult gameResult;
private final List<Matrix.Position> cellsOnFire;
public static GameInfo unknownResult() {
return new GameInfo(GameResult.UNKNOWN, new ArrayList<Matrix.Position>());
}
public static GameInfo drawResult() {
return new GameInfo(GameResult.DRAW, new ArrayList<Matrix.Position>());
}
public GameInfo(GameResult gameResult, List<Matrix.Position> cellsOnFire) {
this.gameResult = gameResult;
this.cellsOnFire = cellsOnFire;
}
public GameResult gameResult() {
return gameResult;
}
public List<Matrix.Position> cellsOnFire() {
return cellsOnFire;
}
public boolean resultIsKnown() {
return gameResult != GameResult.UNKNOWN;
}
}
↓
public class GameJudgeImpl implements GameJudge {
private final Matrix<Cell> gameBoard;
private final int gameBoardDimension;
public GameJudgeImpl(Matrix<Cell> gameBoard) {
this.gameBoard = gameBoard;
this.gameBoardDimension = gameBoard.rows;
}
@Override
public GameInfo gameInfo() {
GameInfo gameInfo = checkAllRowsColumns();
if (gameInfo.resultIsKnown()) {
return gameInfo;
}
gameInfo = checkDiagonals();
if (gameInfo.resultIsKnown()) {
return gameInfo;
}
if (gameBoard.contains(Cell.EMPTY)) {
return GameInfo.unknownResult();
}
return GameInfo.drawResult();
}
private GameInfo checkAllRowsColumns() {
for (int i = 0; i < gameBoardDimension; ++i) {
GameInfo gameInfo = checkRowColumn(i);
if (gameInfo.resultIsKnown()) {
return gameInfo;
}
}
return GameInfo.unknownResult();
}
private GameInfo checkRowColumn(int index) {
GameInfo rowGameInfo = checkRow(index);
if (rowGameInfo.resultIsKnown()) {
return rowGameInfo;
} else {
return checkColumn(index);
}
}
private GameInfo checkRow(int row) {
return gameInfoByCellsPositions(cellsPositionsOnRow(row));
}
private List<Matrix.Position> cellsPositionsOnRow(int row) {
List<Matrix.Position> cells = new ArrayList<Matrix.Position>(gameBoardDimension);
for (int column = 0; column < gameBoardDimension; ++column) {
cells.add(new Matrix.Position(row, column));
}
return cells;
}
private GameInfo gameInfoByCellsPositions(List<Matrix.Position> cellsPositions) {
Matrix.Position firstCellOnLinePosition = cellsPositions.get(0);
Cell firstCellOnLine = gameBoard.get(firstCellOnLinePosition);
if (firstCellOnLine == Cell.EMPTY) {
return GameInfo.unknownResult();
}
for (int i = 1; i < gameBoardDimension; ++i) {
Matrix.Position currentPosition = cellsPositions.get(i);
Cell currentCell = gameBoard.get(currentPosition);
if (firstCellOnLine != currentCell) {
return GameInfo.unknownResult();
}
}
return new GameInfo(cellToResult(firstCellOnLine), cellsPositions);
}
private GameResult cellToResult(Cell cell) {
if (cell == Cell.PLAYER) {
return GameResult.PLAYER_WINS;
} else if (cell == Cell.OPPONENT) {
return GameResult.OPPONENT_WINS;
}
throw new IllegalArgumentException("Input cell must be not empty!");
}
private GameInfo checkColumn(int column) {
return gameInfoByCellsPositions(cellsPositionsOnColumn(column));
}
private List<Matrix.Position> cellsPositionsOnColumn(int column) {
List<Matrix.Position> cells = new ArrayList<Matrix.Position>(gameBoardDimension);
for (int row = 0; row < gameBoardDimension; ++row) {
cells.add(new Matrix.Position(row, column));
}
return cells;
}
private GameInfo checkDiagonals() {
GameInfo leftUpperDiagonalGameInfo = checkLeftUpperDiagonal();
if (leftUpperDiagonalGameInfo.resultIsKnown()) {
return leftUpperDiagonalGameInfo;
} else {
return checkRightUpperDiagonal();
}
}
private GameInfo checkLeftUpperDiagonal() {
return gameInfoByCellsPositions(cellsPositionsOnLeftUpperDiagonal());
}
private List<Matrix.Position> cellsPositionsOnLeftUpperDiagonal() {
List<Matrix.Position> positions = new ArrayList<Matrix.Position>(gameBoardDimension);
for (int i = 0; i < gameBoardDimension; ++i) {
positions.add(new Matrix.Position(i, i));
}
return positions;
}
private GameInfo checkRightUpperDiagonal() {
return gameInfoByCellsPositions(cellsPositionsOnRightUpperDiagonal());
}
private List<Matrix.Position> cellsPositionsOnRightUpperDiagonal() {
List<Matrix.Position> positions = new ArrayList<Matrix.Position>(gameBoardDimension);
for (int i = 0; i < gameBoardDimension; ++i) {
positions.add(new Matrix.Position(i, gameBoardDimension - i - 1));
}
return positions;
}
}