Fuchs und Hase

D

David Nienhaus

Gast
Hallo liebe Leute,

ich brauche eure Hilfe:
Ich habe die Aufgabe das Programm "Fuchs und Hase" von den Autoren David J. Barnes and Michael Kolling zu erweitern.
Ich soll eine Klasse Fallensteller hinzufügen. Fallensteller sollen Fallen platzieren, die Füchse, bzw. Hasen töten, wenn sie darauf laufen.
Vor der Simulation soll eine feste Anzahl an Fallenstellern festgelegt werden, die während der Simulation konstant bleiben soll.
Genau da liegt mein Problem:
Aus irgendeinem mir unerklärlichen Grund werden währen der Simulation meine Fallensteller sowohl weniger als auch mehr.

Was ich bereits gemacht habe:
- neue Klasse Fallensteller
- Klasse Tier umgeändert zu Klasse Akteur (Fuchs, Hase, Fallensteller Unterklassen)
- Methode "agiere()" von Fallensteller lässt sie erstmal nur herumlaufen
- Methode "bevölkere()" in Klasse "Simulator" angepast, dass auf jeden fall die Anzahl der gewünschten Fallenleger vorhanden ist, nicht wie bei den Tieren nach Wahrscheinlickeit

Vielleicht könnt ihr mir weiterhelfen :)

Java:
import java.util.Random;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collections;
import java.awt.Color;

/**
* Ein einfacher Jäger-Beute-Simulator, basierend auf einem
* Feld mit Füchsen und Hasen.
*
* @author David J. Barnes and Michael Kolling
* @version 2003-04-13
*/
public class Simulator
{
    // Die privaten static final Variablen definieren
    // Konfigurationsinformationen für die Simulation.
    // Die Standardbreite für ein Feld.
    private static final int STANDARD_BREITE = 50;
    // Die Standardtiefe für ein Feld.
    private static final int STANDARD_TIEFE = 50;
  
    private static final int STANDARD_FALLENSTELLERANZAHL = 10;
    // Die Wahrscheinlichkeit f¸r die Geburt eines Fuchses an
    // einer beliebigen Position im Feld.
    private static final double FUCHSGEBURT_WAHRSCHEINLICH = 0.02;
    // Die Wahrscheinlichkeit f¸r die Geburt eines Fuchses an
    // einer beliebigen Position im Feld.
    private static final double HASENGEBURT_WAHRSCHEINLICH = 0.08; 
  
    private int anzahlFallensteller;

    // Die Liste der Tiere im Feld
    //private List tiere;
    private List akteure;
    // Die Liste der gerade geborenen Tiere
    private List neueAkteure;
    //Liste der Fallensteller im Feld
    // Der aktuelle Zustand des Feldes
    private Feld feld;
    // Zweites Feld, mit dem der n‰chste Schritt erzeugt wird
    private Feld naechstesFeld;
    // Der aktuelle Schritt der Simulation
    private int schritt;
    // Eine grafische Ansicht der Simulation
    private Simulationsansicht ansicht;
  
  
    /**
     * Erzeuge ein Simulationsfeld mit einer Standardgrˆfle.
     */
    public Simulator()
    {
        this(STANDARD_TIEFE, STANDARD_BREITE, STANDARD_FALLENSTELLERANZAHL);
    }
  
    /**
     * Erzeuge ein Simulationsfeld mit der gegebenen Grˆfle.
     * @param tiefe die Tiefe des Feldes (muss grˆfler als Null sein).
     * @param breite die Breite des Feldes (muss grˆfler als Null sein).
     */
    public Simulator(int tiefe, int breite, int anzahlFallensteller)
    {
        if(breite <= 0 || tiefe <= 0) {
            System.out.println("Abmessungen müssen gröfler als Null sein.");
            System.out.println("Benutze Standardwerte.");
            tiefe = STANDARD_TIEFE;
            breite = STANDARD_BREITE;
            anzahlFallensteller = STANDARD_FALLENSTELLERANZAHL;
        }
        akteure = new ArrayList();
        neueAkteure = new ArrayList();
        feld = new Feld(tiefe, breite);
        naechstesFeld = new Feld(tiefe, breite);
        this.anzahlFallensteller = anzahlFallensteller;
        // Eine Ansicht der Zust‰nde aller Positionen im Feld erzeugen.
        ansicht = new Simulationsansicht(tiefe, breite);
        ansicht.setzeFarbe(Fuchs.class, Color.blue);
        ansicht.setzeFarbe(Hase.class, Color.orange);
        ansicht.setzeFarbe(Fallensteller.class, Color.green);
      
        // Einen g¸ltigen Startzustand einnehmen.
        zuruecksetzen();
    }
  
    /**
     * Starte die Simulation vom aktuellen Zustand aus f¸r einen l‰ngeren
     * Zeitraum, etwa 500 Schritte.
     */
    public void starteLangeSimulation()
    {
        simuliere(500);
    }
  
    /**
     * F¸hre vom aktuellen Zustand aus die angegebene Anzahl an
     * Simulationsschritten durch.
     * Brich vorzeitig ab, wenn die Simulation nicht mehr aktiv ist.
     */
    public void simuliere(int schritte)
    {
        for(int schritt = 1; schritt <= schritte && ansicht.istAktiv(feld); schritt++) {
            simuliereEinenSchritt();
        }
    }
  
