package jpp.numbergame;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
public class NumberGame {
private Tile gameBoard[][];
private int width;
private int height;
private int gamePoints;
public NumberGame(int width, int height) {
if (width < 1 || height < 1) {
throw new IllegalArgumentException("Das Feld ist zu klein");
}
gameBoard = new Tile[width][height];
this.width = width;
this.height = height;
gamePoints = 0;
}
public NumberGame(int width, int height, int initialTiles) {
this(width, height);
if (initialTiles < 0 || initialTiles > width * height) {
throw new IllegalArgumentException("Fehler");
}
for (int i = 0; i < initialTiles; i++) {
this.addRandomTile();
}
}
public int get(Coordinate2D coord) {
if (coord.getX() >= this.width || coord.getY() >= this.height
|| coord.getX() < 0 || coord.getY() < 0) {
throw new IndexOutOfBoundsException("Nicht auf dem Spielfeld");
}
int x = coord.getX();
int y = coord.getY();
if (gameBoard[x][y] == null) {
return 0;
}
return gameBoard[x][y].getValue();
}
public int get(int x, int y) {
if (gameBoard[x][y] == null) {
return 0;
}
return gameBoard[x][y].getValue();
}
public int getPoints() {
return gamePoints;
}
public boolean isFull() {
for (int i = 0; i < gameBoard.length; i++) {
for (int e = 0; e < gameBoard[i].length; e++) {
if (gameBoard[e][i] == null) {
return false;
}
}
}
return true;
}
public Tile addRandomTile() {
Random rnd = new Random();
int posX = rnd.nextInt(this.width);
int posY = rnd.nextInt(this.height);
int newValue = 0;
float chance = rnd.nextFloat();
if (chance <= 0.10f) {
newValue = 4;
} else {
newValue = 2;
}
while(get(posX,posY) != 0)
{
posX = rnd.nextInt(this.width);
posY = rnd.nextInt(this.height);
}
gameBoard[posX][posY] = new Tile(new Coordinate2D(posX, posY), newValue);
return new Tile(new Coordinate2D(posX, posY), newValue);
}
public Tile addTile(int x, int y, int value) {
int fieldValue = get(x, y);
if (fieldValue != 0) {
throw new TileExistsException("Feld bereits belegt!");
}
Tile field = new Tile(new Coordinate2D(x,y), value) ;
gameBoard[x][y] = field ;
return field;
}
public List<Move> move(Direction dir) {
int xB = 0;
LinkedList<Move> list = new LinkedList<Move>();
if (dir == Direction.UP) {
for (int t = 0; t < 2; t++) {
for (int i = 0; i < gameBoard.length; i++) {
for (int e = 0; e < gameBoard[i].length; e++) {
if (gameBoard[e][i] == null) {
for (int r = e; r < gameBoard.length; r++) {
if (gameBoard[r][i] != null) {
gameBoard[e][i] = new Tile(
new Coordinate2D(e, i), get(r, i));
list.add(new Move(new Coordinate2D(e + xB,
i), new Coordinate2D(e, i), get(r,
i), get(r, i)));
gameBoard[r][i] = null;
xB = r - e;
break;
}
}
}
if (e > 0 && t == 0) {
if (get(e - 1, i) == get(e, i) && get(e, i) > 0) {
list.add(new Move(new Coordinate2D(e + xB, i),
new Coordinate2D(e - 1, i), get(e - 1,
i), get(e - 1, i) * 2));
gamePoints += get(e - 1, i) * 2;
gameBoard[e - 1][i] = new Tile(
new Coordinate2D(e - 1, i), get(e - 1,
i) * 2);
gameBoard[e][i] = null;
}
}
}
}
}
} else if (dir == Direction.LEFT) {
for (int t = 0; t < 2; t++) {
for (int i = 0; i < gameBoard.length; i++) {
for (int e = 0; e < gameBoard[i].length; e++) {
if (gameBoard[i][e] == null) {
for (int r = e; r < gameBoard.length; r++) {
if (gameBoard[i][r] != null) {
gameBoard[i][e] = new Tile(
new Coordinate2D(i, e), get(i, r));
System.out.print(get(i, r));
list.add(new Move(new Coordinate2D(i, e
+ xB), new Coordinate2D(i, e), get(
i, r), get(i, r)));
gameBoard[i][r] = null;
xB = r - e;
break;
}
}
}
if (e > 0 && t == 0) {
if (get(i, e - 1) > 0 && get(i, e - 1) == get(i, e)) {
list.add(new Move(new Coordinate2D(i, e),
new Coordinate2D(i, e - 1), get(i, e),
get(i, e - 1) * 2));
gamePoints += get(i, e - 1) * 2;
gameBoard[i][e - 1] = new Tile(
new Coordinate2D(i, e - 1), get(i,
e - 1) * 2);
gameBoard[i][e] = null;
}
}
}
}
}
} else if (dir == Direction.DOWN) {
for (int t = 0; t < 2; t++) {
for (int i = gameBoard.length - 1; i >= 0; i--) {
for (int e = gameBoard[i].length - 1; e >= 0; e--) {
if (gameBoard[e][i] == null) {
for (int r = e; r >= 0; r--) {
if (gameBoard[r][i] != null) {
gameBoard[e][i] = new Tile(
new Coordinate2D(e, i), get(r, i));
list.add(new Move(new Coordinate2D(e, i),
new Coordinate2D(e + 1, i), get(r,
i), get(r, i)));
gameBoard[r][i] = null;
xB = r - e;
break;
}
}
}
if (e < gameBoard.length - 1 && t == 0) {
if (get(e + 1, i) == get(e, i) && get(e, i) > 0) {
list.add(new Move(new Coordinate2D(e - xB, i),
new Coordinate2D(e + 1, i), get(e + 1,
i), get(e + 1, i) * 2));
gamePoints += get(e + 1, i) * 2;
gameBoard[e + 1][i] = new Tile(
new Coordinate2D(e + 1, i), get(e + 1,
i) * 2);
gameBoard[e][i] = null;
}
}
}
}
}
} else if (dir == Direction.RIGHT) {
for (int t = 0; t < 2; t++) {
for (int i = gameBoard.length - 1; i >= 0; i--) {
for (int e = gameBoard[i].length - 1; e >= 0; e--) {
if (gameBoard[i][e] == null) {
for (int r = e; r >= 0; r--) {
if (gameBoard[i][r] != null) {
gameBoard[i][e] = new Tile(
new Coordinate2D(i, e), get(i, r));
list.add(new Move(new Coordinate2D(i, e),
new Coordinate2D(i, e + 1), get(i,
r), get(i, r)));
gameBoard[i][r] = null;
xB = r - e;
break;
}
}
}
if (e < gameBoard.length - 1 && t == 0) {
if (get(i, e + 1) > 0 && get(i, e + 1) == get(i, e)) {
list.add(new Move(new Coordinate2D(i, e - xB),
new Coordinate2D(i, e + 1), get(i, e),
get(i, e + 1) * 2));
gamePoints += get(i, e + 1) * 2;
gameBoard[i][e + 1] = new Tile(
new Coordinate2D(i, e + 1), get(i,
e + 1) * 2);
gameBoard[i][e] = null;
}
}
}
}
}
}
return list;
}
public boolean canMove(Direction dir) {
if (dir == Direction.UP) {
for (int i = 0; i < gameBoard.length; i++) {
for (int e = 1; e < gameBoard[i].length; e++) {
if (gameBoard[e][i] != null && gameBoard[e - 1][i] == null) {
return true;
}
}
}
} else if (dir == Direction.RIGHT) {
for (int i = gameBoard.length - 1; i >= 0; i--) {
for (int e = gameBoard[i].length - 2; e >= 0; e--) {
if (gameBoard[i][e] != null && gameBoard[i][e + 1] == null) {
return true;
}
}
}
} else if (dir == Direction.DOWN) {
for (int i = gameBoard.length - 1; i >= 0; i--) {
for (int e = gameBoard[i].length - 2; e >= 0; e--) {
if (gameBoard[e][i] != null && gameBoard[e + 1][i] == null) {
return true;
}
}
}
}
else if (dir == Direction.LEFT) {
for (int i = 0; i < gameBoard.length; i++) {
for (int e = 1; e < gameBoard[i].length; e++) {
if (gameBoard[i][e] != null && gameBoard[i][e - 1] == null) {
return true;
}
}
}
}
return false;
}
public boolean canMove() {
if (canMove(Direction.DOWN)) {
return true;
}
if (canMove(Direction.UP)) {
return true;
}
if (canMove(Direction.LEFT)) {
return true;
}
if (canMove(Direction.RIGHT)) {
return true;
}
return false;
}
public void printField() {
for (int i = 0; i < gameBoard.length; i++) {
for (int e = 0; e < gameBoard[i].length; e++) {
if (gameBoard[i][e] == null) {
System.out.print("0 ");
} else {
System.out.print(gameBoard[i][e].getValue() + " ");
}
}
System.out.println();
}
}
}