package com.webnobis.labyrinth.elements;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
/**
*
* Title: RandomLabyrinth<br>
* Description: Zufälliges Labyrinth<br>
* Copyright: Copyright (c) 2006<br>
* <br>
*
* @author Steffen<br>
* @version 1.00 (21.02.2006)<br>
*/
public class RandomLabyrinth extends AbstractLabyrinth {
private Random r;
private Segment[] segmentArray;
private int minWayPosition;
private RelativePosition relativePosition;
/**
* Konstruktor, der die Maße erwartet.<br>
* Erstellt wird ein zufällig generiertes Labyrinth mit mindestens einem Lösungsweg.<br>
*
* @param width
* Breite
* @param height
* Höhe
*/
public RandomLabyrinth(int width, int height) {
super(width, height);
this.r = new Random();
this.minWayPosition = ((width * height) - ((width * 2) + (height * 2))) / 2;
this.init();
}
// Initialisierung
private void init() {
this.segmentArray = new Segment[super.getWidth() * super.getHeight()];
Position entry;
Position target;
switch (r.nextInt(4)) {
case 0:
entry = new Position(0, r.nextInt(super.getHeight() - 2) + 1);
target = new Position(super.getWidth() - 1, r.nextInt(super.getHeight() - 2) + 1);
break;
case 1:
entry = new Position(super.getWidth() - 1, r.nextInt(super.getHeight() - 2) + 1);
target = new Position(0, r.nextInt(super.getHeight() - 2) + 1);
break;
case 2:
entry = new Position(r.nextInt(super.getWidth() - 2) + 1, 0);
target = new Position(r.nextInt(super.getWidth() - 2) + 1, super.getHeight() - 1);
break;
default:
entry = new Position(r.nextInt(super.getWidth() - 2) + 1, super.getHeight() - 1);
target = new Position(r.nextInt(super.getWidth() - 2) + 1, 0);
}
this.relativePosition = new RelativePosition(target, super.getWidth(), super.getHeight());
this.addSolutionWay(new ArrayList(super.getWidth() * super.getHeight()), entry, target);
}
// Lösungsweg hinzufügen
private void addSolutionWay(List list, Position entry, Position target) {
boolean isWay;
WayFinder wf;
Position position;
int i, count;
do {
// Startposition einnehmen
count = 0;
list.clear();
Arrays.fill(segmentArray, Segment.WALL); // count < minWayPosition
position = entry;
// Weg erstellen
for (i = 0; i < (super.getWidth() * super.getHeight() * 10); i++) {
isWay = false;
position = this.nextPosition(list, position);
if (position == null || (count < minWayPosition && position.equals(target))) {
position = (Position) list.remove(r.nextInt(list.size()));
isWay = this.canSet(position);
} else {
isWay = true;
}
if (isWay) {
if (position.equals(target)) {
break;
}
count++;
segmentArray[PositionTranslator.toPosition(position.getX(), position.getY(), super.getWidth())] = Segment.WAY;
}
}
segmentArray[PositionTranslator.toPosition(entry.getX(), entry.getY(), super.getWidth())] = Segment.ENTRY;
segmentArray[PositionTranslator.toPosition(target.getX(), target.getY(), super.getWidth())] = Segment.TARGET;
wf = new WayFinder(this);
} while (!wf.hasWay() || (count < minWayPosition));
}
// liefert die nächste zufällig gefundene erlaubte Position
private Position nextPosition(List listWay, Position position) {
Position nextPosition;
List list = relativePosition.getPositionList(position);
listWay.addAll(list);
while (!list.isEmpty()) {
nextPosition = (Position) list.remove(r.nextInt(list.size()));
if (this.canSet(nextPosition)) {
return nextPosition;
}
}
return null;
}
// true, wenn mögliche Position
private boolean canSet(Position position) {
int wayCount = 0;
int pos;
Position nextPosition;
Iterator it = relativePosition.getPositionList(position).iterator();
while (it.hasNext()) {
nextPosition = (Position) it.next();
pos = PositionTranslator.toPosition(nextPosition.getX(), nextPosition.getY(), super.getWidth());
if (!Segment.WALL.equals(segmentArray[pos])) {
wayCount++;
}
}
return (wayCount < 2); // Anzahl bereits vorhandener Weg-Positionen prüfen
}
/**
*
* @see com.webnobis.labyrinth.elements.Labyrinth#getSegmentArray()
*/
public Segment[] getSegmentArray() {
return segmentArray;
}
}