    /**
     * F¸hre einen einzelnen Simulationsschritt aus:
     * Durchlaufe alle Feldpositionen und aktualisiere den
     * Zustand jedes Fuchses und Hasen.
     */
    public void simuliereEinenSchritt()
    {
        schritt++;
        neueAkteure.clear();
      
        // alle Akteure agieren lassen
        for(Iterator iter = akteure.iterator(); iter.hasNext(); ) {
            Akteur akteur = (Akteur)iter.next();
            if(akteur.istLebendig()) {
                akteur.agiere(feld, naechstesFeld, neueAkteure);
            }
            else {
                iter.remove();   // totes Tier entfernen
            }
        }
        // neu geborene Tiere in die Liste der Tiere einfügen.
        akteure.addAll(neueAkteure);
      
        // feld und nächstesFeld am Ende des Schritts austauschen.
        Feld temp = feld;
        feld = naechstesFeld;
        naechstesFeld = temp;
        naechstesFeld.raeumen();

        // das neue Feld in der Ansicht anzeigen.
        ansicht.zeigeStatus(schritt, feld);
    }
      
    /**
     * Setze die Simulation an den Anfang zur¸ck.
     */
    public void zuruecksetzen()
    {
        schritt = 0;
        akteure.clear();
        feld.raeumen();
        naechstesFeld.raeumen();
        bevoelkere(feld);
      
        // Zeige den Startzustand in der Ansicht.
        ansicht.zeigeStatus(schritt, feld);
    }
  
    /**
     * Bevölkere das Feld mit Füchsen, Hasen und Fallenstellern.
     */
    private void bevoelkere(Feld feld)
    {
        Random rand = new Random();
        feld.raeumen();
        // Alle Fallensteller (Annzahl vorgegeben) auf zufälligen Positionen platzieren.
        for (int i=0; i<anzahlFallensteller; i++)
        {
            int zeile = rand.nextInt(feld.gibTiefe());
            int spalte = rand.nextInt(feld.gibBreite());
            if (feld.gibObjektAn(zeile, spalte) != null){
                i--;
            }
            else {
                Fallensteller fallensteller = new Fallensteller();
                fallensteller.setzePosition(zeile, spalte);
                akteure.add(fallensteller);
                feld.platziere(fallensteller);
            }
        }
        for(int zeile = 0; zeile < feld.gibTiefe(); zeile++) {
            for(int spalte = 0; spalte < feld.gibBreite(); spalte++) {
                if (feld.gibObjektAn(zeile, spalte) != null)
                {
                }
                else if(rand.nextDouble() <= FUCHSGEBURT_WAHRSCHEINLICH) {
                    Fuchs fuchs = new Fuchs(true);
                    fuchs.setzePosition(zeile, spalte);
                    akteure.add(fuchs);
                    feld.platziere(fuchs);
                }
                else if(rand.nextDouble() <= HASENGEBURT_WAHRSCHEINLICH) {
                    Hase hase = new Hase(true);
                    hase.setzePosition(zeile, spalte);
                    akteure.add(hase);
                    feld.platziere(hase);
                }
                // ansonsten die Position leer lassen
            }
        }
        Collections.shuffle(akteure);
    }
}
Java:
import java.util.List;


public abstract class Akteur
{
    private Position position;
    private boolean lebendig;
    private int alter;
  
    /**
     * Erzeuge ein Tier mit Alter Null (ein Neugeborenes).
     */
    public Akteur()
    {
        alter = 0;
        lebendig = true;
    }
  
    /**
     * Lasse dieses Tier agieren - es soll das tun, was
     * es tun muss oder mˆchte.
     */
    abstract public void agiere(Feld aktuellesFeld, Feld naechstesFeld, List neueTiere);

    /**
     * Liefere das Alter dieses Tieres.
     * @return das Alter dieses Tieres.
     */
    public int gibAlter()
    {
        return alter;
    }

    /**
     * Setze das Alter dieses Tieres.
     * @param alter das Alter dieses Tieres.
     */
    public void setzeAlter(int alter)
    {
        this.alter = alter;
    }
  
    /**
     * Pr¸fe, ob dieses Tier noch lebendig ist.
     * @return true wenn dieses Tier noch lebendig ist.
     */
    public boolean istLebendig()
    {
        return lebendig;
    }
  
    /**
     * Signalisiere diesem Tier, dass es gestorben ist.   :-(
     */
    public void setzeGestorben()
    {
        lebendig = false;
    }

    /**
     * Liefere die Position dieses Tieres.
     * @return die Position dieses Tieres.
     */
    public Position gibPosition()
    {
        return position;
    }

    /**
     * Setze die Position dieses Tieres.
     * @param zeile die vertikale Koordinate der Position.
     * @param spalte die horizontale Koordinate der Position.
     */
    public void setzePosition(int zeile, int spalte)
    {
        this.position = new Position(zeile, spalte);
    }

    /**
     * Setze die Position dieses Tieres.
     * @param position die Position dieses Tieres.
     */
    public void setzePosition(Position position)
    {
        this.position = position;
    }

}
Java:
import java.util.List;
import java.util.Iterator;
import java.util.Random;

/**
* Tier ist eine abstrakte Superklasse f¸r Tiere.
* Sie verwaltet Eigenschaften, die alle Tiere gemein haben,
* wie etwas das Alter oder eine Position.
*
* @author David J. Barnes and Michael Kolling
* @version 2003-04-16
*/
public class Fallensteller extends Akteur
{
    // Die Position dieses Tieres.
    private Position position;
    /**
     * Erzeuge ein Tier mit Alter Null (ein Neugeborenes).
     */
    public Fallensteller()
    {
        super();
    }
  
