I redid a Reversi game state class that is online. It follows the conventional rules of the board game. The game state connects to a command line interface now. I am unfamiliar with Android so comments related to that would be especially appreciated. Java related comments would be useful too.
/**
* Date: 11/3/13
* Time: 11:07 AM
* based on https://github.com/dweekly/android-reversi
*/
public class GameState {
public static final byte DIM = 8;
public static final byte MAXRAYS = 8;
public static final char LIGHT = 'W';
public static final char DARK = 'B';
private final static char[][] DEFAULTBOARD = {
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', 'W', 'B', ' ', ' ', ' '},
{' ', ' ', ' ', 'B', 'W', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}
};
private char _board[][];
private char _currentSide;
private boolean _frozen;
public GameState() {
this(DEFAULTBOARD, DARK);
}
public GameState(char board[][], char currentSide) {
_board = new char[DIM][DIM];
transferBoard(_board, board);
_currentSide = currentSide;
_frozen = false;
}
public void freeze(boolean state) {
_frozen = state;
}
public void transfer(GameState copy) {
assert(!_frozen);
_currentSide = copy._currentSide;
transferBoard(_board, copy._board);
}
public void swapSides() {
assert(!_frozen);
assert (Location.isaSide(_currentSide));
_currentSide = (_currentSide == LIGHT) ? DARK : LIGHT;
}
private static void transferBoard(char[][] board1, char[][] board2) {
for (byte x = 0; x < DIM; x++)
for (byte y = 0; y < DIM; y++)
board1[x][y] = board2[x][y];
}
public byte moveTo(byte x, byte y, byte[] turners) {
assert(!_frozen);
return moveTo(x, y, turners, false);
}
public byte previewMove(byte x, byte y) {
return moveTo(x, y, null, true);
}
private byte moveTo(byte x, byte y, byte[] turners, boolean preview) {
assert (Location.isaSide(_currentSide));
assert (Location.isEmpty(_board[x][y]));
assert (Location.isInBounds(x, y));
byte turnerCount = makeTurners(_currentSide, _board, x, y, turners);
if (preview) {
return turnerCount;
}
assert(!_frozen);
_board[x][y] = _currentSide;
for (byte i = 0; i < turnerCount; i++) {
Location.setLocation(_currentSide, _board, turners[i]);
}
return turnerCount;
}
public char at(byte x, byte y) {
return _board[x][y];
}
public boolean isCurrentSide(char c) {
return _currentSide == c;
}
public boolean isFirstSide() {
return _currentSide == GameState.DARK;
}
private static boolean checkForTurner(char currentSide, char[][] board, byte x, byte y) {
return makeTurners(currentSide, board, x, y, null) != 0;
}
private static byte makeTurners(char currentSide, char[][] board, byte x, byte y, byte[] turners) {
byte maxIndex = 0;
for (byte dx = -1; dx <= 1; dx++) {
for (byte dy = -1; dy <= 1; dy++) {
if (dx == 0 && dy == 0)
continue;
for (byte steps = 1; steps < DIM; steps++) {
int ray_x = x + dx * steps;
int ray_y = y + dy * steps;
if (Location.isOutOfBounds(ray_x, ray_y) || Location.isEmpty(board[ray_x][ray_y]))
break;
if (board[ray_x][ray_y] == currentSide) {
if (steps > 1) {
for (int backStep = steps - 1; backStep > 0; backStep--) {
if (turners != null) {
turners[maxIndex] = Location.toLocation(x + dx * backStep, y + dy * backStep);
}
maxIndex++;
}
}
break;
}
assert(Location.getOtherSide(currentSide) == board[ray_x][ray_y]);
}
}
}
return maxIndex;
}
public byte makePossibleMoves(byte[] locations) {
byte locationIndex = 0;
for (byte x = 0; x < DIM; x++) {
for (byte y = 0; y < DIM; y++) {
if (Location.isEmpty(_board[x][y]) && checkForTurner(_currentSide, _board, x, y)) {
if (locations != null) {
locations[locationIndex] = Location.toLocation(x, y);
}
locationIndex++;
}
}
}
return locationIndex;
}
public byte getScore(char side) {
assert (Location.isValid(side));
byte result = 0;
for (byte x = 0; x < DIM; x++) {
for (byte y = 0; y < DIM; y++) {
if (_board[x][y] == side)
result++;
}
}
return result;
}
public String toString() {
StringBuffer sb = new StringBuffer();
for (byte y = 0; y < DIM; y++) {
for (byte x = 0; x < DIM; x++) {
if (Location.isEmpty(_board[x][y]))
sb.append(".");
else
sb.append(_board[x][y]);
}
sb.append("\n");
}
sb.append("\n");
return sb.toString();
}
}
/**
* Date: 11/3/13
* Time: 11:33 AM
*/
public class Location {
public static boolean isValid(char c) {
return c == ' ' || c == 'B' || c == 'W';
}
public static boolean isaSide(char c) {
return c == 'B' || c == 'W';
}
public static char getOtherSide(char c) {
return c == 'B' ? 'W' : 'B';
}
public static boolean isEmpty(char c) {
return c == ' ';
}
public static boolean isInBounds(byte b) {
return isInBounds(toX(b), toY(b));
}
public static boolean isInBounds(int x, int y) {
return x >= 0 && x < GameState.DIM && y >= 0 && y < GameState.DIM;
}
public static boolean isOutOfBounds(int x, int y) {
return !isInBounds(x, y);
}
public static byte toLocation(int x, int y) {
assert (isInBounds(x, y));
return (byte) (x + y * GameState.DIM);
}
public static void setLocation(char side, char[][] board, byte loc) {
board[Location.toX(loc)][Location.toY(loc)] = side;
}
public static byte toX(byte b) {
return (byte) (b % GameState.DIM);
}
public static byte toY(byte b) {
return (byte) (b / GameState.DIM);
}
}