/**
* Returns the maximum value in the gameField matrix.
*/
private int getMaxTileValue() {
int max = 2;
for (int x = 0; x < SIDE; x ++) {
for (int y = 0; y < SIDE; y++) {
max = Math.max(gameField[x][y], max);
}
}
return max;
}
package com.codegym.games.game2048;
import com.codegym.engine.cell.*;
public class Game2048 extends Game {
private static final int SIDE = 4;
private int [][] gameField = new int[SIDE][SIDE];
private boolean isGameStopped;
/**
* Set the size of the game board, decide whether to display the grid, etc...
*/
@Override
public void initialize() {
setScreenSize(SIDE, SIDE);
createGame();
drawScene();
}
private void createGame() {
createNewNumber();
createNewNumber();
}
/**
* Draw the game field and colors all the cells.
*/
private void drawScene() {
for (int x = 0; x < SIDE; x ++) {
for (int y = 0; y < SIDE; y ++) {
setCellColoredNumber(x, y, gameField[y][x]);
}
}
}
/**
* Selects a random cell whose value is 0 in the gameField matrix.
* If getRandomNumber(10) returns the number 9, the cell is assigned the value 4;
* If getRandomNumber(10) returns a number between 0 and 8, the cell is assigned the value 2.
*/
private void createNewNumber() {
if (getMaxTileValue() == 2048) { win(); }
int x, y, cell;
do {
x = getRandomNumber(SIDE);
y = getRandomNumber(SIDE);
cell = gameField[x][y];
} while(cell != 0);
gameField[x][y] = getRandomNumber(10) == 9 ? 4 : 2;
}
/**
* Takes as arguments a cell's coordinates and value, and...
* ...calculate the cell color (using the getColorByValue() method).
* ...display the cell value and color on the game board.
*/
private void setCellColoredNumber(int x, int y, int value) {
setCellValueEx(x, y, getColorByValue(value), value == 0 ? "" : String.valueOf(value));
}
/**
* Return a color based on the cell value passed to method
*/
private Color getColorByValue(int value) {
switch (value) {
case 2:
return Color.SILVER;
case 4:
return Color.LIGHTGREEN;
case 8:
return Color.MEDIUMSEAGREEN;
case 16:
return Color.GREEN;
case 32:
return Color.TEAL;
case 64:
return Color.STEELBLUE;
case 128:
return Color.DODGERBLUE;
case 256:
return Color.BLUEVIOLET;
case 512:
return Color.MEDIUMVIOLETRED;
case 1024:
return Color.CRIMSON;
case 2048:
return Color.FIREBRICK;
default:
return Color.LIGHTGRAY;
}
}
/**
* Shifts all non-zero elements of the row array to the left (towards the zero index).
* Zero elements are moved to the right.
* If at least one element was moved, the method returns true, otherwise – false.
*/
private boolean compressRow(int[] row) {
int zeros = 0;
int shifts = 0;
for (int index = 0; index < row.length; index ++) {
if (row[index] == 0) { zeros ++; }
else if (zeros > 0) {
row[index - zeros] = row[index];
row[index] = 0;
shifts ++;
}
}
return shifts > 0;
}
/**
* Merges adjacent pairs of identical non-zero elements of the row array.
*/
private boolean mergeRow(int[] row) {
boolean merge = false;
for (int index = 0; index < row.length - 1; index ++) {
if (row[index] == 0) { continue; }
if (row[index] == row [index + 1]) {
row[index] += row[index + 1];
row[index + 1] = 0;
merge = true;
}
}
return merge;
}
/**
* Returns the maximum value in the gameField matrix.
*/
private int getMaxTileValue() {
int max = 2;
for (int x = 0; x < SIDE; x ++) {
for (int y = 0; y < SIDE; y++) {
max = Math.max(gameField[y][x], max);
}
}
return max;
}
private void win() {
isGameStopped = true;
showMessageDialog(Color.TEAL, "You won!", Color.WHITE, 30);
}
/**
* When a key is pressed, the corresponding action happens (shift, merge).
*/
@Override
public void onKeyPress(Key key) {
switch (key) {
case UP:
moveUp();
drawScene();
break;
case DOWN:
moveDown();
drawScene();
break;
case LEFT:
moveLeft();
drawScene();
break;
case RIGHT:
moveRight();
drawScene();
break;
}
}
// MOVES
private void moveUp() {
for (int rotation = 0; rotation < 4; rotation ++) {
if (rotation == 3) { moveLeft(); }
rotateClockwise();
}
}
private void moveDown() {
for (int rotation = 0; rotation < 4; rotation ++) {
if (rotation == 1) { moveLeft(); }
rotateClockwise();
}
}
private void moveLeft() {
boolean merge = false;
for (int indexRow = 0; indexRow < gameField.length; indexRow ++) {
if (compressRow(gameField[indexRow])) { merge = true; };
if (mergeRow(gameField[indexRow])) { merge = true; };
if (compressRow(gameField[indexRow])) { merge = true; };
}
if (merge) { createNewNumber(); }
}
private void moveRight() {
for (int rotation = 0; rotation < 4; rotation ++) {
if (rotation == 2) { moveLeft(); }
rotateClockwise();
}
}
/**
* Rotates the gameField matrix clockwise by 90 degrees.
*/
private void rotateClockwise() {
int[][] copy = new int[SIDE][SIDE];
for (int indexRow = 0; indexRow < SIDE; indexRow++) {
copy[indexRow] = gameField[indexRow].clone();
}
for (int indexRow = 0; indexRow < SIDE; indexRow ++) {
for (int indexColumn = 0; indexColumn < SIDE; indexColumn ++) {
int rotateIndex = SIDE - 1 - indexColumn;
gameField[indexRow][indexColumn] = copy[rotateIndex][indexRow];
}
}
}
}