    public void agiere(Feld aktuellesFeld, Feld naechstesFeld, List neueAkteure)
    {
            Position neuePosition = naechstesFeld.freieNachbarposition(gibPosition());
            // nur in das n‰chste Feld setzen, wenn eine Position frei ist
            if(neuePosition != null) {
                setzePosition(neuePosition);
                naechstesFeld.platziere(this);
            }
            else {
                setzePosition(position);
                naechstesFeld.platziere(this);
            }
    }
}
Java:
import java.util.List;
import java.util.Iterator;
import java.util.Random;

/**
* Ein simples Modell eines Fuchses.
* F¸chse altern, bewegen sich, fressen Hasen und sterben.
*
* @author David J. Barnes and Michael Kolling
* @version 2003-04-16
*/
public class Fuchs extends Akteur
{
    // Eigenschaften aller F¸chse (statische Datenfelder)
  
    // Das Alter, in dem ein Fuchs geb‰rf‰hig wird.
    private static final int GEBAER_ALTER = 10;
    // Das Hˆchstalter eines Fuchses.
    private static final int MAX_ALTER = 150;
    // Die Wahrscheinlichkeit, mit der ein Fuchs Nachwuchs geb‰rt.
    private static final double GEBAER_WAHRSCHEINLICHKEIT = 0.09;
    // Die maximale Grˆfle eines Wurfes (Anzahl der Jungen).
    private static final int MAX_WURFGROESSE = 3;
    // Der N‰hrwert eines einzelnen Hasen. Letztendlich ist
    // dies die Anzahl der Schritte, die ein Fuchs bis zur
    //n‰chsten Mahlzeit laufen kann.
    private static final int HASEN_NAEHRWERT = 4;
    // Ein Zufallsgenerator, der die Geburten beeinflusst.
    private static final Random rand = new Random();
  
    // Individuelle Eigenschaften (Instanzfelder).

    // Der Futter-Level, der durch das Fressen von Hasen erhˆht wird.
    private int futterLevel;

    /**
     * Erzeuge einen Fuchs. Ein Fuchs wird entweder neu geboren
     * (Alter 0 Jahre und nicht hungrig) oder mit einem zuf‰lligen Alter.
     *
     * @param zufaelligesAlter falls true, hat der neue Fuchs ein
     *        zuf‰lliges Alter und einen zuf‰lligen Futter-Level.
     */
    public Fuchs(boolean zufaelligesAlter)
    {
        super();
        if(zufaelligesAlter) {
            setzeAlter(rand.nextInt(MAX_ALTER));
            futterLevel = rand.nextInt(HASEN_NAEHRWERT);
        }
        else {
            // leave age at 0
            futterLevel = HASEN_NAEHRWERT;
        }
    }
  
    /**
     * Das was ein Fuchs die meiste Zeit tut: er jagt Hasen.
     * Dabei kann er Nachwuchs geb‰ren, vor Hunger sterben oder
     * an Altersschw‰che.
     */
    public void agiere(Feld aktuellesFeld, Feld naechstesFeld, List neueAkteure)
    {
        alterErhoehen();
        hungerVergroessern();
        if(istLebendig()) {
            // neue Füchse werden in Nachbarpositionen geboren.
            int geburten = gebaereNachwuchs();
            for(int b = 0; b < geburten; b++) {
                Fuchs neuerFuchs = new Fuchs(false);
                neueAkteure.add(neuerFuchs);
                neuerFuchs.setzePosition(naechstesFeld.zufaelligeNachbarposition(gibPosition()));
                naechstesFeld.platziere(neuerFuchs);
            }
            // In die Richtung bewegen, in der Futter gefunden wurde.
            Position neuePosition = findeNahrung(aktuellesFeld, gibPosition());
            if(neuePosition == null) {  // kein Futter - zuf‰llig bewegen
                neuePosition = naechstesFeld.freieNachbarposition(gibPosition());
            }
            if(neuePosition != null) {
                setzePosition(neuePosition);
                naechstesFeld.platziere(this); // setzt die Position
            }
            else {
                // weder Bleiben noch Gehen mˆglich - ‹berpopulation - kein Platz
                setzeGestorben();
            }
        }
    }
  
    /**
     * Erhˆhe das Alter dieses Fuchses. Dies kann zu seinem
     * Tod f¸hren.
     */
    private void alterErhoehen()
    {
        setzeAlter(gibAlter()+1);
        if(gibAlter() > MAX_ALTER) {
            setzeGestorben();
        }
    }
  
    /**
     * Vergrˆflere den Hunger dieses Fuchses. Dies kann zu seinem
     * Tode f¸hren.
     */
    private void hungerVergroessern()
    {
        futterLevel--;
        if(futterLevel <= 0) {
            setzeGestorben();
        }
    }
  
    /**
     * Suche nach Nahrung (Hasen) in den Nachbarpositionen.
     * @param feld das Feld, in dem gesucht werden soll.
     * @param position die Position, an der sich der Fuchs befindet.
     * @return die Position mit Nahrung, oder null, wenn keine vorhanden.
     */
    private Position findeNahrung(Feld feld, Position position)
    {
        Iterator nachbarPositionen =
                          feld.nachbarpositionen(position);
        while(nachbarPositionen.hasNext()) {
            Position pos = (Position) nachbarPositionen.next();
            Object akteur = feld.gibObjektAn(pos);
            if(akteur instanceof Hase) {
                Hase hase = (Hase) akteur;
                if(hase.istLebendig()) {
                    hase.setzeGestorben();
                    futterLevel = HASEN_NAEHRWERT;
                    return pos;
                }
            }
        }
        return null;
    }
      
