/SS2015/RecursiveBacktracker.java
Java | 345 lines | 244 code | 48 blank | 53 comment | 104 complexity | 4b06dbd65db0aa9116a06227c12dd5d6 MD5 | raw file
Possible License(s): GPL-2.0
- /**
- * Dies ist die aktuelle Pflichtaufgabe.
- * Diese Datei beinhaltet die RecursiveBacktracker-Klasse
- *
- * @author Eva Vanessa Bolle 4528650 Gruppe 2a
- * @author Steffen Richter 4388227 Gruppe 2a
- * @author Philipp 4569839 Gruppe 5b
- */
- class RecursiveBacktracker implements MazeGenerator {
- /**
- * the map
- */
- private char[][] map;
- /**
- * Konstruktor
- * @param height Hoehe der Karte
- * @param width Breite der Karte
- */
- public RecursiveBacktracker(int height, int width) {
- this.map = this.generate(height, width);
- }
-
- /** @return mapdata */
- public char[][] getMap() {
- return this.map;
- }
- /**
- * generate-Methode, generiert die Map
- *
- * @param height Hoehe der Karte
- * @param width Breite der Karte
- * @return Die fertige Map
- */
- public char[][] generate(int height, int width) {
- if (height * width % 2 != 1) {
- throw new IllegalArgumentException("Height and width of map must be odd.");
- } // end of if
- if (height < 5 || width < 5) {
- throw new IllegalArgumentException("Map must be at least 5x5 in size.");
- } // end of if
- char[][] map = new char[height][width];
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++) {
- if (i % 2 == 0) {
- map [i][j] = WALL;
- } else if (j % 2 == 0) {
- map [i][j] = WALL;
- } else {
- map [i][j] = ' ';
- }
- }
- } // Jetzt ist die Map ein Gitter
-
- int x = (int) ((width - 3) / 2 * Math.random()) * 2 + 1;
- int y = (int) ((height - 3) / 2 * Math.random()) * 2 + 1;
-
- this.rekursion(map, x, y);
- map[x][y] = 'S';
- map = this.createShop(map);
- map = this.createGoal(map);
- map = this.createQ(map);
- return map;
- }
-
- /**
- * rekusion-Methode, generiert das Labyrinth
- * @param map Die unfertige Karte
- * @param x Aktuelle x-Position auf der Karte
- * @param y Aktuelle y-Position auf der Karte
- */
- private void rekursion(char[][] map, int x, int y) {
- map [x][y] = '.'; //Aktuelles Feld als besucht markieren
-
- //solange es noch unbesuchte Nachbarn gibt
- int ndir = 0;
- char [] dir = {0, 0, 0, 0};
- if ((x > 1) && (map[x - 2][y] == ' ')) {
- dir[ndir] = 'w';
- ndir++;
- }
-
- if ((y > 1) && (map[x][y - 2] == ' ')) {
- dir[ndir] = 'n';
- ndir++;
- }
-
- if ((x < map.length - 2) && (map[x + 2][y] == ' ')) {
- dir[ndir] = 'e';
- ndir++;
- }
-
- if ((y < map[0].length - 2) && (map[x][y + 2] == ' ')) {
- dir[ndir] = 's';
- ndir++;
- }
-
-
- while (ndir > 0) {
-
- //naechste Position setzen
- int r = (int) (Math.random() * ndir);
-
- int xneu = 0, yneu = 0;
-
- switch (dir[r]) {
- case 'n':
- xneu = x;
- yneu = y - 2;
- break;
-
- case 'e':
- xneu = x + 2;
- yneu = y;
- break;
-
- case 's':
- xneu = x;
- yneu = y + 2;
- break;
-
- case 'w':
- xneu = x - 2;
- yneu = y;
- break;
- default:
- }
-
- //Mauer dahin entfernen
- map [x - (x - xneu) / 2][y - (y - yneu) / 2] = '.';
-
- this.rekursion(map, xneu, yneu);
-
- //ndir und dir neu bestimmen
- ndir = 0;
- for (int i = 0; i < 4; i++) {
- dir[i] = 0;
-
- } // end of for
- if ((x > 1) && (map[x - 2][y] == ' ')) {
- dir[ndir] = 'w';
- ndir++;
- }
-
- if ((y > 1) && (map[x][y - 2] == ' ')) {
- dir[ndir] = 'n';
- ndir++;
- }
-
- if ((x < map.length - 2) && (map[x + 2][y] == ' ')) {
- dir[ndir] = 'e';
- ndir++;
- }
-
- if ((y < map[0].length - 2) && (map[x][y + 2] == ' ')) {
- dir[ndir] = 's';
- ndir++;
- }
- } //end of while
-
- double r = Math.random();
-
- int i = 0; //Anzahl verbundene Felder zaehlen:
- if (map[x - 1][y] == '.') {
- i++;
- }
-
- if (map[x + 1][y] == '.') {
- i++;
- }
-
- if (map[x][y - 1] == '.') {
- i++;
- }
-
- if (map[x][y + 1] == '.') {
- i++;
- }
-
- switch (i) {
- case 1: //Sackgasse: 0.5 Brunnen, 0.3 Schmied, 0.2 nix
- if (r <= 0.5) {
- map[x][y] = WELL;
- } else if (r <= 0.8) {
- map[x][y] = SMITHY;
- }
- break;
-
- case 2: //Strasse: 0.1 Schmied, 0.15 Brunnen, 0.25 Kampf, 0.4 nix
- if (r <= 0.15) {
- map[x][y] = WELL;
- } else if (r <= 0.25) {
- map[x][y] = SMITHY;
- } else if (r <= 0.5) {
- map[x][y] = BATTLE;
- }
- break;
-
- case 3: //Abzweigung: 0.05 Schmied, 0.15 Brunnen, 0.5 Kampf, 0.3 nix
- if (r <= 0.15) {
- map[x][y] = WELL;
- } else if (r <= 0.2) {
- map[x][y] = SMITHY;
- } else if (r <= 0.7) {
- map[x][y] = BATTLE;
- }
- break;
-
- case 4: //Kreuzung: 0.6 Kampf, 0.3 nix
- if (r <= 0.6) {
- map[x][y] = BATTLE;
- }
- break;
- default:
- }
-
- }
- /**
- * Shop-Methode, definiert mindestens drei Shops
- * @param map Karte
- * @return Karte mit Shops
- *
- */
- private char[][] createShop(char [][] map) {
- int n = (int) ((map[0].length * map.length) / 30.0); //Anzahl Shops, abhängig vom Größe der Map
- n = (n < 3) ? 3 : n;
- int i = 0;
- while (i < n) {
- int x = (int) (Math.random() * (map.length / 2)) * 2 + 1;
- int y = (int) (Math.random() * (map[0].length / 2)) * 2 + 1;
- if ((map[x][y] != 'H') && (map[x][y] != 'S')) {
- map[x][y] = 'H';
- i++;
- }
- }
- return map;
- }
-
- /**
- * Ziel-Methode, legt das Zielfeld fest
- *
- * @param map Karte
- * @return die Karte mit Zielfeld
- */
- private char[][] createGoal(char [][] map) {
- char [][] walkmap = new char[map.length][map[0].length];
- int x = 0;
- int y = 0;
- for (int i = 0; i < walkmap.length; i++) {
- for (int j = 0; j < walkmap[0].length; j++) {
- walkmap[i][j] = map[i][j];
- if (map[i][j] == 'S') {
- x = i;
- y = j;
- }
- }
- }
-
- boolean keinZielfeld = true;
- while (keinZielfeld) {
- //Bewegungsmoeglichkeiten zaehlen
- int ndir = 0;
- char [] dir = {0, 0, 0, 0};
- if ((walkmap[x - 1][y] != WALL) && (walkmap[x - 1][y] != 'x')) {
- dir[ndir] = 'w';
- ndir++; //Bewegung Richtung Westen pruefen
- }
-
- if ((walkmap[x][y - 1] != WALL) && (walkmap[x][y - 1] != 'x')) {
- dir[ndir] = 'n';
- ndir++; //Bewegung Richtung Norden pruefen
- }
-
- if ((walkmap[x + 1][y] != WALL) && (walkmap[x + 1][y] != 'x')) {
- dir[ndir] = 'e';
- ndir++; //Bewegung Richtung Osten pruefen
- }
-
- if ((walkmap[x][y + 1] != WALL) && (walkmap[x][y + 1] != 'x')) {
- dir[ndir] = 's';
- ndir++; //Bewegung Richtung Sueden pruefen
- }
- //Bei > 0: aktuelle Position mit 'x' markieren, eine Richtung auswaehlen und gehen
- if (ndir > 0) {
- walkmap[x][y] = 'x';
- int r = (int) (Math.random() * ndir);
- switch (dir[r]) {
- case 'n': //Bewegung Richtung Norden
- y = y - 1;
- break;
-
- case 'e': //Bewegung Richtung Osten
- x = x + 1;
- break;
-
- case 's': //Bewegung Richtung Sueden
- y = y + 1;
- break;
-
- case 'w': //Bewegung Richtung Westen
- x = x - 1;
- break;
- default:
- }
- } else { //Bei == 0: aktuelle Position in map[][] auf 'Z' setzten, boolean keinZielfeld auf false setzen
- map [x][y] = 'Z';
- keinZielfeld = false;
- }
- }
- return map;
- }
- /**
- * creating a questbuddy on the map near the start
- * @param map the map
- * @return the map
- */
- private char[][] createQ(char[][] map) {
- int x = 0;
- int y = 0;
- for (int i = 0; i < map.length; i++) {
- for (int j = 0; j < map[0].length; j++) {
- if (map[i][j] == 'S') {
- x = i;
- y = j;
- }
- }
- }
- if (map[x][y - 1] != '#') {
- map[x][y - 2] = 'Q';
- } else if (map[x][y + 1] != '#') {
- map[x][y + 2] = 'Q';
- } else if (map[x - 1][y] != '#') {
- map[x - 2][y] = 'Q';
- } else {
- map[x + 2][y] = 'Q';
- }
- return map;
- }
- }