Final task is failing with the following error:
The onKeyPress(Key) method must call the gameOver() method and do nothing else, if the canUserMove() method returns false.
Recommendation from your mentor:
Be sure that the gameOver() method is called if the canUserMove() method returns false.
package com.codegym.games.game2048;
import com.codegym.engine.cell.*;
import java.util.Arrays;
public class Game2048 extends Game
{
private static final int SIDE = 4;
private int[][] gameField = new int[SIDE][SIDE];
private boolean isGameStopped = false;
private boolean canMove = false;
@Override
public void initialize()
{
setScreenSize (SIDE, SIDE);
createGame();
drawScene();
}
private void drawScene()
{
for (int y = 0; y < SIDE; y++)
{
for (int x = 0; x < SIDE; x++)
{
setCellColoredNumber(x, y, gameField[y][x]);
}
}
}
private void createGame()
{
createNewNumber();
createNewNumber();
}
private void createNewNumber()
{
if (getMaxTileValue() == 2048)
{
win();
}
int x;
int y;
do
{
x = getRandomNumber(SIDE); //Choose a random cell
y = getRandomNumber(SIDE);
} while(gameField[x][y] != 0); //which should be empty
int chance = getRandomNumber(10);
if (chance == 9) gameField[x][y] = 4; //10% chance for a 4
else gameField[x][y] = 2; //90% chance for a 2
}
private void setCellColoredNumber(int x, int y, int value)
{
Color color = getColorByValue(value);
if (value > 0)
{
setCellValueEx(x, y, color, Integer.toString(value));
}
else
{
setCellValueEx(x, y, color, "");
}
}
private Color getColorByValue(int value)
{
Color color = null;
switch(value)
{
case 0:
color = Color.GRAY;
break;
case 2:
color = Color.LIGHTBLUE;
break;
case 4:
color = Color.LIGHTPINK;
break;
case 8:
color = Color.LIGHTGREEN;
break;
case 16:
color = Color.LIGHTCYAN;
break;
case 32:
color = Color.LIGHTSKYBLUE;
break;
case 64:
color = Color.MAGENTA;
break;
case 128:
color = Color.ORANGE;
break;
case 256:
color = Color.PINK;
break;
case 512:
color = Color.YELLOW;
break;
case 1024:
color = Color.PURPLE;
break;
case 2048:
color = Color.OLDLACE;
break;
default:
color = Color.GRAY;
break;
}
return color;
}
private boolean compressRow(int[] row)
{
int temp = 0;
int[] rowtemp = row.clone();
boolean isChanged = false;
for(int i = 0; i < row.length; i++)
{
for(int j = 0; j < row.length-i-1; j++)
{
if(row[j] == 0)
{
temp = row[j];
row[j] = row[j+1];
row[j+1] = temp;
}
}
}
if (!Arrays.equals(row,rowtemp))
{
isChanged = true;
}
return isChanged;
}
private boolean mergeRow(int[] row)
{
boolean moved = false;
for (int i=0; i< row.length-1;i++)
{
if ( (row[i] == row[i + 1]) && (row[i] != 0) )
{
row[i] = 2 * row[i];
row[i + 1] = 0;
moved = true;
}
}
return moved;
}
@Override
public void onKeyPress(Key key)
{
canUserMove();
if (canMove = false)
{
gameOver();
}
else
{
if ( key == Key.LEFT )
{
moveLeft();
drawScene();
}
else if ( key == Key.RIGHT )
{
moveRight();
drawScene();
}
else if ( key == Key.UP )
{
moveUp();
drawScene();
}
else if ( key == Key.DOWN )
{
moveDown();
drawScene();
}
}
}
private void moveLeft()
{
boolean compressed; // variable to get return from compressRow
boolean merged; // variable to get return from mergeRow
boolean compressed2; // variable to get return from second compressRow
int moved = 0; // to check if compressRow or mergeRow occurs
for (int i = 0; i < SIDE; i++)
{
compressed = compressRow(gameField[i]);
merged = mergeRow(gameField[i]);
compressed2=compressRow(gameField[i]);
if(compressed || merged || compressed2)
{
moved++;
}
}
if (moved != 0)
{
createNewNumber();
}
}
private void moveRight()
{
// In the moveRight() method, rotate the gameField matrix clockwise twice,
// then call moveLeft(), which we've already written,
// and again rotate the gameField clockwise two more times. It should work.
rotateClockwise();
rotateClockwise();
moveLeft();
rotateClockwise();
rotateClockwise();
}
private void moveUp()
{
// In the moveUp() method, we first rotate 90 degrees three times,
// and then call moveLeft() and rotate 90 degrees one more time.
rotateClockwise();
rotateClockwise();
rotateClockwise();
moveLeft();
rotateClockwise();
}
private void moveDown()
{
// In the moveDown() method, rotate 90 degrees once,
// then call moveLeft() and rotate 90 degrees another 3 times.
rotateClockwise();
moveLeft();
rotateClockwise();
rotateClockwise();
rotateClockwise();
}
private void rotateClockwise()
{
// Traverse each cycle
for (int i = 0; i < SIDE / 2; i++)
{
for (int j = i; j < SIDE - i - 1; j++)
{
// Swap elements of each cycle in clockwise direction
int temp = gameField[i][j];
gameField[i][j] = gameField[SIDE - 1 - j][i];
gameField[SIDE - 1 - j][i] = gameField[SIDE - 1 - i][SIDE - 1 - j];
gameField[SIDE - 1 - i][SIDE - 1 - j] = gameField[j][SIDE - 1 - i];
gameField[j][SIDE - 1 - i] = temp;
}
}
}
private int getMaxTileValue()
{
int max = gameField[0][0];
for (int[] row : gameField)
{
for (int value : row)
{
max = Math.max(max, value);
}
}
return max;
}
private void win()
{
isGameStopped = true;
showMessageDialog(Color.YELLOW, "YOU WIN!", Color.WHITE, 50);
}
private void gameOver()
{
isGameStopped = true;
showMessageDialog(Color.RED, "YOU LOST!", Color.WHITE, 50);
}
private boolean canUserMove()
{
canMove = false;
//comparison loop, checking for any duplicates when all spaces are taken.
for (int i = 0 ; i < SIDE; i++)
{
for (int j = 0; j < SIDE; j++)
{
if ( gameField[i][j] == 0 )
{
canMove = true;
break;
}
//this if statement checks if there is an above cell has it got the same value in it.
if ( (i - 1) > 0 && (gameField[i][j] == gameField[i - 1][j]) )
{
canMove = true;
break;
}
//this checks for DOWN
if ( (i + 1) < SIDE && (gameField[i][j] == gameField[i + 1][j]) )
{
canMove = true;
break;
}
//this checks for RIGHT
if ( (j + 1) < SIDE && (gameField[i][j] == gameField[i][j + 1]) )
{
canMove = true;
break;
}
//this checks for LEFT
if ( (j - 1) > 0 && (gameField[i][j] == gameField[i][j - 1]) )
{
canMove = true;
break;
}
}
if ( canMove = true )
{
break;
}
}
return canMove;
}
}