    /**
     * Geb‰re Nachwuchs, wenn dieser Fuchs geb‰rf‰hig ist.
     * @return die Anzahl der Neugeborenen (kann Null sein).
     */
    private int gebaereNachwuchs()
    {
        int geburten = 0;
        if(kannGebaeren() && rand.nextDouble() <= GEBAER_WAHRSCHEINLICHKEIT) {
            geburten = rand.nextInt(MAX_WURFGROESSE) + 1;
        }
        return geburten;
    }
  
    /**
     * Liefere eine String-Beschreibung dieses Fuchses.
     */
    public String toString()
    {
      return "Fuchs, Alter " + gibAlter();
    }

    /**
     * Ein Fuchs kann geb‰ren, wenn er das geb‰rf‰hige
     * Alter erreicht hat.
     */
    private boolean kannGebaeren()
    {
        return gibAlter() >= GEBAER_ALTER;
    }
  
}
Java:
import java.util.List;
import java.util.Random;

/**
* Ein einfaches Modell eines Hasen.
* Ein Hase altert, bewegt sich, geb‰rt Nachwuchs und stirbt.
*
* @author David J. Barnes and Michael Kolling
* @version 2003-04-16
*/
public class Hase extends Akteur
{
    // Eigenschaften aller Hasen (statische Datenfelder).

    // Das Alter, in dem ein Hase geb‰rf‰hig wird.
    private static final int GEBAER_ALTER = 5;
    // Das Hˆchstalter eines Hasen.
    private static final int MAX_ALTER = 50;
    // Die Wahrscheinlichkeit, mit der ein Hase Nachwuchs geb‰rt.
    private static final double GEBAER_WAHRSCHEINLICHKEIT = 0.15;
    // Die maximale Grˆfle eines Wurfes (Anzahl der Jungen)
    private static final int MAX_WURFGROESSE = 5;
    // Ein Zufallsgenerator, der die Geburten beeinflusst.
    private static final Random rand = new Random();
  
    // Individuelle Eigenschaften eines Hasen (Instanzfelder).
  
    /**
     * Erzeuge einen neuen Hasen. Ein Hase kann das Alter 0
     *(neu geboren) oder ein zuf‰lliges Alter haben.
     * @param zufaelligesAlter soll der Hase ein zuf‰lliges Alter haben?
     */
    public Hase(boolean zufaelligesAlter)
    {
        super();
        if(zufaelligesAlter) {
            setzeAlter(rand.nextInt(MAX_ALTER));
        }
    }
  
    /**
     * Das was ein Hase die meiste Zeit tut - er l‰uft herum.
     * Manchmal geb‰rt er Nachwuchs und irgendwann stirbt er
     * an Altersschw‰che.
     */
    public void agiere(Feld feld, Feld naechstesFeld, List neueAkteure)
    {
        alterErhoehen();
        if(istLebendig()) {
            int geburten = gebaereNachwuchs();
            for(int b = 0; b < geburten; b++) {
                Hase neuerHase = new Hase(false);
                neueAkteure.add(neuerHase);
                neuerHase.setzePosition(naechstesFeld.zufaelligeNachbarposition(gibPosition()));
                naechstesFeld.platziere(neuerHase);
            }
            Position neuePosition = naechstesFeld.freieNachbarposition(gibPosition());
            // nur in das n‰chste Feld setzen, wenn eine Position frei ist
            if(neuePosition != null) {
                setzePosition(neuePosition);
                naechstesFeld.platziere(this);
            }
            else {
                // weder Bleiben noch Gehen mˆglich - ‹berpopulation - kein Platz
                setzeGestorben();
            }
        }
    }
  
    /**
     * Erhˆhe das Alter dieses Hasen.
     * Dies kann zu seinem Tod f¸hren.
     */
    private void alterErhoehen()
    {
        setzeAlter(gibAlter()+1);
        if(gibAlter() > MAX_ALTER) {
            setzeGestorben();
        }
    }
  
    /**
     * Geb‰re Nachwuchs, wenn dieser Hase geb‰rf‰hig ist.
     * @return die Anzahl der Neugeborenen (kann Null sein).
     */
    private int gebaereNachwuchs()
    {
        int geburten = 0;
        if(kannGebaeren() && rand.nextDouble() <= GEBAER_WAHRSCHEINLICHKEIT) {
            geburten = rand.nextInt(MAX_WURFGROESSE) + 1;
        }
        return geburten;
    }

    public String toString()
    {
        return "Hase, Alter " + gibAlter();
    }
    /**
     * Ein Hase kann geb‰ren, wenn er das geb‰rf‰hige Alter
     * erreicht hat.
     */
    private boolean kannGebaeren()
    {
        return gibAlter() >= GEBAER_ALTER;
    }
}

Java:
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Random;
import java.lang.reflect.Type;

/**
* Ein rechteckiges Gitter von Feldpositionen.
* Jede Position kann ein einzelnen Akteur aufnehmen.
*
* @author David J. Barnes and Michael Kolling
* @version 2003-04-16
*/
public class Feld
{
    private static final Random rand = new Random();
  
    // Die Tiefe und die Breite des Feldes
    private int tiefe, breite;
    // Speicher für die Tiere
    private Akteur[][] feld;

    /**
     * Erzeuge ein Feld mit den angegebenen Dimensionen.
     * @param tiefe die Tiefe des Feldes.
     * @param breite die Breite des Feldes.
     */
    public Feld(int tiefe, int breite)
    {
        this.tiefe = tiefe;
        this.breite = breite;
        feld = new Akteur[tiefe][breite];
    }
  
