# 2048, 3 kleine Probleme



## Maverick2112 (8. Sep 2014)

Hallo liebes Forum,

ich habe mich hier angemeldet, da ich mit meinem Latein am Ende bin. Ich muss für die Uni das Spiel 2048 programmieren, nach bestimmten vorgaben. Habe es auch relativ weit hinbekommen, bei den letzten 3 Fehler weiß ich nur leider nicht weiter.
Im Anhang habe ich mal die Fehlermeldung sowie mein Code angehängt, evtl hat ja jemand von euch eine Idee was da falsch läuft.
Anhang anzeigen Coordinate2D.javaAnhang anzeigen Direction.javaAnhang anzeigen Move.javaAnhang anzeigen NumberGame.javaAnhang anzeigen Tile.javaAnhang anzeigen TileExistsException.java

Die Fehler müssten alle in der NumberGame stattfinden.

Vielen Dank schonmal für die Hilfe
Marcel


----------



## Maverick2112 (8. Sep 2014)

Der mittlere Fehler is raus. Ich hatte bei addRandomTile vergessen zu prüfen ob das Feld schon belegt ist.


----------



## strußi (8. Sep 2014)

also code wäre praktisch, damit wir mehr als nur fehlermeldungen haben


----------



## Maverick2112 (8. Sep 2014)

Dachte das geht die Java's zu öffnen!?

```
package jpp.numbergame;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * Die NumberGame-Klasse stellt eine Spielrunde von 2048 dar und beinhaltet die
 * Spiellogik. Sie speichert den aktuellen Zustand des Spielbretts und fuehrt
 * Zuege des Spielers darauf aus. Ausserdem verwaltet sie die Punktzahl des
 * Spielers.
 * 
 * @author Marcel
 * 
 */
public class NumberGame {
	private Tile gameBoard[][];
	private int width;
	private int height;
	private int gamePoints;

	/**
	 * Erstellt ein neues Spiel mit einem Spielfeld, welches width Felder breit
	 * und height Felder hoch ist. Alle Felder des Spieles sind zu Beginn leer.
	 * Die Punktzahl des Spielers ist auf 0 zu setzen. Ist width oder height
	 * kleiner als 1, wird eine IllegalArgumentException geworfen.
	 * 
	 * @param width
	 * @param height
	 */
	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;
	}

	/**
	 * Wie oben, platziert jedoch initialTiles zufaellige Teile (siehe
	 * addRandomTile-Methode unten). Ist initialTiles kleiner als 0 oder
	 * groesser als width * height, soll eine IllegalArgumentException geworfen
	 * werden.
	 * 
	 * @param width
	 * @param height
	 * @param initialTiles
	 */
	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();
		}
	}

	/**
	 * Liefert den Wert des Teils an der als Coordinate2D oder x- und y-Wert
	 * angegebenen Position des Spielfeldes, wobei die x-Achse nach rechts und
	 * die y-Achse nach unten zeigt (Dieses Koordinatensystem wird auch von
	 * JavaFX benutzt, dies erleichtert spaeter die Implementation der GUI).
	 * Befindet sich kein Teil auf dem angegebenen Feld, wird 0 zurueckgegeben.
	 * Liegt die Koordinate ausserhalb des Feldes, wird eine
	 * IndexOutOfBoundsException geworfen.
	 * 
	 * @param coord
	 * @return
	 */
	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();

	}

	/**
	 * Liefert den Wert des Teils an der als Coordinate2D oder x- und y-Wert
	 * angegebenen Position des Spielfeldes, wobei die x-Achse nach rechts und
	 * die y-Achse nach unten zeigt (Dieses Koordinatensystem wird auch von
	 * JavaFX benutzt, dies erleichtert spaeter die Implementation der GUI).
	 * Befindet sich kein Teil auf dem angegebenen Feld, wird 0 zurueckgegeben.
	 * Liegt die Koordinate ausserhalb des Feldes, wird eine
	 * IndexOutOfBoundsException geworfen.
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public int get(int x, int y) {
		if (gameBoard[x][y] == null) {
			return 0;
		}

		return gameBoard[x][y].getValue();
	}

	/**
	 * Gibt die aktuelle Punktzahl des Spielers zurueck.
	 * 
	 * @return
	 */
	public int getPoints() {
		return gamePoints;
	}

	/**
	 * Gibt true zurueck, wenn alle Felder des Spielbretts mit einem Teil belegt
	 * sind.
	 * 
	 * @return true
	 */
	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;
	}

	/**
	 * Fuegt ein neues Teil an einer zufaelligen freien Position des Spielfelds
	 * ein (benutzen Sie java.util.Random). Der Wert des neuen Teils wird mit
	 * einer Chance von ca. 10% auf 4 gesetzt, ansonsten auf 2.
	 * 
	 * @return
	 */
	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);
	}

	/**
	 * Fuegt ein neues Teil an der angegebenen Position des Spielfelds mit dem
	 * Wert value ein. Ist das angegebene Feld bereits belegt, wird eine
	 * TileExistsException geworfen.
	 * 
	 * @param x
	 *            X-Koordinate
	 * @param y
	 *            Y-Koordinate
	 * @param value
	 *            Wert der Position
	 * @return field
	 */
	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;
	}


	/**
	 * Fuehrt einen Spielerzug aus. Alle Teile werden entsprechend der oben
	 * beschriebenen Regeln in die uebergebene Richtung bewegt.
	 * 
	 * @param dir
	 * @return
	 */
	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;

	}

	/**
	 * Gibt true zurueck, wenn eine Bewegung in die angegebene Richtung moeglich
	 * ist, d.h. es wuerde mindestens ein Teil dadurch bewegt.
	 * 
	 * @param dir
	 * @return true
	 */
	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;
	}

	/**
	 * Gibt true zurueck, wenn eine Bewegung in mindestens eine der vier
	 * Richtungen moeglich ist. Anderenfalls hat der Spieler verloren.
	 * 
	 * @return true
	 */
	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();

		}
	}
}
```


----------



## JavaMeister (8. Sep 2014)

500 Zeilen Code um die Anforderungen, die wir nicht kennen, von einem UnitTest herauszufinden?

Viel spaß ^^


----------

