import java.util.Random;
import java.awt.Graphics2D;
import java.awt.Color;

/**
 * Eine Klasse für die Daten eines Labyrinths
 * @author Ralph Matthes
 * @version 1.0
 */
public class Labyrinth{

    static final int FREI = 1;
    static final int BELEGT = 2;
    static final int BESUCHT = 3;
    private int breite, hoehe;
    private int[][] kaestchen;

    /**
     * erzeugt quadratisches Labyrinth
     * @param seitenlaenge Gesamtzahl der Kästchen horizontal und vertikal
     */
    public Labyrinth(int seitenlaenge) {

	this(seitenlaenge, seitenlaenge);
    }

    /**
     * erzeugt rechteckiges Labyrinth
     * @param breite Gesamtzahl der Kästchen horizontal (inkl. Ränder)
     * @param hoehe Gesamtzahl der Kästchen vertikal (inkl. Ränder)
     */
    public Labyrinth(int breite, int hoehe) {
	
	this.breite = breite;
	this.hoehe = hoehe;
	kaestchen = new int[breite][hoehe];
    }

    /**
     * Abmessung des Labyrinths
     * @return die horizontale Kästchenzahl
     */
    public int getBreite() {

	return breite;
    }

    /**
     * Abmessung des Labyrinths
     * @return die vertikale Kästchenzahl
     */
    public int getHoehe() {

	return hoehe;
    }

    /**
     * erzeugt zufällige Belegung
     */
    public void initialisiere(){
	Random generator = new Random();

	for (int i = 0; i < breite; i++) {
	    kaestchen[i][0] = BELEGT;
	    kaestchen[i][hoehe - 1] = BELEGT;
	}

	for (int j = 0; j < hoehe; j++) {
	    kaestchen[0][j] = BELEGT;
	    kaestchen[breite - 1][j] = BELEGT;
	}

	for (int i = 1; i < breite - 1; i++) {
	    for (int j = 1; j < hoehe - 1; j++) {

		double zufallszahl = generator.nextDouble();
		if (zufallszahl < .36) kaestchen[i][j] = BELEGT;
		else kaestchen[i][j] = FREI;
	    }
	}
    }

    int getEintrag (int i, int j) {
	
	int wert = kaestchen[i][j];
	if (wert == BELEGT || wert == FREI || wert == BESUCHT) {
	    return wert;
	} else {
	    throw new FalscherEintragAusnahme
		("An Stelle " + i + ", " + j + " steht der Wert " +wert); 
	}
    }

    void setBesucht(int i, int j) {

	kaestchen[i][j] = BESUCHT;
    }

    /**
     * erzeugt eine Kopie
     * @return die Kopie
     */
    public Labyrinth kopie() {

	Labyrinth kopie = new Labyrinth(breite, hoehe);
	for (int i = 0; i < breite; i++) {
	    for (int j = 0; j < hoehe; j++) {
		kopie.kaestchen[i][j] = kaestchen[i][j];
	    }
	}
	return kopie;
    }
    
    /**
     * zeichnet das Labyrinth in schwarz und rot
     * @param g2 der Grafik-Kontext
     * @param pixelzahl die Seitenlänge der Kästchen in Pixel
     */
    public void zeichne(Graphics2D g2, int pixelzahl) {
	
	for (int i = 0; i < breite; i++) {
	    for (int j = 0; j < hoehe; j++) {
		
		int eintrag = getEintrag(i,j);
		Color farbe;
		
		if (eintrag == FREI) farbe = Color.white;
		else if (eintrag == BELEGT) farbe = Color.black;
		else if (eintrag == BESUCHT) farbe = Color.red;
		else {
		    throw new FalscherEintragAusnahme
			("Kaestchen "+i+", "+j+
			 " mit Wert "+eintrag+" belegt.");
		}
		g2.setColor(farbe);
		g2.fillRect(i*pixelzahl,j*pixelzahl,pixelzahl,pixelzahl);
	    }
	}
    }

    /**
     * markiert alle besuchten (roten) Punkte als belegt (schwarz)
     */
    public void besuchtNachBelegt() {

	for (int i=1; i<breite-1; i++) {
	    for (int j=1; j<hoehe-1; j++) {
		
		if (kaestchen[i][j] == BESUCHT) kaestchen[i][j] = BELEGT;
	    }
	}
    }
}