    /**
     * R‰ume das Feld.
     */
    public void raeumen()
    {
        for(int zeile = 0; zeile < tiefe; zeile++) {
            for(int spalte = 0; spalte < breite; spalte++) {              
                    feld[zeile][spalte] = null;
            }
        }
    }
      
    /**
     * Platziere das gegebene Tier an der angegebenen Position.
     * Wenn an der Position bereits ein Tier eingetragen ist,
     * geht es verloren.
     * @param tier das Tier, das platziert werden soll.
     */
    public void platziere(Akteur akteur)
    {
        Position position = akteur.gibPosition();
        feld[position.gibZeile()][position.gibSpalte()] = akteur;
    }
  
    /**
     * Liefere das Tier an der angegebenen Position, falls vorhanden.
     * @param position die gew¸nschte Position.
     * @return das Tier an der angegebenen Position oder null, wenn
     *         dort kein Tier ist.
     */
    public Akteur gibObjektAn(Position position)
    {
        return gibObjektAn(position.gibZeile(), position.gibSpalte());
    }
  
    /**
     * Liefere das Tier an der angegebenen Position, falls vorhanden.
     * @param zeile die gew¸nschte Zeile.
     * @param spalte die gew¸nschte Spalte.
     * @return das Tier an der angegebenen Position oder null, wenn
     *         dort kein Tier ist.
     */
    public Akteur gibObjektAn(int zeile, int spalte)
    {
        return feld[zeile][spalte];
    }
  
    /**
     * Wähle zufällig eine der Positionen, die an die gegebene Position
     * angrenzen, oder die gegebene Position selbst.
     * Die gelieferte Position liegt innerhalb der gültigen Grenzen
     * dieses Feldes.
     * @param position die Position, von der ein Nachbar zu w‰hlen ist.
     * @return eine g¸ltige Position innerhalb dieses Feldes. Das kann
     *         auch die gegebene Position selbst sein.
     */
    public Position zufaelligeNachbarposition(Position position)
    {
        int zeile = position.gibZeile();
        int spalte = position.gibSpalte();
        // Zufällig eine Abweichung von -1, 0 oder +1 für Zeile und Spalte wählen.
        int naechsteZeile = zeile + rand.nextInt(3) - 1;
        int naechsteSpalte = spalte + rand.nextInt(3) - 1;
        // Prüfen, ob die neue Position außerhalb der Feldgrenzen liegt.
        if(naechsteZeile < 0 || naechsteZeile >= tiefe
           || naechsteSpalte < 0 || naechsteSpalte >= breite || feld[naechsteZeile][naechsteSpalte] == null) {
            return position;
        }
        else if(naechsteZeile != zeile || naechsteSpalte != spalte ) {
            return new Position(naechsteZeile, naechsteSpalte);
        }
        else {
            return position;
        }
    }
  
    /**
     * Versuche, eine freie Nachbarposition zur gegebenen Position zu
     * finden. Wenn es keine gibt, liefere die gegebene Position, wenn
     * sie selbst frei ist. Ansonsten liefere null.
     * Die gelieferte Position liegt innerhalb der Feldgrenzen.
     * @param position die Position, f¸r die eine Nachbarposition
     *                 zu liefern ist.
     * @return eine g¸ltige Position innerhalb der Feldgrenzen. Das
     *         kann die gegebene Position selbst sein oder null, wenn
     *         alle Nachbarpositionen und die Position selbst belegt sind.
     */
    public Position freieNachbarposition(Position position)
    {
        Iterator nachbarn = nachbarpositionen(position);
        while(nachbarn.hasNext()) {
            Position naechste = (Position) nachbarn.next();
            if(feld[naechste.gibZeile()][naechste.gibSpalte()] == null) {
                return naechste;
            }
        }
        // Prüfen, ob die gegebene Position selbst frei ist.
        if(feld[position.gibZeile()][position.gibSpalte()] == null) {
            return position;
        }
        else {
            return null;
        }
    }

    /**
     * Erzeuge einen Iterator ¸ber eine gemischte Liste von Nachbarpositionen
     * zu der gegebenen Position. Diese Liste enth‰lt nicht die gegebene
     * Position selbst. Alle Positionen liegen innerhalb des Feldes.
     * @param position die Position, f¸r die Nachbarpositionen zu liefern sind.
     * @return ein Iterator ¸ber Nachbarpositionen zur gegebenen Position.
     */
    public Iterator nachbarpositionen(Position position)
    {
        int zeile = position.gibZeile();
        int spalte = position.gibSpalte();
        LinkedList positionen = new LinkedList();
        for(int zDiff = -1; zDiff <= 1; zDiff++) {
            int naechsteZeile = zeile + zDiff;
            if(naechsteZeile >= 0 && naechsteZeile < tiefe) {
                for(int sDiff = -1; sDiff <= 1; sDiff++) {
                    int naechsteSpalte = spalte + sDiff;
                    // Exclude invalid locations and the original location.
                    if(naechsteSpalte >= 0 && naechsteSpalte < breite && (zDiff != 0 || sDiff != 0)) {
                        positionen.add(new Position(naechsteZeile, naechsteSpalte));
                    }
                }
            }
        }
        Collections.shuffle(positionen,rand);
        return positionen.iterator();
    }

    /**
     * @return die Tiefe dieses Feldes.
     */
    public int gibTiefe()
    {
        return tiefe;
    }
  
