PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/SS2015/RecursiveBacktracker.java

https://gitlab.com/without-trust/tubsassign
Java | 345 lines | 244 code | 48 blank | 53 comment | 104 complexity | 4b06dbd65db0aa9116a06227c12dd5d6 MD5 | raw file
Possible License(s): GPL-2.0
  1. /**
  2. * Dies ist die aktuelle Pflichtaufgabe.
  3. * Diese Datei beinhaltet die RecursiveBacktracker-Klasse
  4. *
  5. * @author Eva Vanessa Bolle 4528650 Gruppe 2a
  6. * @author Steffen Richter 4388227 Gruppe 2a
  7. * @author Philipp 4569839 Gruppe 5b
  8. */
  9. class RecursiveBacktracker implements MazeGenerator {
  10. /**
  11. * the map
  12. */
  13. private char[][] map;
  14. /**
  15. * Konstruktor
  16. * @param height Hoehe der Karte
  17. * @param width Breite der Karte
  18. */
  19. public RecursiveBacktracker(int height, int width) {
  20. this.map = this.generate(height, width);
  21. }
  22. /** @return mapdata */
  23. public char[][] getMap() {
  24. return this.map;
  25. }
  26. /**
  27. * generate-Methode, generiert die Map
  28. *
  29. * @param height Hoehe der Karte
  30. * @param width Breite der Karte
  31. * @return Die fertige Map
  32. */
  33. public char[][] generate(int height, int width) {
  34. if (height * width % 2 != 1) {
  35. throw new IllegalArgumentException("Height and width of map must be odd.");
  36. } // end of if
  37. if (height < 5 || width < 5) {
  38. throw new IllegalArgumentException("Map must be at least 5x5 in size.");
  39. } // end of if
  40. char[][] map = new char[height][width];
  41. for (int i = 0; i < height; i++) {
  42. for (int j = 0; j < width; j++) {
  43. if (i % 2 == 0) {
  44. map [i][j] = WALL;
  45. } else if (j % 2 == 0) {
  46. map [i][j] = WALL;
  47. } else {
  48. map [i][j] = ' ';
  49. }
  50. }
  51. } // Jetzt ist die Map ein Gitter
  52. int x = (int) ((width - 3) / 2 * Math.random()) * 2 + 1;
  53. int y = (int) ((height - 3) / 2 * Math.random()) * 2 + 1;
  54. this.rekursion(map, x, y);
  55. map[x][y] = 'S';
  56. map = this.createShop(map);
  57. map = this.createGoal(map);
  58. map = this.createQ(map);
  59. return map;
  60. }
  61. /**
  62. * rekusion-Methode, generiert das Labyrinth
  63. * @param map Die unfertige Karte
  64. * @param x Aktuelle x-Position auf der Karte
  65. * @param y Aktuelle y-Position auf der Karte
  66. */
  67. private void rekursion(char[][] map, int x, int y) {
  68. map [x][y] = '.'; //Aktuelles Feld als besucht markieren
  69. //solange es noch unbesuchte Nachbarn gibt
  70. int ndir = 0;
  71. char [] dir = {0, 0, 0, 0};
  72. if ((x > 1) && (map[x - 2][y] == ' ')) {
  73. dir[ndir] = 'w';
  74. ndir++;
  75. }
  76. if ((y > 1) && (map[x][y - 2] == ' ')) {
  77. dir[ndir] = 'n';
  78. ndir++;
  79. }
  80. if ((x < map.length - 2) && (map[x + 2][y] == ' ')) {
  81. dir[ndir] = 'e';
  82. ndir++;
  83. }
  84. if ((y < map[0].length - 2) && (map[x][y + 2] == ' ')) {
  85. dir[ndir] = 's';
  86. ndir++;
  87. }
  88. while (ndir > 0) {
  89. //naechste Position setzen
  90. int r = (int) (Math.random() * ndir);
  91. int xneu = 0, yneu = 0;
  92. switch (dir[r]) {
  93. case 'n':
  94. xneu = x;
  95. yneu = y - 2;
  96. break;
  97. case 'e':
  98. xneu = x + 2;
  99. yneu = y;
  100. break;
  101. case 's':
  102. xneu = x;
  103. yneu = y + 2;
  104. break;
  105. case 'w':
  106. xneu = x - 2;
  107. yneu = y;
  108. break;
  109. default:
  110. }
  111. //Mauer dahin entfernen
  112. map [x - (x - xneu) / 2][y - (y - yneu) / 2] = '.';
  113. this.rekursion(map, xneu, yneu);
  114. //ndir und dir neu bestimmen
  115. ndir = 0;
  116. for (int i = 0; i < 4; i++) {
  117. dir[i] = 0;
  118. } // end of for
  119. if ((x > 1) && (map[x - 2][y] == ' ')) {
  120. dir[ndir] = 'w';
  121. ndir++;
  122. }
  123. if ((y > 1) && (map[x][y - 2] == ' ')) {
  124. dir[ndir] = 'n';
  125. ndir++;
  126. }
  127. if ((x < map.length - 2) && (map[x + 2][y] == ' ')) {
  128. dir[ndir] = 'e';
  129. ndir++;
  130. }
  131. if ((y < map[0].length - 2) && (map[x][y + 2] == ' ')) {
  132. dir[ndir] = 's';
  133. ndir++;
  134. }
  135. } //end of while
  136. double r = Math.random();
  137. int i = 0; //Anzahl verbundene Felder zaehlen:
  138. if (map[x - 1][y] == '.') {
  139. i++;
  140. }
  141. if (map[x + 1][y] == '.') {
  142. i++;
  143. }
  144. if (map[x][y - 1] == '.') {
  145. i++;
  146. }
  147. if (map[x][y + 1] == '.') {
  148. i++;
  149. }
  150. switch (i) {
  151. case 1: //Sackgasse: 0.5 Brunnen, 0.3 Schmied, 0.2 nix
  152. if (r <= 0.5) {
  153. map[x][y] = WELL;
  154. } else if (r <= 0.8) {
  155. map[x][y] = SMITHY;
  156. }
  157. break;
  158. case 2: //Strasse: 0.1 Schmied, 0.15 Brunnen, 0.25 Kampf, 0.4 nix
  159. if (r <= 0.15) {
  160. map[x][y] = WELL;
  161. } else if (r <= 0.25) {
  162. map[x][y] = SMITHY;
  163. } else if (r <= 0.5) {
  164. map[x][y] = BATTLE;
  165. }
  166. break;
  167. case 3: //Abzweigung: 0.05 Schmied, 0.15 Brunnen, 0.5 Kampf, 0.3 nix
  168. if (r <= 0.15) {
  169. map[x][y] = WELL;
  170. } else if (r <= 0.2) {
  171. map[x][y] = SMITHY;
  172. } else if (r <= 0.7) {
  173. map[x][y] = BATTLE;
  174. }
  175. break;
  176. case 4: //Kreuzung: 0.6 Kampf, 0.3 nix
  177. if (r <= 0.6) {
  178. map[x][y] = BATTLE;
  179. }
  180. break;
  181. default:
  182. }
  183. }
  184. /**
  185. * Shop-Methode, definiert mindestens drei Shops
  186. * @param map Karte
  187. * @return Karte mit Shops
  188. *
  189. */
  190. private char[][] createShop(char [][] map) {
  191. int n = (int) ((map[0].length * map.length) / 30.0); //Anzahl Shops, abhängig vom Größe der Map
  192. n = (n < 3) ? 3 : n;
  193. int i = 0;
  194. while (i < n) {
  195. int x = (int) (Math.random() * (map.length / 2)) * 2 + 1;
  196. int y = (int) (Math.random() * (map[0].length / 2)) * 2 + 1;
  197. if ((map[x][y] != 'H') && (map[x][y] != 'S')) {
  198. map[x][y] = 'H';
  199. i++;
  200. }
  201. }
  202. return map;
  203. }
  204. /**
  205. * Ziel-Methode, legt das Zielfeld fest
  206. *
  207. * @param map Karte
  208. * @return die Karte mit Zielfeld
  209. */
  210. private char[][] createGoal(char [][] map) {
  211. char [][] walkmap = new char[map.length][map[0].length];
  212. int x = 0;
  213. int y = 0;
  214. for (int i = 0; i < walkmap.length; i++) {
  215. for (int j = 0; j < walkmap[0].length; j++) {
  216. walkmap[i][j] = map[i][j];
  217. if (map[i][j] == 'S') {
  218. x = i;
  219. y = j;
  220. }
  221. }
  222. }
  223. boolean keinZielfeld = true;
  224. while (keinZielfeld) {
  225. //Bewegungsmoeglichkeiten zaehlen
  226. int ndir = 0;
  227. char [] dir = {0, 0, 0, 0};
  228. if ((walkmap[x - 1][y] != WALL) && (walkmap[x - 1][y] != 'x')) {
  229. dir[ndir] = 'w';
  230. ndir++; //Bewegung Richtung Westen pruefen
  231. }
  232. if ((walkmap[x][y - 1] != WALL) && (walkmap[x][y - 1] != 'x')) {
  233. dir[ndir] = 'n';
  234. ndir++; //Bewegung Richtung Norden pruefen
  235. }
  236. if ((walkmap[x + 1][y] != WALL) && (walkmap[x + 1][y] != 'x')) {
  237. dir[ndir] = 'e';
  238. ndir++; //Bewegung Richtung Osten pruefen
  239. }
  240. if ((walkmap[x][y + 1] != WALL) && (walkmap[x][y + 1] != 'x')) {
  241. dir[ndir] = 's';
  242. ndir++; //Bewegung Richtung Sueden pruefen
  243. }
  244. //Bei > 0: aktuelle Position mit 'x' markieren, eine Richtung auswaehlen und gehen
  245. if (ndir > 0) {
  246. walkmap[x][y] = 'x';
  247. int r = (int) (Math.random() * ndir);
  248. switch (dir[r]) {
  249. case 'n': //Bewegung Richtung Norden
  250. y = y - 1;
  251. break;
  252. case 'e': //Bewegung Richtung Osten
  253. x = x + 1;
  254. break;
  255. case 's': //Bewegung Richtung Sueden
  256. y = y + 1;
  257. break;
  258. case 'w': //Bewegung Richtung Westen
  259. x = x - 1;
  260. break;
  261. default:
  262. }
  263. } else { //Bei == 0: aktuelle Position in map[][] auf 'Z' setzten, boolean keinZielfeld auf false setzen
  264. map [x][y] = 'Z';
  265. keinZielfeld = false;
  266. }
  267. }
  268. return map;
  269. }
  270. /**
  271. * creating a questbuddy on the map near the start
  272. * @param map the map
  273. * @return the map
  274. */
  275. private char[][] createQ(char[][] map) {
  276. int x = 0;
  277. int y = 0;
  278. for (int i = 0; i < map.length; i++) {
  279. for (int j = 0; j < map[0].length; j++) {
  280. if (map[i][j] == 'S') {
  281. x = i;
  282. y = j;
  283. }
  284. }
  285. }
  286. if (map[x][y - 1] != '#') {
  287. map[x][y - 2] = 'Q';
  288. } else if (map[x][y + 1] != '#') {
  289. map[x][y + 2] = 'Q';
  290. } else if (map[x - 1][y] != '#') {
  291. map[x - 2][y] = 'Q';
  292. } else {
  293. map[x + 2][y] = 'Q';
  294. }
  295. return map;
  296. }
  297. }