I tried to get back into Java by implementing a simplified version of the 2048 game. What I am mainly looking for is ways to reduce code duplication, all of my move functions have a very similar but distinct pattern.
Suggestions on better patterns, practices or optimizations are welcome, keeping in mind that I am trying to implement my functionality without relying on any Libraries (built-in or otherwise).
public class Game {
int[][] board;
int COLNUM = 4;
int ROWNUM = 4;
int globalPointer = 0;
// demonstration code to illustrate usage
public static void main (String[] args) {
Game game = new Game();
game.printBoard();
game.moveSouth();
game.printBoard();
game.moveWest();
game.printBoard();
game.moveWest();
game.printBoard();
game.moveEast();
game.printBoard();
game.moveNorth();
game.printBoard();
}
// simplified constructor, could add option to provide 2D array to instantiate the board
public Game() {
board = new int[ROWNUM][COLNUM];
board[0][0] = 2;
board[1][0] = 8;
board[2][0] = 4;
board[3][0] = 8;
board[0][1] = 1;
board[0][2] = 2;
board[0][3] = 1;
board[2][1] = 4;
board[2][2] = 4;
board[2][3] = 4;
}
public void printBoard() {
String output = "";
for (int i = 0; i < ROWNUM; i++) {
String row = "";
for (int j = 0; j < COLNUM; j++) {
row += board[i][j] + ",";
}
row += "\n";
output += row;
}
System.out.println(output);
}
public void moveNorth() {
for (int col = 0; col < COLNUM; col++) {
globalPointer = 0;
for (int row = 0; row < ROWNUM; row++) {
// if not zero we try to suck in the next tile
if (board[row][col] != 0) {
// if we had a prior zero tile then shift the column
if (globalPointer <= row) {
shiftRowTiles(row, col, false);
}
}
}
}
}
public void moveSouth() {
for (int col = 0; col < COLNUM; col++) {
globalPointer = ROWNUM - 1;
for (int row = ROWNUM -1; row >= 0; row--) {
// if not zero we try to suck in the next tile
if (board[row][col] != 0) {
// if we had a prior zero tile then shift the column
if (globalPointer >= row) {
shiftRowTiles(row, col, true);
}
}
}
}
}
public void moveWest() {
for (int row = 0; row < ROWNUM; row++) {
globalPointer = 0;
for (int col = 0; col < COLNUM; col++) {
// if not zero we try to suck in the next tile
if (board[row][col] != 0) {
// if we had a prior zero tile then shift the row
if (globalPointer <= col) {
shiftColTiles(row, col, false);
}
}
}
}
}
public void moveEast() {
for (int row = 0; row < ROWNUM; row++) {
globalPointer = COLNUM - 1;
for (int col = COLNUM - 1; col >= 0; col--) {
// if not zero we try to suck in the next tile
if (board[row][col] != 0) {
// if we had a prior zero tile then shift the row
if (globalPointer >= col) {
shiftColTiles(row, col, true);
}
}
}
}
}
private void shiftRowTiles(int currentRow, int currentCol, boolean reverse) {
// if we have same tiles we suck them in
if (board[globalPointer][currentCol] == 0 || board[globalPointer][currentCol] == board[currentRow][currentCol]) {
if (currentRow > globalPointer || (reverse && (globalPointer > currentRow))) {
board[globalPointer][currentCol] += board[currentRow][currentCol];
board[currentRow][currentCol] = 0;
}
} else {
if (reverse) {
globalPointer--;
} else {
globalPointer++;
}
// look around to shift away zeroes in sequences
shiftRowTiles(currentRow, currentCol, reverse);
}
}
private void shiftColTiles(int currentRow, int currentCol, boolean reverse) {
// if we have same tiles we suck them in
if (board[currentRow][globalPointer] == 0 || board[currentRow][globalPointer] == board[currentRow][currentCol]) {
if (currentCol > globalPointer || (reverse && (globalPointer > currentCol))) {
board[currentRow][globalPointer] += board[currentRow][currentCol];
board[currentRow][currentCol] = 0;
}
} else {
if (reverse) {
globalPointer--;
} else {
globalPointer++;
}
// look around to shift away zeroes in sequences
shiftColTiles(currentRow, currentCol, reverse);
}
}
}