    /**
     * @return die Breite dieses Feldes.
     */
    public int gibBreite()
    {
        return breite;
    }
}

Java:
/**
* Objekte dieser Klasse repr‰sentieren
* Positionen in einem rechteckigen Feld.
*
* @author David J. Barnes and Michael Kolling
* @version 2002-04-09
*/
public class Position
{
    // Zeilen- und Spaltenposition.
    private int zeile;
    private int spalte;

    /**
     * Repräsentiere eine Zeile und eine Spalte.
     * @param zeile die Zeile.
     * @param spalte die Spalte.
     */
    public Position(int zeile, int spalte)
    {
        this.zeile = zeile;
        this.spalte = spalte;
    }
  
    /**
     * Pr¸fung auf Datengleichheit.
     */
    public boolean equals(Object obj)
    {
        if(obj instanceof Position) {
            Position anderePosition = (Position) obj;
            return zeile == anderePosition.gibZeile()
                && spalte == anderePosition.gibSpalte();
        }
        else {
            return false;
        }
    }
  
    /**
     * Liefere einen String in der Form 'Zeile,Spalte'
     * @return eine Stringdarstellung dieser Position.
     */
    public String toString()
    {
        return zeile + "," + spalte;
    }
  
    /**
     * Benutze die 16 hˆherwertigen Bits f¸r den den Zeilenwert
     * und die 16 niederwertigen Bits f¸r den Spaltenwert.
     * Aufler f¸r sehr grofle Felder sollte dies einen eindeutigen
     * Hashwert f¸r jedes Zeile-Spalte-Paar geben.
     */
    public int hashCode()
    {
        return (zeile << 16) + spalte;
    }
  
    /**
     * @return Die Zeile.
     */
    public int gibZeile()
    {
        return zeile;
    }
  
    /**
     * @return Die Spalte.
     */
    public int gibSpalte()
    {
        return spalte;
    }
}
 
D

David Nienhaus

Gast
Klar, hier :)

Java:
import java.awt.*;
import javax.swing.*;
import java.util.HashMap;

/**
* Eine grafische Ansicht des Simulationsfeldes.
* Die Ansicht zeigt f¸r jede Position ein gef‰rbtes Rechteck,
* das den jeweiligen Inhalt repr‰sentiert, und hat eine
* vorgebene Hintergrundfarbe.
* Die Farben f¸r die verschiedenen Tierarten kˆnnen mit
* der Methode setzeFarbe definiert werden.
*
* @author David J. Barnes and Michael Kolling
* @version 2003-04-12
*/
public class Simulationsansicht extends JFrame
{
    // Die Farbe f¸r leere Positionen
    private static final Color LEER_FARBE = Color.white;

    // Die Farbe f¸r Objekte ohne definierte Farbe
    private static final Color UNDEF_FARBE = Color.gray;

    private final String SCHRITT_PREFIX = "Schritt: ";
    private final String POPULATION_PREFIX = "Population: ";
    private JLabel schrittLabel, population;
    private Feldansicht feldansicht;
   
    // Eine Map f¸r die Farben der Simulationsteilnehmer
    // (Abbildung Tierklasse -> Farbe)
    private HashMap farben;
    // Ein Statistik-Objekt zur Berechnung und Speicherung
    // von Simulationsdaten
    private FeldStatistik stats;

    /**
     * Erzeuge eine Ansicht mit der gegebenen Breite und Hˆhe.
     */
    public Simulationsansicht(int hoehe, int breite)
    {
        stats = new FeldStatistik();
        farben = new HashMap();

        setTitle("Simulation von F¸chsen und Hasen");
        schrittLabel = new JLabel(SCHRITT_PREFIX, JLabel.CENTER);
        population = new JLabel(POPULATION_PREFIX, JLabel.CENTER);
       
        setLocation(100, 50);
       
        feldansicht = new Feldansicht(hoehe, breite);

        Container inhalt = getContentPane();
        inhalt.add(schrittLabel, BorderLayout.NORTH);
        inhalt.add(feldansicht, BorderLayout.CENTER);
        inhalt.add(population, BorderLayout.SOUTH);
        pack();
        setVisible(true);
    }
   
    /**
     * Definiere eine Farbe f¸r die gegebene Tierklasse.
     */
    public void setzeFarbe(Class tierklasse, Color farbe)
    {
        farben.put(tierklasse, farbe);
    }

    /**
     * Liefere die definierte Farbe f¸r eine gegebene Tierklasse.
     */
    private Color gibFarbe(Class tierklasse)
    {
        Color farbe = (Color)farben.get(tierklasse);
        if(farbe == null) {
            // f¸r die gegebene Klasse ist keine Farbe definiert
            return UNDEF_FARBE;
        }
        else {
            return farbe;
        }
    }

    /**
     * Zeige den aktuellen Zustand des Feldes.
     * @param schritt welcher Iterationsschritt ist dies.
     * @param feld das Feld, das angezeigt werden soll.
     */
    public void zeigeStatus(int schritt, Feld feld)
    {
        if(!isVisible())
            setVisible(true);

        schrittLabel.setText(SCHRITT_PREFIX + schritt);

        stats.zuruecksetzen();
        feldansicht.zeichnenVorbereiten();
           
        for(int zeile = 0; zeile < feld.gibTiefe(); zeile++) {
            for(int spalte = 0; spalte < feld.gibBreite(); spalte++) {
                Object tier = feld.gibObjektAn(zeile, spalte);
                if(tier != null) {
                    stats.erhoeheZaehler(tier.getClass());
                    feldansicht.zeichneMarkierung(spalte, zeile, gibFarbe(tier.getClass()));
                }
                else {
                    feldansicht.zeichneMarkierung(spalte, zeile, LEER_FARBE);
                }
            }
        }
        stats.zaehlungBeendet();

        population.setText(POPULATION_PREFIX + stats.gibBewohnerInfo(feld));
        feldansicht.repaint();
    }

    /**
     * Entscheide, ob die Simulation weiterlaufen soll.
     * @return true wenn noch mehr als eine Spezies lebendig ist.
     */
    public boolean istAktiv(Feld feld)
    {
        return stats.istAktiv(feld);
    }
   
    /**
     * Liefere eine grafische Ansicht eines rechteckigen Feldes.
     * Dies ist eine geschachtelte Klasse (eine Klasse, die
     * innerhalb einer anderen Klasse definiert ist), die eine
     * eigene grafische Komponente f¸r die Benutzungsschnittstelle
     * definiert. Diese Komponente zeigt das Feld an.
     * Dies ist fortgeschrittene GUI-Technik - Sie kˆnnen sie
     * f¸r Ihr Projekt ignorieren, wenn Sie wollen.
     */
    private class Feldansicht extends JPanel
    {
        private final int DEHN_FAKTOR = 6;

        private int feldBreite, feldHoehe;
        private int xFaktor, yFaktor;
        Dimension groesse;
        private Graphics g;
        private Image feldImage;

        /**
         * Erzeuge eine neue Komponente zur Feldansicht.
         */
        public Feldansicht(int hoehe, int breite)
        {
            feldHoehe = hoehe;
            feldBreite = breite;
            groesse = new Dimension(0, 0);
        }

        /**
         * Der GUI-Verwaltung mitteilen, wie grofl wir sein wollen.
         * Der Name der Methode ist durch die GUI-Verwaltung festgelegt.
         */
        public Dimension getPreferredSize()
        {
            return new Dimension(feldBreite * DEHN_FAKTOR,
                                 feldHoehe * DEHN_FAKTOR);
        }
       
        /**
         * Bereite eine neue Zeichenrunde vor. Da die Komponente
         * in der Grˆfle ge‰ndert werden kann, muss der Maflstab neu
         * berechnet werden.
         */
        public void zeichnenVorbereiten()
        {
            if(! groesse.equals(getSize())) {  // Grˆfle wurde ge‰ndert...
                groesse = getSize();
                feldImage = feldansicht.createImage(groesse.width, groesse.height);
                g = feldImage.getGraphics();

                xFaktor = groesse.width / feldBreite;
                if(xFaktor < 1) {
                    xFaktor = DEHN_FAKTOR;
                }
                yFaktor = groesse.height / feldHoehe;
                if(yFaktor < 1) {
                    yFaktor = DEHN_FAKTOR;
                }
            }
        }
       
        /**
         * Zeichne an der gegebenen Position ein Rechteck mit
         * der gegebenen Farbe.
         */
        public void zeichneMarkierung(int x, int y, Color farbe)
        {
            g.setColor(farbe);
            g.fillRect(x * xFaktor, y * yFaktor, xFaktor-1, yFaktor-1);
        }

        /**
         * Die Komponente f¸r die Feldansicht muss erneut angezeigt
         * werden. Kopiere das interne Image in die Anzeige.
         * Der Name der Methode ist durch die GUI-Verwaltung festgelegt.
         */
        public void paintComponent(Graphics g)
        {
            if(feldImage != null) {
                g.drawImage(feldImage, 0, 0, null);
            }
        }
    }
}
ute das Problem könnte vielleicht in Klasse Feld Method
 
D

David Nienhaus

Gast
Die letzten beiden Klassen kann ich ja dann auch noch posten

Java:
/**
* Diese Klasse definiert Z‰hler f¸r die Akteurstypen
* in einer Simulation.
* Ein Z‰hler wird ¸ber einen Namen identifiziert und
* z‰hlt, wieviele Akteure des Typs innerhalb der Simulation
* jeweils existieren.
*
* @author David J. Barnes and Michael Kolling
* @version 2003-04-12
*/
public class Zaehler
{
    // Ein Name f¸r den Akteurstyp in dieser Simulation
    private String name;
    // Wie viele von diesem Typ existieren in der Simulation.
    private int zaehler;

    /**
     * Initialisiere mit dem Namen des Typs.
     * @param name Ein Name, z.B. "Fuchs".
     */
    public Zaehler(String name)
    {
        this.name = name;
        zaehler = 0;
    }
   
    /**
     * @return den Namen des Typs dieses Z‰hlers.
     */
    public String gibName()
    {
        return name;
    }

    /**
     * @return den aktuellen Z‰hlerstand dieses Typs.
     */
    public int gibStand()
    {
        return zaehler;
    }

    /**
     * Erhˆhe diesen Z‰hler um Eins.
     */
    public void erhoehen()
    {
        zaehler++;
    }
   
    /**
     * Setze diesen Z‰hler auf Null zur¸ck.
     */
    public void zuruecksetzen()
    {
        zaehler = 0;
    }
}

Java:
import java.util.HashMap;
import java.util.Iterator;

/**
* Diese Klasse sammelt und liefert statistische Daten ¸ber den
* Zustand eines Feldes. Auf sehr flexible Weise: Es wird ein
* Z‰hler angelegt und gepflegt f¸r jede Objektklasse, die im
* Feld gefunden wird.
*
* @author David J. Barnes and Michael Kolling
* @version 2003-04-12
*/
public class FeldStatistik
{
    // Die Z‰hler f¸r die jeweiligen Akteurstypen (Fuchs, Hase, etc.)
    // in der Simulation.
    private HashMap zaehler;
    // Sind die Z‰hlerst‰nde momentan aktuell?
    private boolean zaehlerAktuell;

    /**
     * Erzeuge ein Objekt f¸r die Feldstatistik.
     */
    public FeldStatistik()
    {
        // Wir legen eine Sammlung f¸r die Z‰hler an, die wir f¸r
        // die gefundenen Tierarten erzeugen.
        zaehler = new HashMap();
        zaehlerAktuell = true;
    }

    /**
     * @return Eine Beschreibung, welche Tiere das
     *          Feld bevˆlkern.
     */
    public String gibBewohnerInfo(Feld feld)
    {
        StringBuffer buffer = new StringBuffer();
        if(!zaehlerAktuell) {
            gibZaehlerstaende(feld);
        }
        Iterator schluessel = zaehler.keySet().iterator();
        while(schluessel.hasNext()) {
            Zaehler info = (Zaehler) zaehler.get(schluessel.next());
            buffer.append(info.gibName());
            buffer.append(": ");
            buffer.append(info.gibStand());
            buffer.append(' ');
        }
        return buffer.toString();
    }
   
    /**
     * Verwerfe alle bisher gesammelten Daten; setze alle Z‰hler
     * auf Null zur¸ck.
     */
    public void zuruecksetzen()
    {
        zaehlerAktuell = false;
        Iterator schluessel = zaehler.keySet().iterator();
        while(schluessel.hasNext()) {
            Zaehler z = (Zaehler) zaehler.get(schluessel.next());
            z.zuruecksetzen();
        }
    }

    /**
     * Erhˆhe den Z‰hler f¸r eine Tierklasse.
     */
    public void erhoeheZaehler(Class tierklasse)
    {
        Zaehler z = (Zaehler) zaehler.get(tierklasse);
        if(z == null) {
            // Wir haben noch keinen Z‰hler f¸r
            // diese Spezies - also neu anlegen
            z = new Zaehler(tierklasse.getName());
            zaehler.put(tierklasse, z);
        }
        z.erhoehen();
    }

    /**
     * Signalisiere, dass eine Tierz‰hlung beendet ist.
     */
    public void zaehlungBeendet()
    {
        zaehlerAktuell = true;
    }

    /**
     * Stelle fest, ob die Simulation noch aktiv ist, also
     * ob sie weiterhin laufen sollte.
     * @return true wenn noch mehr als eine Spezies lebt.
     */
    public boolean istAktiv(Feld feld)
    {
        // Wieviele Z‰hler sind nicht Null.
        int nichtNull = 0;
        if(!zaehlerAktuell) {
            gibZaehlerstaende(feld);
        }
        Iterator schluessel = zaehler.keySet().iterator();
        while(schluessel.hasNext()) {
            Zaehler info = (Zaehler) zaehler.get(schluessel.next());
            if(info.gibStand() > 0) {
                nichtNull++;
            }
        }
        return nichtNull > 1;
    }
   
    /**
     * Erzeuge Z‰hler f¸r die Anzahl der F¸chse und Hasen.
     * Diese werden nicht st‰ndig aktuell gehalten, w‰hrend
     * F¸chse und Hasen in das Feld gesetzt werden, sondern
     * jeweils bei der Abfrage der Z‰hlerst‰nde berechnet.
     */
    private void gibZaehlerstaende(Feld feld)
    {
        zuruecksetzen();
        for(int zeile = 0; zeile < feld.gibTiefe(); zeile++) {
            for(int spalte = 0; spalte < feld.gibBreite(); spalte++) {
                Object tier = feld.gibObjektAn(zeile, spalte);
                if(tier != null) {
                    erhoeheZaehler(tier.getClass());
                }
            }
        }
        zaehlerAktuell = true;
    }
}
 
D

David Nienhaus

Gast
Fallensteller können ja an sich nicht sterben, ich gehe also davon aus, dass sie entweder von einem anderen Objekt überdeckt werden, also ihr platz geklaut wird, oder dass sie aus dem Spielfeld herausgehen. Obwohl ich eigentlich beides versucht habe im code zu verhindern.
Dann erklärt sich mir aber nicht, wie wieder neue Fallensteller dazu kommen.
Alles sehr merkwürdig in meinen Augen:confused:
 
D

David Nienhaus

Gast
Ich habe das Problem gefunden.

Ich musste die Methode platziere() folgendermaßen anpassen:

Java:
public void platziere(Akteur akteur)
    {
        Position position = akteur.gibPosition();
        if (akteur instanceof Fallensteller && !(feld[position.gibZeile()][position.gibSpalte()] instanceof Fallensteller)){
            feld[position.gibZeile()][position.gibSpalte()] = akteur;
        }
        else if (!(feld[position.gibZeile()][position.gibSpalte()] instanceof Fallensteller)) {
            feld[position.gibZeile()][position.gibSpalte()] = akteur;
        }
    }
 

Student110

Neues Mitglied
Hallo liebes Forum!
Ich muss das Gleiche Programm schreiben und bin fast fertig. Das einzige was noch nicht funktioniert sind die Fallen.
Laut Simulation tappt niemals ein Tier in meine Falle. @David Nienhaus: Kannst du dein Programm vielleicht einmal posten? :D
Freundliche Grüße...
 

Neue Themen


Oben