# Textbasiertes Spiel - Umsetzungsfrage & Schleifen Problem



## Ion (30. Mai 2015)

Ich bin grade dabei ein Textbasiertes Spiel (Rollenspiel sollte man warscheinlich sagen oder "Adventure") zu erstellen und ich bin dabei auf ein paar Umsetzungsprobleme gestoßen und auch sonst will ich einfach einen guten konzeptionellen Weg gehen. 

Ich bin auch noch nicht so lange im OOP Bereich aber ich wollte unbedingt mal ein paar kleiner Projekte für mich selbst erledigen.

Zudem habe ich da auch noch so ein kleines Problem mit einer Schleife und ich finde da den Fehler irgendwie nicht.

Erst einmal zu den konzeptionellen Fragen:
1. Ich bin grade an einer "Monster" oder Kreatur Klasse dran und ich habe das ganze jetzt so geregelt, das ein Monster in einem Raum existieren darf aber nicht mehr. Wenn man mehrere Monster in einem Raum haben wollte, müsste man diese ja einfach nur in einer Hashmap oder einer andere Collection (im Raum) speichern, oder?

2. 

2.1 Ich habe jetzt eine Klasse Lebewesen erstellt und eine Klasse Spieler und eine Klasse Monster erben grade davon. Die Klasse Lebewesen ist abstrakt. 
Das sieht bei mir derzeit so aus:


```
public abstract class Lebewesen
{
    private String name;  
    private int schaden;
    private int lebenspunkte;    
    
    private Raum aktuellerRaum;
    
    /**
     * Konstruktor der Klasse Lebewesen
     */
    public Lebewesen(String name, int lebenspunkte, int schaden, Raum startRaum)
    {
        this.name = name;
        this.schaden = schaden;
        this.lebenspunkte = lebenspunkte;
        
        this.aktuellerRaum = startRaum;
    }
     
    /**
     * @return Gibt die Lebenspunkte des Lebewesens zurück.
     */
    public int getLebenspunkte() 
    {
        return lebenspunkte;
    }
    
    /**
     * @return Gibt den Schaden des Lebewesens zurück.
     */
    public int getSchaden() 
    {
        return schaden;
    }
    
    /**
     * @return Gibt den Raum zurück, in dem sich das Lebewesen grade befindet.
     */
    public Raum getAktuellerRaum() 
    {
        return aktuellerRaum;
    }
    
    /**
     * Setter für den Raum des Lebewesens
     */
    public void setAktuellerRaum(Raum raum)
    {
        aktuellerRaum = raum;
    }
    
    /**
     * Setter für die Lebenspunkte des Lebewesens
     */
    public void setLebenspunkte(int lebenspunkte)
    {
        this.lebenspunkte = lebenspunkte;
    }
    
    /**
     * Setter für den Schaden des Lebewesens
     */
    public void getSchaden(int schaden) 
    {
        this.schaden = schaden;
    }
    
    /**
     * @return Gibt den "Status" des Lebewesens wieder, also ob es tot oder lebendig ist.
     * Gibt 'true' zurück, wenn das Lebewesen tot ist, andernfalls 'false'.
     */
    public abstract boolean istTot(); 
        
    public void attack(Lebewesen lebewesen) 
    {
        int damage = Math.max(0, this.getSchaden());
        int health = lebewesen.getLebenspunkte() - damage;
    
        System.out.println(this.getName() + "'s angriff hat " + damage + " Schaden angerichtet!\n");
        System.out.println(lebewesen.getName() + "'s Lebenspunkte: " + health);
    
        lebewesen.setLebenspunkte(health);     
    }
}
```

und dann ein Monster:


```
import java.util.Iterator;

public class Monster extends Lebewesen
{
    public Monster(String name, int lebenspunkte, int schaden, Raum raum)
    {
        super(name, lebenspunkte, schaden, raum);
        raum.setMonster(this);
    }
    
    public String gibBeschreibung() 
    {       
        String returnString = getAktuellerRaum().gibLangeBeschreibung();
        returnString += "Lebenspunkte " + getLebenspunkte();
        return returnString;
    }
    
    public boolean istTot() 
    {
        if(getLebenspunkte() < 1)
            return true;
            
        return false;
    } 
   
    public boolean kannSpielerVerfolgen() 
    {
        if(Math.random() < 0.2) // 20% chance
            return true;

        return false;
    }
}
```

Ist das so ein guter Ansatz? Da der Spieler ja auch noch einige zusätzliche Werte hat, wie evtl. Hunger oder Durst habe ich die Methode istTot nur als abstract gekennzeichnet und ohne eine Implementierung.

2.2 Wie man sieht habe ich ja auch noch eine Methode kannSpielerVerfolgen und dazu hätte ich auch noch eine Frage. In meiner "Spiel" Klasse, also da wo das Spiel initialisiert wird etc.  rufe ich dann bei der Eingabe von angriff eine Methode kampf auf. Da gibt es dann aber auch immer ein Problem. Ich setze ja jetzt bspw. so eigentlich immer voraus, das der Spieler zuerst angreift und dem ist ja auch so aber müsste man nicht auch noch vor monster.attack() dann prüfen, ob das monster nicht evtl. schon vom Spieler angegriffen wurde? Ansonsten würde das tote Monster den Spieler ja auch wieder angreifen können?


```
private void kampf(Befehl befehl)
{
    boolean fliehen = false;
    
    Monster monster = spieler.getAktuellerRaum().getMonster();        
    do
    {
        spieler.attack(monster);
        monster.attack(spieler); 
        
        System.out.println("Weiterkämpfen? Dann geben Sie bitte 'weiter' ein.");
        
        parser.getEingabeBefehl();  
        String befehlswort = befehl.gibEingabeBefehl();
        if (befehlswort.equals("weiter")) 
        {
            
        }
        else if(befehlswort.equals("fliehen"))
        {
            spieler.getAktuellerRaum().setZufaelligerFluchtraum(spieler);
            
            if(monster.kannSpielerVerfolgen())
            {
                monster.attack(spieler);
                System.out.println("Sie konnten leider nicht entkommen. Das Monster hat Sie zudem angegriffen!");
                System.out.println("Was möchten Sie machen? Weiterkämpfen oder weiter versuchen zu fliehen?");
            }
            else
            {
                fliehen = true;
                return;
            }                
        }
        
        System.out.println("Loop Spieler LP: " + spieler.getLebenspunkte());
        System.out.println("Loop Monster LP: " + monster.getLebenspunkte());
        
        System.out.println("Loop Spieler Tot: " + spieler.istTot());
        System.out.println("Loop Monster Tot: " + monster.istTot());
    }
    while ((!spieler.istTot() && !monster.istTot()) && !fliehen);
    
    System.out.println("Spieler LP: " + spieler.getLebenspunkte());
    System.out.println("Monster LP: " + monster.getLebenspunkte());
    
    if (!spieler.istTot())
        System.out.println("Sie haben den Kampf gewonnen!");
    else if (!monster.istTot())
        System.out.println("Sie haben den Kampf verloren!");
}
```

In der Methode habe ich auch noch zwei zusätzliche Probleme und da ist auch das Schleifenproblem aber wie gesagt, erst einmal das konzeptionelle.

2.3 Da ich ja wie schon in 2.2 gesagt immer mehr oder weniger voraussetze, das der Spieler zuerst angreift bin ich auf ein Problem gestoßen. Ich wollte das jetzt kurz vor dem Ausgang und auch in ein paar anderen Räumen so machen, das die Monster eine Chance von 40% oder so haben, den Spieler zu "sehen" und ihn dann anzugreifen. Dazu müsste aber ja jetzt natürlich das Monster zuerst angreifen. 

Ich habe das jetzt so gelöst, das ich in der Methode die auch in der Klasse Spiel ist, prüfe, ob es sich dabei um einen speziellen Raum handelt, da wo der Spieler bspw. auf jeden Fall gesehen werden soll. Das befindet sich jetzt in der Methode, die aufgerufen wird, wenn der Spieler weitergeht:


```
private void wechsleRaum(Befehl befehl) 
{
    Raum aktuellerRaum = spieler.getAktuellerRaum();
    
    ....

    if (naechsterRaum == null) 
    {
        System.out.println("\nIn dieser Richtung befindet sich kein Raum!");
    }
    else if(spieler.weitergehen(richtung)) 
    {
        aktuellerRaum = naechsterRaum;
        System.out.println(aktuellerRaum.getBeschreibung());
        
        if(aktuellerRaum == vorAusgang)
        {
            monster.attack(spieler);
            System.out.println("Sie wurden von einem Monster angegriffen, was möchten Sie tun?");
        }
    }
}
```

Aber ist das wohl ein guter Weg oder gibt es da noch eine bessere Möglichkeit? Wie könnte ich das aber dann z.B auch noch allgemein halten, also das es in jedem Raum vielleicht auch unterschiedliche Chancen gibt, das der Spieler gseehen wird?

3.

3.1 Ich würde jetzt auch gerne spezielle Gegenstände erstellen, also bspw. sowas wie ein Schwert oder einen allgemeinen Gegenstand wie eine Wasserflasche oder dergleichen erstellen. Erst einmal habe ich auch dafür wieder eine Klase Gegenstand erstellt.

```
public class Gegenstand
{
    private String name;
    private String beschreibung;
    
    public Gegenstand(String name, String beschreibung)
    {
        this.name = name;
        this.beschreibung = beschreibung;
    }
    
    public String getName() {
        return name;
    }
    
    public String getBeschreibung() {
        return beschreibung;
    }
}
```

und dann, bspw. für das Wasser oder allgemein "trinkbare" Gegenstände eine Klasse "Trinkbar" erstellt. 


```
public class Trinkbar extends Gegenstand
{
    public Trinkbar(String name, String beschreibung)
    {
        super(name, beschreibung);
    }   

    /*
    public void trinken()
    {
        // Durst des Spielers holen und anschleißend mit dem stillendem Durst addieren und dann set aufrufen?
       // und anschließend den Gegenstand entfernen?
    }
    */
}
```

Da bräuchte man dann ja auch eigentlich nur noch ein Attribut, das beschreibt wie viele Durst oder dergleichen das Objekt still und dann noch eine Methode, die aufgerufen wird, wie z.B trinken() und da wird dann einfach der Durst des Spielers gesetzt aber aber wie sorge ich dafür, das wenn der Gegenstand Wasserflasche benutzt wird auch die Methode trinken aufgerufen wird? Müsste das dann auch in die Spiel Klasse?

3.2 Wenn ich jetzt auch beispielsweise auch noch ein Schwert oder eine Waffe mit magischen Fähigkeiten erstellen wollte, dann bräuchte man doch auch wieder eine neue Klasse aber würde man dafür auch wieder eine Klasse Waffe erst einmal erstellen oder sowas wie eine Klasse Magisch, die sich dann von Gegenstand ableitet und dann das Schwert von "Magisch"?

4. Analog dazu:
Wie würde man das bei Monstern machen, also wenn die auch noch eine Fähigkeit haben, dann würde ein Objekt von Monster ja eigentlich nicht mehr reichen oder? Dann müsste man ja schon ein Klasse von Monster ableiten, z.B ein Hexer? 

Wie geht man aber dann auch nachher sicher, das der Hexer dann auch seine Fähigkeit evtl. mal anwendet? Könnte man das auch wieder mit so einer Prozentualen Lösung machen und evtl. einem "Cooldown"?

Zu 3. & 4
Wie man es dann erreichen könnte das der Schaden etc. dann für kurze Zeit bei einer Schadensfähigkeit erhöht wird, wäre mir schon klar aber wie könnte eine Implementierung für einen Gifteffekt oder so aussehen? Der müsste dann ja beim Spieler implementiert sein, nehme ich mal an? Wenn man da mit Schaden/Zeit was machen müsste, wie würde man das dann machen? Mit einem Timer?

Bräuchte man dann eigentlich auch evtl. sogar noch eine Klasse Fähigkeit oder würde das eher zu den Monstern/Spielern bzw. den Gegenständen gehören?

So, das wäre auch das konzeptionelle. Ich habe da auch noch immer so ein paar Zuordnungsprobleme, wie man vielleicht auch sieht, also bspw. wo man dann auch nachher welche Methode verstaut.

Nun zu dem Schleifenproblem: (Ist bei 3 die Kampf Methode)

Wenn ich das Programm dann mal so laufen lasse, dann kriege ich diese Ausgabe:

```
> 
Loop Spieler LP: 40
Loop Monster LP: 60
Loop Spieler Tot: false
Loop Monster Tot: false
Tobias's angriff hat 10 schaden gemacht!

Höhlenwolf's Lebenspunkte: 50
Höhlenwolf's angriff hat 20 schaden gemacht!

Tobias's Lebenspunkte: 20
Weiterkämpfen? Dann geben Sie bitte 'weiter' ein.

> 
Loop Spieler LP: 20
Loop Monster LP: 50
Loop Spieler Tot: false
Loop Monster Tot: false
Tobias's angriff hat 10 schaden gemacht!

Höhlenwolf's Lebenspunkte: 40
Höhlenwolf's angriff hat 20 schaden gemacht!

Tobias's Lebenspunkte: 0
Weiterkämpfen? Dann geben Sie bitte 'weiter' ein.

> 
Loop Spieler LP: 0
Loop Monster LP: 40
Loop Spieler Tot: true
Loop Monster Tot: false
Spieler LP: 0
Monster LP: 40

Sie haben den Kampf verloren!
```

Ich habe jetzt auch mal einige Teile entfernt, damit das ganze hier nicht zu überladen wird aber wie man sieht, läuft die Schleife einmal zu viel aber warum? Ich muss, obwohl der Spieler "Tobias" ja oben schon tot ist, trotzdem noch einmal eine Eingabe machen aber wieso? Der Spieler ist ja, wie man oben sieht tot? (0 Lebenspunkte).

Wieso wird die Schleife dann trotzdem noch einmal ausgeführt oder bin ich grade einfach nur zu müde? Irgendwie finde ich den Fehler nicht ...

Puuuh .. das wärs dann auch. Danke schon einmal für jede Hilfe und jeden Ratschlag.


----------



## strußi (30. Mai 2015)

do ist eine fußgesteuerte schleife, läuft erst und schaut dann nach. while vlt die bessere wahl


----------



## InfectedBytes (30. Mai 2015)

1. jo, einfach alle monster in eine collection und fertig.

2.1. Grundsätzlich schon ein recht guter Ansatz.
2.2. Genau, du müsstest vorher noch prüfen ob das Monster überhaupt noch lebt. 
2.3. Hierfür gibts natürlich unmengen an möglichkeiten, eine wäre z.b. die Monster (oder auch den Raum) um eine Methode onEnter(Spieler spieler) zu erweitern. 
Diese methode wird dann immer automatisch aufgerufen, wenn der Spieler den aktuellen Raum betritt. So kann nun jeder Raum oder jedes Monster selbst entscheiden was gemacht wird, wenn der Spieler ankommt.

3.1. Du könntest dem allgemeinen Gegenstand eine use() methode geben, die aufgerufen wird, wenn der gegenstand benutzt werden soll. dein trinkbares würde dort dann das Wasser auffüllen, während deine Nahrung den Hunger stillt. Potions könnten heilen, etc. 
Bei Schwerten könnte diese Funktion genutzt werden, um sie auszurüsten. 
Alternativ könntest du auch ein entity component framework nutzen, dies ist aber vielleicht etwas für spätere projekte^^

3.2. Hierfür würde sich tatsächlich ein component framework anbieten. Die Idee ist dabei ein "allgemeines" Objekt mit Komponenten auszustatten. Eine Schwert hätte dann z.b. die Komponente "Waffe" und ggf die Komponente "Magisch". Dies kann man ebenso auf 3.1 anwenden und so z.b. die Komponente "Nahrung" hinzufügen. 
Die einzelnen Komponenten enthalten nichts weiter als Attribute, wie z.b. Stärke, etc. 
Des Weiteren hat man EntitySysteme, welche die Logik bereitstellen um Objekte und ihre Komponenten zu verarbeiten. 
Falls du tatsächlich den Komponentenweg gehen willst, würde ich dir empfehlen dir mal konkrete Tutorials anzuschauen. 
Für Java finde ich das Ashley Framework ziemlich gut.

4. Entweder wie du bereits sagt weiter vererben (ggf. etwas unschön) oder auch hier komponenten
Du könntest jedem Monster eine Liste an potentiellen Aktionen mitgeben und diese nacheinander abarbeiten oder per zufall eien der aktionen wählen. Dein Hexer könnte nun die folgenden Aktionen haben: MagieAngriff, StabAngriff, Heilung
Aus diesen könntest du dann immer zufällig eine Aktion auswählen.

3&4 Dafür würde es sich anbieten der Lebewesenklasse eine liste an aktiven effekten mitzugeben. Wenn ein Lebewesen nun vergiftet wird, wird eben ein GiftObjekt dieser Liste hinzugefügt. 
Die Liste wird dann immer wieder abgelaufen und jeder einzelne Effekt wird angewendet. Dabei kann natürlich die restliche Wirkzeit reduziert werden und falls diese auf 0 sinkt, kann der Effekt entfernt werden.


----------



## Ion (30. Mai 2015)

@strußi
Ja aber die Schleife soll ja wenigstens einmal ausgeführt werden. Auch wenn ich dann die while Schleife benutze, ändert sich nichts. Irgendwie sehe ich da aber keinen Fehler drin.

```
while ((!spieler.istTot() && !monster.istTot()) && !fliehen)
{
    // ....
}
```

Zu 2.2 Wäre denn da evtl. auch ein guter Ansatz, das man das in die Methode des Lebewens integriert, also so: 

```
public void attack(Lebewesen lebewesen) 
{
    if(!this.istTot())
    {
        int damage = Math.max(0, this.getSchaden());
        int health = lebewesen.getLebenspunkte() - damage;
    
        System.out.println(this.getName() + "'s angriff hat " + damage + " schaden gemacht!\n");
        System.out.println(lebewesen.getName() + "'s Lebenspunkte: " + health);
    
        lebewesen.setLebenspunkte(health);     
    }
}
```

Ansonsten müsste man das ja auch evtl. immer an vielen verschiedenen Stellen überprüfen, bspw. auch wenn es mehrere Attacken oder was weiß ich gibt? 

Zu 2.3:
Würde das dann aber nicht eigentlich eher in die Klasse des Lebewesens, also in dem Fall in das Monster gehören oder wäre das auch durchaus okay, das in die Raum Klasse zu packen? Natürlich würden sicherlich beide Methoden funktionieren aber müsste das nicht eigentlich in die Monster Klasse?

Zu 3.1
Hmm ..stimmt natürlich. Daran hatte ich in dem Moment gar nicht gedacht. Der Gegenstand sollte dann natürlich auch schon erst zu der Ausrüstung hinzugefügt werden und nicht nur zum Inventar. Allerdings bräuchte man dann aber doch auch wieder eine extra Klasse, also Waffe bspw. oder? Zudem muss der Spieler dann ja auch noch um eine Collection oder zumindest Variablen erweitert werden, die sagen, welche "Ausrüstrungsgenstände" er grade aus dem Inventar benutzt?

Also so:

```
public class Player {
    private Ruestung ruestung;
    private Waffe waffen;

    public Ruestung getRuestung() {
        return ruestung;
    }

    public Waffe getWaffe() {
        return waffe;
    }

    public void setWaffe(Waffe waffe) {
        this.waffe = waffe;
    }

    public void setRuestung(Ruestung ruestung) {
        this.ruestung = ruestung;
    }
}
```

Wobei das glaube ich doch nicht mit einer Collection funkionieren würde? 

Zu 3.2:
Aber eine Komponente ist dann schon wieder eine Klasse. richtig? Werden diese Komponenten dann in einer Collection gesammelt oder wie funktioniert das?

Zu 4;
Nette Idee. 
Ich denke, das ich das dann so machen werde:

Schritt 1: Prozentuale Chance, dass das Monster den Spieler sieht in die Monster Klasse einfügen. 
Schritt 2: Falls der Spieler gesehen wurde, wird eine zufaelligeAktion ausgeführt. Das ist dann eine Methode, die sich in der Klasse Hexer befinden würde, also waehleZufaelligenAngriff() oder so ähnlich.
Schritt 3: Die zufaellig gewählte Methode dann aufrufen.

Hört sich das gut an?
Nur warum ist das ggf. etwas unschön? Könntest du das evtl. ein wenig näher erläutern? Warum ist das gegebenfalls etwas unschön?

Zu 3 & 4:
Aber wie sorgt man dafür, das diese Effekte dann auch immer abgearbeitet werden? Wie könnte man so eine Implementierung machen? Dann bräuchte man ja auch wieder noch eine Klasse für Effekte und auch noch eine extra Klasse für ein Gift oder reicht dafür dann immer jeweils ein Objekt vom Typ Effekt? 


```
public class Effekt
{
    enum Effekt {
        Schaden,
        Stun,
        Gift
    }
    
    public int berechneSchaden(int basisSchaden)
    {
        int schaden = basisSchaden;

        if (spieler.getEffekte().contains(Effekt.Stun)) {
            damage = 0;
        }
        ....
       
        return damage;
    }
}
```

und dann dem Spieler eine List anheften?

```
private List<Effekt> effekte = new ArrayList<>();
```


----------



## InfectedBytes (30. Mai 2015)

2.2. jo, kann man machen

2.3. klar, ob das monster angreifen soll oder nicht, sollte in den code des monsters rein. Aber häufig macht es auch sinn, den Raum eine aktion starten zu lassen. Z.b. wenn der Raum mit Wasser geflutet werden soll oder so.

3.1. Ich würde dem Spieler halt eine Liste mit allen Gegenständen geben die er besitzt, Ausrüstbare Gegenstände kannst du, wenn du willst wie von dir beschrieben nochmal extra speichern. 

3.2. Im Grunde kümmert sich das Framework um sowas. Jeder Gegenstand ist dann nur noch eine Entity, welche intern eine Liste von Komponenten verwaltet. Jede einzelne Komponente ist dabei ein Objekt einer Klasse, welches (im Allgemeinen) nur Attribute enthält und keine logik.

4. ist ok.
Vererbung kann in solchen Fällen halt etwas unschön werden, betrachte dazu folgendes Beispiel:
Gegnertyp Hexer erbt von Monster, Gegnertyp Dämon erbt ebenfalls von Monster. Nun möchtest du aber zusätzlich noch dämonische Hexer haben, von welcher Klasse erbt dieser? Eigentlich müsste er sowohl von Hexer als auch Dämon erben, da dies jedoch nicht geht, muss man leider unschöne umwege gehen.

3&4. Kommt ganz drauf an. Im Grunde reicht eine Klasse Effekt. Falls du aber sehr verschiedene Arten von Effekten haben willst, wäre es sinnvoller mehrere Klassen zu nutzen. Denn der Effekt "Gift" ist nun sehr verschieden von dem Effekt "Zeit verlangsamen"


----------



## Ion (31. Mai 2015)

Zu 3,1:
Ja, ich habe schon eine Liste mit allen Gegenständen, die der Spieler besitzen kann. Das ist soweit schon fertig aber es geht mir da ja jetzt auch um spezielle Gegenstände.

Für die Ausrüstungsgegenstände reicht doch dann aber auch jeweils eine Variable? Man kann ja schließlich auch nur ein Schwert tragen oder eine Rüstung haben, also keine Collection dafür?

Zu 3.2:
Werde ich mir mal anschauen aber das kann ich mir ja danach auch noch angucken und das dann mal so umsetzen. Jetzt wollte ich aber sowieso erst einmal ohne Frameworks arbeiten.

Zu 3&4:
Mhm .. aber würdest du denn dann trotzdem noch eine abstrakte Oberklasse Effekt oder so definieren? Das Projekt war aber sowieso erst einmal nicht als zu tief gedacht. 

Aber wie implementiert man das denn, das diese Effekte dann auch nebenbei abgearbeitet werden? Muss man da mit Threads arbeiten oder wie soll sowas dann laufen? Irgendwie kann ich mir da die Vorgehensweise nicht so recht vorstellen.

Ich hätte auch noch einmal eine zusätzliche Frage zu einer Umsetzung.
Ich will jetzt evtl. auch sowas wie eine Falle in einem Raum aber sollte man das lieber so machen, das es dann einen "Fallenraum" (eine Abgeleitete Klasse von Raum) oder so ähnlich gibt oder das es weiterhin eine Klasse Raum gibt und eine Klasse "Falle"?

Zudem bin ich da dann grad noch haken, wenn der Raum gewechselt werden soll. Derzeit befindet sich das mit der Initialisierung in der Klasse Spiel, also auch dort, wo das Spiel initialisert wird etc.

```
private void wechsleRaum(Befehl befehl) 
{
    Raum aktuellerRaum = spieler.getAktuellerRaum();
    
    if(!befehl.hatZweitesWort()) 
    {
        // Gibt es kein zweites Wort, wissen wir nicht, wohin...
        System.out.println("\n In welche Richtung möchten Sie gehen?");
        return;
    }

    String richtung = befehl.gibZweitesWort();
    Raum naechsterRaum = aktuellerRaum.getAusgang(richtung); // Versuchen, den Raum zu verlassen

    if (naechsterRaum == null) 
    {
        System.out.println("\nIn dieser Richtung befindet sich kein Raum!");
    }
    else if(spieler.weitergehen(richtung)) 
    {
        aktuellerRaum = naechsterRaum;
        System.out.println(aktuellerRaum.getBeschreibung());
        
        if(aktuellerRaum == vorAusgang)
        {
            boss.greifeAn(spieler);
            System.out.println("Sie wurden von einem großen Wolf angegriffen!");
        }
    }
}
```

Sollte die Überprüfung mit dem Raum sich denn auch da in der Klasse befinden oder sollte die eigentlich nicht da sein oder passt das so wohl? Nur wüsste ich dann auch nicht, wie ich dann in dem Kontext bspw. überprüfen soll, ob der Raum ebend der Ausgang oder vor dem Ausgang der Raum ist oder evtl. sogar ein Fallenraum? ;(

Das hier ist dann die Methode, mit dem der Spieler dann den Raum wechselt:

```
public boolean weitergehen(String richtung) 
{
    Raum naechsterRaum = getAktuellerRaum().getAusgang(richtung);
    if(naechsterRaum != null) 
    {
        raumBetreten(naechsterRaum);
        return true;
    } 
    else 
    {
        return false;
    }
}
```


```
private void raumBetreten(Raum raum) 
{
    setAktuellerRaum(raum);
}
```


----------



## InfectedBytes (31. Mai 2015)

3.1. jo, in dem fall reicht es

3&4. wenn du wirklich nicht mehr als sowas wie gift/heil effekte brauchst, dann ist keine abstrakte Effekt klasse nötig. 
Es kommt drauf an wie dein Projekt allgemein konzipiert ist. 
Du kannst das ganze natürlich in einem Thread auslagern, aber da dein Textadventure bisher ja immer nur nach der eingabe des nutzers etwas macht, würde ich die effekte auch immer nach der eingabe eines nutzers abarbeiten. 
Grundlegend könnte deine Mainloop ungefähr so aussehen:

```
while(spieler.isAlive()) {
  string input = scanner.readLine();
  verarbeiteInput(input);
  for(Lebewesen wesen : aktuellerRaum) {
    wesen.verarbeiteEffekte();
  }
}
```

Zu den Fallen:
Eine gute Variante ist es, dem Raum eine liste an Gegenständen zu geben. Diese Gegenstände können natürlich einerseits "normale" Gegenstände sein, welche vom Benutzer aufgehoben werden können und zum anderen auch Gegenstände welche tatsächlich dem Raum gehören, wie z.b. Fallen. Wenn der Spieler einen Raum betritt, rufst du die onEnter Methode des Raums auf, welche wiederum alle Gegenstände im Raum durchgeht und deren onEnter aufruft. 
Fallen können dann ausgelöst werden und andere Gegenstände können auf wunsch ebenfalls aktionen ausführen. Z.b. kann ein Questgegenstand anfangen zu leuchten, etc. 

Zum Raumwechsel:
Im Grunde würde ich einen Schritt weitergehen und dem Lebewesen die Möglichkeit geben den Raum zu wechseln, dadurch können deine Monster auch umherwandern. 

```
public class Lebewesen {
  //...
  public bool wechselRaum(Raum ziel) {
    //raum wechseln
    //wenn der Raum nicht betreten werden konnte (z.b. weil verschlosssen):
    if(success)
      return false;
    //Ansonsten
    ziel.onEnter(this);//dieses Lebewesen hat den raum betreten
    return true;
  }
}
```
Wo auch immer du deine Eingabe auswertest, kannst du dann auf deinem Spieler die Methode wechselRaum aufrufen.

Die Sache mit dem Raum vor dem letzten Raum, würde ich lieber etwas allgemeiner fassen. Denn warum soll immer der vorletzte Raum was besonderes sein? Lass es den Raum lieber selbst entscheiden, ob er wichtig ist oder nicht. 
D.h. ob nun das Monster angreift oder nicht, wird einfach vom jeweiligen Raum selbst geklärt. Z.b. indem du bei der Erzeugung des Raums einfach einen boolean mitgibst, der sagt ob die Monster zuerst angreifen sollen.


----------



## Ion (2. Jun 2015)

Jo, stimmt. Das würde mit einem Thread eh glaube ich nicht gut gehen. Da ist ja auch keine zeitliche Begrenzung oder so mit dabei, also kann man da auch irgendwie nicht sagen: Mache nach 10 sek 3 schaden oder was weiß ich.

Ob aber eine Falle jetzt unbedingt ein Gegenstand ist? Mhm ... 
Könnte man nicht auch einfach einen Raum "Fallenraum" von Raum ableiten und da die onEnter Methode aufrufen, also z.B so?

```
public void OnEnter(int aktuelleLebenspunkte)
{
    int schaden = Math.max(0, this.schaden);
    int lebenspunkte = aktuelleLebenspunkte - schaden;

    System.out.println("Die Falle hat " + schaden + " Schaden gemacht!\n");
    System.out.println("Lebenspunkte: " + lebenspunkte);  
}
```

Eine Falle kann ja auch in die Wände oder so integriert sein, wie z.B eine Pfeilfalle oder irgendwas dergleichen? Sollte man da dann eigentlich auch System.out.println() benutzen oder gehört das eher in die Spiel Klasse.

Zum Raumwechsel: 
Okay, das mit dem boolean für eine Chance auf einem Angriff beim Raumeintritt finde ich sinnvoll aber wie sieht das dann mit der Raumüberprüfung aus? Gehört die Überprüfung, ob der Spieler den Ausgang erreicht hat in die Spiel Klasse oder in die Raum Klasse? 

```
boolean beendet = false;
while(!beendet) 
{
    if(spieler.istTot())
    {
        verlorenstextAusgeben();
        beendet = true;
    }
    if(spieler.getAktuellerRaum() == ausgang) 
    {
        gewonnenstextAusgeben();
        beendet = true;
    }
}
```

Es könnte ja auch noch andere besondere Räume geben oder eine Chance auf eine Fallenaktivierung, weil die Falle evtl. beschädigt ist oder so?

Noch einmal was anderes:
Ich würde auch gerne noch magische Gegenstände erstellen. Da wäre es dann ja eigentlich auch so wie bei dem Lebewesen oder? Eine Klasse Gegenstand habe ich ja schon und dann eine Unterklasse Magisch erstellen und davon dann wieder eine, bspw. ein Heiltrank, richtig?

Und dann die benutzen Methode für den Heiltrank (eigene Klasse) aufrufen. So einen Gegenstand "Heiltrank" würde ich nämlich wirklich wohl gerne erstellen aber wie unterscheidet man denn da nachher? 
Wenn ich jetzt auch bspw. einen Wasser Gegenstand benutzen will, habe ich das hier:

```
private void gegenstandTrinken(Befehl befehl) 
{
    if(!befehl.hatZweitesWort()) 
    {
        System.out.println("Welchen Gegenstand möchten Sie trinken?");
        return;
    }
    
    String gegenstand = befehl.gibZweitesWort();
    if(spieler.gegenstandTrinken(gegenstand))
    {
        System.out.println("Der Gegensntad " + gegenstand + " kann nicht getrunken werden!");            
    } 
    else 
    {
        System.out.println("Sie haben den " + gegenstand + " getrunken.");
    }
}
```

Aber man müsste das dann ja irgendwie ja auch allgemein halten, ansonsten wäre das ja nachher eine ziemliche Code Dupliuierung? Müsste man dann erst den Gegenstand des Spielers aus dem Inventar holen, dann die benutzen Methode aufrufen und anschließend den Gegenstand aus dem Inventar entfernen (oder erst entfernen), also so? (Pseudo-Code)

```
private void gegenstandBenutzen(Befehl befehl) 
{
    if(!befehl.hatZweitesWort()) 
    {
        System.out.println("Welchen Gegenstand möchten Sie benutzen?");
        return;
    }
    
    String gegenstand = befehl.gibZweitesWort();
    Gegenstand gegenstand = spieler.gegenstandEntfernen(gegenstand);
    gegenstand.benutze();
}
```

Die Methode gegenstandEntfernen des Spielers gibt nämlich den gelöschten Gegenstand zurück aber wie kann ich dann nachher jeweils eine passende Meldung rausgeben? Die Methode benutze() sollte ja warscheinlich eher einen Bool zurückgeben aber ich will ja nachher bspw. noch sagen. "Sie haben ein Wasser getrunken" oder "Sie haben einen Heiltrank benutzt", wie macht man das?

Bräuchte ich nicht auch noch für die benutzen Methode des Heiltranks  die Spielerintanz, also um die Lebenspunkte zu holen und diese zu setzen, also so?

```
public void benutze()
{
    int lebenspunkte = spieler.getLebenspunkte();
    lebenspunkte += zusaetzlicheLebenspunkte;
    spieler.setLebenspunkte(lebenspunkte);
}
```

So sollte doch dann die benutzen Methode des Heiltranks aussehen oder müsste man das noch mehr aufteilen? Nur wie komme ich da an die Lebenspunkte ran?

Solche konzeptionellen Ansätze und was dann nachher wo hingehört ist mir irgendwie auch noch nicht so 100%ig klar aber wie kann man da möglichst sicher sein, das man das gut implementiert hat? -.-


----------



## InfectedBytes (2. Jun 2015)

Natürlich kannst du den Fallenraum einfach von Raum erben lassen, aber was wenn du dann einen weiteren Raum haben willst, der eine Falle enthält und einen Heilbrunnen? Wovon erbt der Raum dann? Von FallenRaum oder von HeilRaum? 
Im Grunde sollte der Raum allgemein gehalten werden und alle Besonderheit werden nur in einer Liste gemanaged. Anstatt Fallen als Gegenstände des Raumes zu betrachten, kannst du natürlich auch einfach jedem Raum eine Liste an "Events" geben, die beim eintreten stattfinden. 

Was meinst du mit "System.out.println() oder Spielklasse"? Ich vermute mal, dass du wissen willst ob das System.out.println in den Raum/die Falle oder in die Spielklasse soll: Das sollte definitiv in den entsprechenden Raum / die Falle. Denn wenn du jedes kleine Sonderverhalten in die Spielklasse tust, hast du sehr schnell eine gigantische hauptmethode, die einfach alles macht und unmöglich zu durchblicken ist. Außerdem ist die Falle nunmal eine besonderheit des Raums, also sollte sie auch in diesen rein.

Raumwechsel:
Da der Zielraum doch schon etwas wirklich sehr besonderes ist, kannst du ihn auch in der Spielklasse überprüfen. 
Aber mit der gleichen Begründung wie eben, ist es vielleicht nicht unbedingt die beste Wahl. 
Und richtig, es kann ja noch weitere besondere Räume geben, deswegen sollte die entsprechende Logik nicht komplett in die Spielklasse, sondern in die Klasse, welche es "auslöst". Also z.B. der entsprechende Raum selbst.

Magischer Gegenstand: 
Ich glaube du willst für jeden Gegenstand eine eigene Klasse schreiben, aber im Grunde sind die meisten Gegenstände ja ziemlich ähnlich:

```
//der Einfachheit halber verzichte ich mal auch getter/setter
public class UsableItem {
  private String name;
  private String description;
  private boolean magic;
  private int healthBoni;
  private int manaBoni;
  public UsableItem(....) { ... }
  public void use() {
    System.out.println("Du benutzt " + name);
    spieler.addHealth(healthBoni);
  }
}

//Dein Heiltrank könnte dann so erstellt werden:
UsableItem heiltrank = new UsableItem("Heiltrank", "Ein rot leuchtender Heiltrank", false, 10, 0);
//eine magische mana potion:
UsableItem manaPotion = new UsableItem("ManaPotion", "Eine magische Manapotion", true, 0, 10);
//etc.
```

In der Spielklasse sollte sich gar nichts ändern, da die ja nichts weiter macht, als die use-Methode des Gegenstandes aufzurufen. 
Ob du den Gegenstand erst benutzt oder erst entfernst ist in deinem Fall wahrscheinlich egal. 
Wichtig ist nur, dass du den Gegenstand nur entfernst, wenn er auch wirklich benutzt wurde. Falls du nämlich etwas benutzen willst, was nicht benutzt werden kann, dann sollte dieser Gegenstand natürlich nicht verschwinden. 
Die passende Meldung könntest du als Parameter mitgeben, also neben Name, beschreibung, etc. auch noch die Meldung die ausgegeben wird, wenn der Gegenstand benutzt wird. 

Genau die Spielerinstanz brauchst du schon. Wobei ich lieber allgemeiner sein würde und ein Lebewesen objekt nutzen würde, denn dann können ggf. auch gegner tränke trinken. 
Dafür bieten sich zwei Wege ganz gut an, einerseits könntest du im Gegenstand speichern, wem er gehört.
Andererseits kannst du auch die benutzen Methode um einen Parameter erweitern, der angibt von wem er benutzt wird. 


100%ig sicher sein kann man sich nie, aber mit genügend erfahrung bekommt ein gefühl dafür. 
Im Grunde musst du nur fleißig weiter arbeiten. Wenn du dann später größere Projekte angehst oder wenn du ein bestehendes Projekt erweitern willst, wirst du hier und da sehen was nicht so gut. 
Ansonsten kann es auch nicht schaden sich Bücher über Design Pattern bzw. AntiPattern anzusehen. Da kann man schon ein paar gute Ansätze lernen, bzw. man lernt auch was man besser nicht tun sollte und warum.


----------



## Ion (2. Jun 2015)

Mhm, da hast du natürlich Recht. Überzeugendes Argument mit den Räumen aber wie meinst du das, alle besonderen Räume (oder was meinst du mit "_Im Grunde sollte der Raum allgemein gehalten werden und alle Besonderheit werden nur in einer Liste gemanaged_." ) in einer Liste gespeichert werden sollen?

Was soll man denn dann damit machen? Ist die OnEnter Methode wie oben beschrieben nicht eigentlich schon ein Event? 
Ob das hier in die OnEnter Methode gehört, das meinte ich eigentlich:

```
public void OnEnter(int aktuelleLebenspunkte)
{
    int schaden = Math.max(0, this.schaden);
    int lebenspunkte = aktuelleLebenspunkte - schaden;
     
    System.out.println("Die Falle hat " + schaden + " Schaden gemacht!\n");
    System.out.println("Lebenspunkte: " + lebenspunkte);  
}[/JAVA ]

aber du sagtest ja, das man dann lieber die Methode auf den Rückgabewert String setzen sollte oder wie macht man das dann? Also so:
[code=Java]public String OnEnter(int aktuelleLebenspunkte)
{
    String rueckgabeString;

    int schaden = Math.max(0, this.schaden);
    int lebenspunkte = aktuelleLebenspunkte - schaden;
     
    rueckgabeString = "Die Falle hat " + schaden + " Schaden gemacht!\n";
    rueckgabeStirng += "Die Falle hat " + schaden + " Schaden gemacht!\n";
    return rueckgabeString;
```
}

So, in der Richtung oder gibt es da bessere Möglichkeiten, die man nutzen sollte / kann oder passt das so wohl?

Zu dem Raumwechsel:
Ja, das dachte ich mir auch schon aber wie kann ich dann diese besonderen Räume nachher überprüfen, also bspw. ob der Spieler jetzt den Ausgang erreicht hat oder nicht, wie mache ich das?

Ich habe ja in meiner Spielklasse dann die Raumvariablen erstellt:

```
private Raum eingang, ausgang ....;
```

und dann prüfe ich ja derzeit in der Hauptschleife des Spiels, ob es sich um den Ausgang handelt:

```
boolean beendet = false;
while(!beendet) 
{
    if(spieler.istTot())
    {
        verlorenstextAusgeben();
        beendet = true;
    }
    if(spieler.getAktuellerRaum() == ausgang) 
    {
        gewonnenstextAusgeben();
        beendet = true;
    }
}
```

aber wie kann ich das auslagern? Das sollte dann ja in die Raum Klasse, also das ich prüfe, ob es sich bei dem Raum um den Ausgang handelt aber wie kann ich diesen Teil dahin auslagern und wie prüfe ich dann, ob es sich um den Ausgang handelt?

Zu den Gegenständen:
Aber sollte man da wirklich nur eine Klasse für nutzen? So wie dein kleines Beispiel hat ja dann auch jeder Gegenstand eine Eigenschaft healthBoni, obwohl er diese ja dann eigentlich nie brauchen wird?
Wenn ich jetzt aber auch unterschiedliche Texte ausgeben will, wie schon oben beschrieben mit:
*"Sie haben eine Flasche Wasser getrunken" oder "Sie haben einen Heiltrank benutzt", wie macht man das?*

Meinstest du mit deiner Aussage, das ich dafür eine extra Objektvariable erzeuge und diese dann auch im Konstruktor des Gegenstandes initialisiere?

Bei dem Beispiel mit dem Gegenstand wird dann ja auch für jeden Gegenstand die addHealth Methode des Spielers aufgerufen aber bei einem Schwert etc. wird die dann ja auch (unnötigerweise) aufgerufen? 

Klar, wenn da dann 0 drinsteht ändert sich der Wert des Lebewesens ja nicht aber ist das so ein "guter" Weg? Kommt mir irgendwie komisch vor. Bei einem Schwert wäre das dann ja addDamage() und wenn da 0 drinsteht ändert sich ja dann auch nicht aber dann hat man ja für jeden Gegenstand immer auch Methoden drin, die eigentlich nichts machen? 

Das der Gegenstand nur enfternt werden soll, wenn er auch benutzbar ist, bzw. genutzt wurde ist mir schon klar. Das kriege ich auch wohl hin.  

Meinst du denn mit der Spielerinstanz, das diese bei jedem Aufruf der benutzen() Methode eines Gegenstandes mitgegeben werden soll? Erscheint mir irgendwie auch wieder ein wenig übertrieben? Oder muss man da dann irgendwie evtl. noch in der Spiel Klasse unterscheiden oder geht das dann so nicht?


Das man sich nie zu 100% sicher sein kann ist schon klar. Einige Sachen sind ja auch doch wirklich noch Ansichtssache oder man kann sie auf verschiedenen implementieren aber es gibt ja trotzdem sowas wie "schlecht" und "gut".

Ich bin mir auch oft bei manchen Methoden nicht einmal sicher, ob diese etwas zurückgeben sollen oder nicht oder ob eine Methode evtl. noch ein Paramter mehr braucht etc. Man kann man ja auch schließlich vieles mit void erledigen.


----------



## InfectedBytes (2. Jun 2015)

Mit den Events meinte ich eher sowas:

```
public interface Trigger {
	public void onEnter(Entity entity);
}
	
public class Falle implements Trigger {
	@Override
	public void onEnter(Entity entity) {
		entity.addHealth(-10);
	}
}

public class Goal implements Trigger {
	@Override
	public void onEnter(Entity entity) {
		//Spiel gewonnen!
	}
}

public class Room {
	private ArrayList<Trigger> onEnterEvents = new ArrayList<Trigger>();

	public void onEnter(Entity entity) {
		for (Trigger event : onEnterEvents) {
			event.onEnter(entity);
		}
	}
}
```
So kann dann ein Raum auch mehrere Fallen oder auch andere Events haben. Deinem letzten Raum kannst du so z.B. den Goal Trigger hinzufügen, welcher dafür sorgt, dass der Spieler tatsächlich gewonnen hat. Die Räume selber bleiben somit alle relativ simpel, da sie selbst quasi keine Logik haben, sondern nur ne Beschreibung + Events + Monster, Die Eigentliche Logik übernehmen dann die Events/Monster.

Das die Methode void ist, ist schon in Ordnung. Ein Rückgabewert wird eigentlich nicht benötigt^^


Der Beispielgegenstand oben war bereits eine der spezieller Klassen, welche z.b. für Nahrung, Potions, etc. gedacht war, sorry für dass missverständnis^^
Der Unterschiedliche Text kann wohl am einfachsten durch einen weiteren Parameter gelöst werden:

```
public class Item {
  private String useText;
  //...
  public void use(Lebewesen wesen) {
    System.out.println(useText);
    //...
  }
}
```

Das Lebewesen gebe ich hier mit, damit es erweiterbar ist. Denn falls du später vielleicht auch Monstern die Möglichkeit geben willst, Items zu benutzen, dann kannst du das so sehr leicht erreichen.


----------



## Ion (2. Jun 2015)

Ja, das mit dem Event war auch mehr so ein Witz, deswegen ja der Smiley. 

Wie würde man das denn aber ohne die Events machen? Wie kann ich denn nachher prüfen, ob es sich bei dem Raum, wie schon oben beschrieben um den Ausgang oder um raum x handelt? Selbst wenn man da irgendeine Methode schreibt, wie soll die aussehen?

Eine Rauminstanz übergeben geht ja auch nicht, denn welche soll ich mitgeben? Es gibt ja zig Räume ... Also, wie nachher prüfen, ob der Raum der Ausgang ist oder evtl. ein 2. Ausgang usw?

Zu den Gegenständen:
Also würdest du doch eine Klasse Magisch von Gegenstand erstellen und dann evtl. noch eine von Magisch, wie z.B ein Heiltrank oder eine Mantrank oder sowas in der Art? Damit hast du mich jetzt echt aus dem Konzept gebracht .. 

Du hast da ja aber jetzt schon eine Abgeleitete Klasse estelltt, also ein Gegenstand der "benutzbar" ist. Du hast da ja aber sowohl healthBoni, als auch manaBoni, also würde dann ja auch in der Methode use addHealth, als auch addMana aufgerufen werden müssen? (confused) oder sollten da jetzt, wie ich das meinte eine Oberklasse Magisch sein und dann ein Manatrank und ein Heiltrank oder so?

Wenn man dann aber weiter die benutzen Methode allgemein halten will, dann braucht man ja auch noch eine Vergleichsmethode oder? Die müsste dann ja prüfen, ob es sich bei dem Gegenstand um einen "normalen" handelt oder bspw. um einen Magischen?


----------



## InfectedBytes (2. Jun 2015)

Eine einfache Möglichkeit wäre den Raum um einen boolean zu erweitern der aussagt ob es ein Ausgang ist oder nicht. 
Bei "normalen" Räumen ist dieser false und bei Ausgängen ist er true.

Das mit den Gegenständen kann man halt auf echt viele Arten bewerkstelligen, da gibt es wohl keinen idealen Weg. 
Am besten betrachtet man dafür erstmal was man alles an Gegenständen haben will und welche Gemeinsamkeiten sie haben. 
Angenommen du hast Waffen/Rüstungen/Tränke. Da könnten man sagen das jede davon eine use-Methode hat, wobei diese bei einer Waffe dazu führt, das sie geführt wird, eine Rüstung wird angezogen und ein Trank getrunken. 
Da könnte man dann eine abstrakte Klasse Item machen, welche sowas wie Name, Beschreibung und eben die use-Methode hat. 
Die Unterklassen Waffe/Rüstung/Trank können dann ggf noch sachen hinzufügen und auf jedenfall die use Methode überschreiben.
Der Trank kann dann halt direkt Health und Mana verbessern oder du seperierst hier weiter. 

Die Frage ist halt warum du nochmal in magisch und nicht magisch aufteilen willst? 
Was ist denn der große Unterschied? Kannst du nicht einfach einen boolean nutzen der sagt ob der Gegenstand magisch ist oder nicht? 
Das würde halt vieles einfacher machen, sonst differenzierst du nachher noch in normale Waffe / magische Waffe, das gleiche mit Rüstung, Trank etc.


----------



## Ion (3. Jun 2015)

Eine einfache Möglichkeit aber auch eine gute? Man könnte ja rein theoretisch vieles mit einem boolean erledigen. Man könnte dann ja auch sagen bei einem Gegenstand boolean istArmor, istMagisch, istTrinkbar und noch vieles mehr aber ob das so gut ist? Bei einem Raum geht das ja denke ich noch, weil der Ausgang ja eigentlich keine zusätzlichen Methoden etc. braucht? 

Die Überprüfung mit der Prüfung auf dem Ausgang müsste dann aber immer trotzdem noch in der Schleife sein oder, also so oder kriegt man das auch irgendwie da raus?

```
boolean beendet = false;
while(!beendet) 
{
    if(spieler.istTot())
    {
        verlorenstextAusgeben();
        beendet = true;
    }
    if(spieler.getAktuellerRaum().istAusgang()) 
    {
        gewonnenstextAusgeben();
        beendet = true;
    }
}
```
 

```
public boolean istAusgang()
{
    return (this.ausgang == true);
}
```

zu den magischen Gegenständen:
Ja, das wäre ja auch wieder die Sache. Das ist zwar einfacher aber wenn ich dann einen Gegenstand benutze, also die benutze (oder use) Methode aufrufe, dann müsste ich da ja auch wieder differenzieren oder nicht?

```
public class UsableItem
{
  private String name;
  private String description;
  private boolean magic;
  private int healthBoni;
  private int manaBoni;
  public UsableItem(String name, String description, boolean magic, int healthBoni, int manaBoni)
  { ... }

   public voud use()
    {
        if(magisch)
        {
            int lebenspunkte = spieler.getLebenspunkte();
            lebenspunkte += healthBoni;
            int manapunkte = spieler.getManapunkte();
            manapunkte += manaBoni;
            
            spieler.setLebenspunkte(lebenspunkte);
            spieler.setManapunkte(manapunkte);
        }
        else
        {
            
        }
    }
}
```

Dann muss man ja auch immer wieder unterscheiden oder nicht? Ich hatte ja auch oben mal gesagt, das ich evtl. sowas wie Wasser als Gegenstand einfügen wollte. Soll man dann auch wieder einen boolean nehmen z.B trinkbar?

Das wird doch mit Sicherheit sehr schnell unübersichtlich oder nicht? Zwar bräuchte man dann noch bei allen die Spielerinstanz aber trotzdem. Dann hat man ja auch immer Methodenaufrufe, die man eigentlich nicht braucht oder nicht?

Oder meinst du mit weiter seperieren, das man doch auch noch weitere Unterklassen erstellt, also dann wirklich von Gegenstand eine Unterklasse Manatrank oder Lebenstrank oder so erstellen?


----------



## InfectedBytes (3. Jun 2015)

ich bin mir immer noch nicht sicher wozu du überhaupt die unterscheidung magisch oder nicht machen willst?
Was soll denn überhaupt der Unterschied zwischen magischen und nicht magischen gegenständen sein?
Was kann ein magischer Gegenstand, was ein nicht magischer nicht kann?

Du kannst natürlich weiter in trinkbar oder nicht differenzieren, aber das ist eigentlich nicht nötig. 
Ob Heiltrank oder Wasser macht ja keinen Unterschied, bloß dass ein Heiltrank die Gesundheit vielleicht um 20 erhöht und das Wasser bloß das Mana um 5. 

```
UsableItem wasser = new UsableItem("Wasser", "Frisches Bergquellwasser", ...);
UsableItem heiltrank = new UsableItem("Heiltrank", "Ein rotglühender Heiltrank", ...);
```

Klar kannsst du eine extraklasse Heiltrank und Manatrank machen, aber diese Unterscheiden sich nur in einer einzigen Variable. Und wenn du einen Universaltrank hinzufügst, der beides kann, dann hast du wieder ein Problem. 
Deswegen ist es sinnvoller Heiltrank und Manatrank als ein und dasselbe zu betrachten:

```
heiltrank = new UsableItem(..., 20, 0); // +20 health, +0 mana
manatrank = new UsableItem(..., 0, 10); // +0 health, +10 mana
universaltrank = new UsableItem(..., 10, 10); // +10 health, +10 mana
```


----------



## Ion (3. Jun 2015)

Wenn man aber bei dem Trinkbaren Gegenstand zusätzlich noch den Durst stillen will (eine int variable), was macht man aber dann? Oder wenn man noch essen einführt? Wasser sollte meiner Ansicht nach sowieso wenn überhaupt eher ein wenig Leben wiederherstellen und kein Mana.

Hast du das mit der Überprüfung des Ausganges übersehen? Du hast nur auf den unteren Teil geantwortet? 

Hier noch einmal:
Die Überprüfung mit der Prüfung auf dem Ausgang müsste dann aber immer trotzdem noch in der Schleife sein oder, also so oder kriegt man das auch irgendwie da raus?

```
boolean beendet = false;
while(!beendet) 
{
    if(spieler.istTot())
    {
        verlorenstextAusgeben();
        beendet = true;
    }
    if(spieler.getAktuellerRaum().istAusgang()) 
    {
        gewonnenstextAusgeben();
        beendet = true;
    }
}
```
 

```
public boolean istAusgang()
{
    return (this.ausgang == true);
}
```


----------



## InfectedBytes (3. Jun 2015)

zu dem Raum:
genau, in der schleife ist es dann ok

Zu den tränken:
Alle Gegenstände die man verbrauchen kann durch essen/trinken, würde ich eben als eine Klasse machen. Bisher habe ich die UsableItem genannt, aber vermutlich würde Consumable besser passen^^
Da würde ich dann eben vier ints reinpacken: health, mana, hunger, thirst. 
Dann kannst du für jeden Gegenstand eine beliebige Kombination einfügen. 
Der Heiltrank könnte somit z.B. gesundheit um 20 erhöhen, den durst um 5 stillen, aber dafür etwas hunger erzeugen. 
Eine wassermelone, könnte dann hunger und durst stillen, aber sonst nix, etc.


----------



## Ion (4. Jun 2015)

Mhm .. evtl. bräuchte ich dieses Attribut magisch dann gar nicht mehr? Letzendlich ist es ja sowieso kein grafisches Spiel. Ich denke, das ich dann eine Klasse Konsumierbar mache. Ansonsten müsste man ja noch in der use Methode differenzieren? Wenn ich keine magischen Gegenstände machen würde, dann könnte das ja mit dem if(magic) weg.

```
public class UsableItem
{
  private String name;
  private String description;
  private boolean magic;
  private int healthBoni;
  private int manaBoni;
  public UsableItem(String name, String description, boolean magic, int healthBoni, int manaBoni)
  { ... }

   public voud use()
    {
        if(magic)
        {
            int lebenspunkte = spieler.getLebenspunkte();
            lebenspunkte += healthBoni;
            int manapunkte = spieler.getManapunkte();
            manapunkte += manaBoni;
            
            spieler.setLebenspunkte(lebenspunkte);
            spieler.setManapunkte(manapunkte);

            // usw. je nach Anzahl der Attribute, die gesetzt werden müssen?
        }
        else
        {
            
        }
    }
}
```

Also würdest du dann für alles was konsumierbar ist, einen int Wert und evtl. auch einen boolean hinzufügen und dann jeweils die setter Methoden des Spielers aufrufen, also obwohl es teilweise auch nicht gebraucht wird? Wenn bei einer variable, wie bspw. mana dann im Konstruktor null steht und dann die Methode aufgerufen wird, dann ändert sich der Wert ja nicht. Meinst du das so? 

Dann hat man aber je nach Anzahl der Eigenschaften des Spielers auch viele Methoden, die im Prinzip nichts ändern? Dann hat man ja auch immer Methodenaufrufe, die man eigentlich nicht braucht oder nicht?


----------



## InfectedBytes (4. Jun 2015)

Genau, nachdem was ich bisher gelesen habe, gibt es effektiv keinen unterschied zwischen magischen und nicht magischen gegenständen. (außer vielleicht dem Namen^^)

Alles was konsumierbar ist, enthält die ganzen ints für health, mana, etc. 
Wofür möchtest du einen boolean einfügen?

Genau, wenn dann im Konstruktor 0 steht, wird eben immer 0 aufaddiert, was logischerweise nichts ändert. 

Man hat dann ggf. schon ein paar unnötige Aufrufe, aber dies 2-3 Stück fallen ja nicht ins gewicht. 
Wenn du jetzt 20 verschiedene Attribute hättest, dann sollte man sich doch was anderes überlegen (z.b. Komponenten pattern). Aber bei diesen 4 Attributen ist es vermutlich so schöner und übersichtlicher.


----------



## Ion (4. Jun 2015)

Ach, das meintest du damit. 
Ja, genau. Das ist mir dann auch gestern endlich mal aufgefallen. 

Meintest du denn aber auch, das die Klasse UsableItem eine Unterklasse von Gegenstand ist oder sollte die eigenständig sein? Wenn ich die nämlich von Gegenstand extende, dann muss ich ja benutze überschreiben, alledings habe ich die ohne Parameter gemacht, weil ich die ja bei der Waffe ja eigentlich nicht brauche?

Die Signatur muss ja beim überschreiben übereinstimmen, also kann man da ja auch nichts machen oder?

Das hier ist in der Spiel Klasse und wird aufgerufen, wenn ein Gegenstand "konsumiert", also verbraucht werden kann. Ich habe jetzt für Waffen als Eingabe ausrüsten genommen. 

```
private void gegenstandKonsumieren(Befehl befehl) 
{
    if(!befehl.hatZweitesWort()) 
    {
        System.out.println("Was möchten Sie tirnken? Geben Sie bitte den Namen ein.");
        return;
    }
    
    String gegenstandsName = befehl.gibZweitesWort();
    Gegenstand gegenstand = spieler.gegenstandKonsumieren(gegenstandsName);
    
    if(gegenstand == null)
    {
        System.out.println("Der Gegenstand \"" + gegenstand + "\" kann nicht benutzt werden!");            
    } 
    else 
    {
        gegenstand.benutze(spieler);
        System.out.println("Sie haben den \"" + gegenstand + "\" benutzt.");
    }
}
```

und das ist dann in der Spieler Klasse:

```
public Gegenstand gegenstandKonsumieren(String gegenstandsName) 
{
    Gegenstand gegenstand = gegenstaende.remove(gegenstandsName); 
    return gegenstand;
}
```


und das hier ist für einen Ausrüstbaren Gegenstand. Diese Methode wird bei Eingabe von "Ausrüsten" aufgerufen. 

```
private void gegenstandAusruesten(Befehl befehl) 
{
    String waffenName = befehl.gibZweitesWort();
    Gegenstand gegenstand = spieler.waffeImInventar(waffenName);
       
    if(gegenstand == null)
    {
        System.out.println("Sie besitzen den Gegentand \"" + waffenName + "\" nicht!");
    }
    else if(!spieler.waffeAusruesten(gegenstand))
    {
        System.out.println("Bei dem Gegenstand handelt es sich nicht um eine Waffe!");
    }
    else
    {
        System.out.println("Sie haben den den Gegenstand \"" + waffenName + "\" ausgerüstet.");
        System.out.println("Ihr Schaden hat sich auf " + spieler.getSchaden() + " erhöht.");
    }
}
```

und hier dann auch noch einmal die vollständigen Methoden dazu. Die Methode istWaffe() brauche ich ja denke ich nicht noch einmal extra zeigen oder? Diese Methoden befinden sich in der Klasse des Spielers.

```
public Gegenstand waffeImInventar(String waffenName) 
{
    Gegenstand waffe = gegenstaende.get(waffenName);
    
    if(waffe == null)
        return null;
                   
    return waffe;
}

public boolean waffeAusruesten(Gegenstand gegenstand)
{
    if(gegenstand.istWaffe(gegenstand))
    {
        setWaffe((Waffe)waffe);
        setSchaden(basisSchaden + ((Waffe) waffe).getSchaden());
        
        return true;
    }
    
    return false;
}
```

Passt das alles wohl so? Sind die Methoden jeweils an der richtigen Postion?

Jetzt fehlt mir eigentlich auch nur noch das mit der benutzen Methode oder wie man das regeln kann. 
Danke noch (und schon einmal?) für deine Hilfe!


----------



## InfectedBytes (5. Jun 2015)

Sie sollte schon von Gegenstand erben. Denn immerhin IST es ein Gegenstand^^. Außerdem willst du die Dinge ja alle Gemeinsam im Inventar Speichern und dafür brauchst du eine gemeinsame Oberklasse. 
Du könntest die benutze-Methode von Gegenstand um den Parameter erweitern. Denn Grundsätzlich kann es ja für jede Art von Gegenstand interessant sein vom wem er benutzt wird. 

Grundsätzlich geht das schon alles, hier und da ist es allerdings etwas unschön.
Z.b. ist die gegenstandKonsumieren-Methode in der Spieler-Klasse etwas unpassend. Dem Namen nach würde man vermuten, dass diese Methode den Gegenstand direkt konsumiert, stattdessen entfernt sie ihn nur aus dem Inventar und gibt ihn zurück. 
Das konsumieren würde ich lieber in der SpielerKlasse erledigen. Bzw. in der gemeinsamen Oberklasse von Spieler und Monster, falls Monster Gegenstände auch benutzen können sollen. 

```
//In der Spielerklasse, bzw. dessen Oberklasse
public boolean gegenstandKonsumieren(String name) {
  Gegenstand gegenstand = gegenstaende.remove(gegenstandsName); 
  if(gegenstand==null) return false; //Gegenstand konnte nicht benutzt werden, da er nicht existiert
  gegenstand.benutze(this);
  return true;//Gegenstand konnte benutzt werden
}
```
In deiner Spiel Klasse vereinfacht sich die Methode dann auch:

```
private void gegenstandKonsumieren(Befehl befehl) {
    if(!befehl.hatZweitesWort()) 
    {
        System.out.println("Was möchten Sie tirnken? Geben Sie bitte den Namen ein.");
        return;
    }

    String gegenstandsName = befehl.gibZweitesWort();
    if(spieler.gegenstandKonsumieren(gegenstandsName)) {
        System.out.println("Gegenstand wurde benutzt");
    } else {
        System.out.println("Der Gegenstand existiert nicht");
    }
}
```

Deine Waffe im Inventar Methode finde ich recht unnötig, da sie ja nichts macht als den Gegenstand zurückzugeben. 
Dafür solltest du lieber eine passende get-Methode nutzen, denn du willst ja ggf. auch andere Gegenstande haben

```
public Gegenstand get(String name) {
  return gegenstaende.get(name);
}
```

Ansonsten ist eigentlich alles soweit in Ordnung


----------



## Ion (6. Jun 2015)

Ja, dass das ein Gegenstand sollte ist mir schon klar, deswegen ja das Problem. 
Ich habe es jetzt allerdings mal so umgsetzt, wie du gesagt hast. Auch das mit dem Konsumieren des Gegenstandes habe ich jetzt noch einmal abgeändert. So passt es jetzt auch wirklich besser.

Zu der Waffe im Inventar Methode:
Ja, das stimmt. Deine Variante ist auch sehr viel  kürzer. Das habe ich auch mal sowas von verlegt, das man das auch mal ebend so schreiben kann. Ich habe es ja derzeit auch derzeit so erledigt, das man nur eine Waffe ausrüsten kann und auch generell überhaupt nur einen Gegenstand. Dafür war diese Methode ja eigentlich gedacht.

Ich bin allerdings grade am überlegen, ob ich es nicht vielleicht so mache, das es dann noch andere Ausrüstungsgegenstände gibt, wie Rüstungen oder sowas. Sollte man dann dafür eine extra hashmap erstellen, wo sich dann die ausgerüsteten Gegenstände drin befinden oder braucht man dafür keine zusätzliche Hashmap? Derzeit habe ich nur eine, die sich inventar nennt. 

Dafür könnte man ja dann diese get Methode benutzen, weil diese ja eigentlich nur für die Waffe gedacht war. Dann wäre diese jetzt ebend, um zu gucken ob sich der Gegenstand in den "ausgerüsteten" Gegenständen befindet, bzw. zu diesen zählt oder ebend nicht.

Dann könnte man ja eine allgemeine Methode in der Spielerklassse gegenstandAusruesten schreiben und die dann auch wieder so wie bei der gegenstandKonsumieren Methode aufrufen.

Das wäre dann die Methode in der Spieler Klasse:

```
public boolean gegenstandAusruesten(String gegenstandsName) 
{
    Gegenstand gegenstand = getGegenstand(gegenstandsName); 
    // und eventuell?
    // Gegenstand gegenstand = gegenstaende.remove(gegenstandsName); 
    if(gegenstand == null)
        return false; 
    
    gegenstand.benutze(this);
    return true; 
}
```

und da wird ja dann je nach Gegenstand auch die passende benutze() Methode aufgerufen. Dann bräuchte ich ja nur wieder einen neuen Gegenstand (Unterklasse von Gegenstand), Armor oder ähnliches, richtig?
Wäre das Vorgehen so richtig, bzw. liege ich damit richtig? 

Nur was ich mich jetzt auch noch frage ist, ob der Gegenstand sich dann *sowohl* in der inventar hashmap, *als auch* in der ausgerüsteteGegenstaende Hashmap (oder wie auch) immer befinden sollte.

Sollte ich dann, wie im Beispiel (auskommentiert) den Gegenstand aus der Hashmap gegenstaende (inventar-hashmap) entfernen oder sollte der da auch drin bleiben?


----------



## InfectedBytes (6. Jun 2015)

Bezüglich der extra ausrüstungshashmap. Es kommt drauf an wieviele ausrüstungsgegenstände man gleichzeitig benutzen können soll. Wenn es nur schwert und rüstung ist, reicht es jeweils eine lokale Variable waffe und armor anzulegen. 
Wenn man dann aber noch handschuhe, hosen, plattenpanzer, etc. tragen kann wäre ggf eine zweite map nicht schlecht. 
Grundsätzlich würde ich aber die gegenstände nicht aus der inventar map entfernen.

Wenn du nun eine extra Liste für ausgerüstete Gegenstände führst, musst du natürlich aufpassen, dass man nicht mehrere Gegenständige der gleichen Sorte trägt. Zwei Hosen anzuhaben macht halt wenig sinn. 
Dafür könntest du den ausrüstbaren Gegenstande eine Variable mitgeben, die aussagt, was für ein Typ sie denn sind:

```
enum AusrüstungsTyp {
 WAFFE, SCHILD, HOSE, HANDSCHUH, HELM, HEMD, ...
}

public class Ausrüstung extends Gegenstand {
  private AusrüstungsTyp typ;
  public AusrüstungsTyp getTyp() { return typ); }
  // ... benutze methode kommt später
}
```
Von dieser Klasse könnte man dann z.b. drei Unterklassen erstellen: Waffe, Schild, Kleidung. 
Die Waffenklasse würde z.b. den Schaden speichern den sie anrichtet, die Kleidungsklasse würde hingegen speichern wieviel sie absorbiert. 
Nun hat jede Kreatur eine ausrüstungshashmap, die jedoch nicht den Namen als Schlüssel benutzt, sondern den Typ. 

```
private HashMap<AusrüstungsTyp, Ausrüstung> ausgerüstet = new HashMap<>();
public Ausrüstung getAusrüstung(AusrüstungsTyp typ) { return ausgerüstet.get(typ); }
public void rüsteAus(Ausrüstung rüstung) {
  ausgerüstet.put(rüstung.getTyp(), rüstung);
}
```

Wenn nun ein ausrüstungsgegenstand benutzt wird, geschieht folgendes:

```
public class Ausrüstung {
  // ...
  public boolean benutze(Lebewesen wesen) {
    wesen.rüsteAus(this);
  }
}
```
Wenn du nun wissen willst, ob ein Lebewesen eine Waffe führt, machst du folgendes: wesen.getAusrüstung(Ausrüstungstyp.WAFFE);
Bei einer hose: wesen.getAusrüstung(Ausrüstungstyp.HOSE); 
etc.

Die Erstellung der verschiedenen Sachen könnte z.B. so aussehen:

```
schwert = new Waffe("Schwert", 10, Ausrüstungstyp.WAFFE); // macht 10 schaden
hose = new Kleidung("Hose", 10, Ausrüstungstyp.HOSE); //absorbiert 10 schaden
handschuh = new Kleidung("Handschuh", 5, Ausrüstungstyp.HANDSCHUH);//absorbiert 5 schaden
```

p.s.
Theoretisch könnte man unter Umständen die Klassen Waffe, Schild, Kleidung zusammenlegen.
Eine Waffe hätte dabei einen Schaden>0 während, Schild und Kleidung Schaden<0 haben. 
Aber das ist ggf. etwas unübersichtlich, daher sind mehrere Klassen vermutlich besser


----------



## Ion (13. Jun 2015)

Naja, wenn dann würde ich die Klassen schon seperieren, was ich auch gemacht habe.
Das mit der enum ist übrigens auch echt eine sehr gute Idee. Ich denke mal, das ich das auch so oder zumindest so ähnlich umsetzen werde.  

Wie könnte man nachher dann aber eigentlich zwischen gleichen Gegenständen seperieren, also ich meine bei zwei Waffen, die beide den Key Schwert haben. Was könnte man da machen, wenn man zweimal das gleiche Item erstellen will und auch mit identischem Namen. Das wäre ja so gar nicht möglich, oder?

Ich hatte ja auch ganz am Anfang mal von dieser prozentualen Chance gesprochen. Wie kann man das eigentlich regeln? Ich will ja dann bei der Objektinitalisierung, bspw. in einem Raum eine Chance von 0 - 100%, das der Spieler in diesem Raum angegriffen wird aber eine prozent Variable gibt es ja nicht, oder?


```
public class Raum 
{    
    private double chanceAufAngriff;
    
    // usw ....

    public Raum(String beschreibung, double chanceAufAngriff) 
    {
        this.beschreibung = beschreibung;
        try
        {
            if(chanceAufAngriff > 1.00 || chanceAufAngriff < 0.00)
                throw new Exception("Der Wert muss zwischen 0 und 1 liegen!"); 
        }
        catch(Exception ex) { }
        
        this.chanceAufAngriff = chanceAufAngriff;
           
        // usw ....
    }
    
    // usw ....
}
```

Aber müsste man dann irgendwas noch in den catch-Block einfügen oder kann man das auch irgendwie anders bzw. besser regeln? Eine prozent variable gibt es ja nicht?

Wenn der Wert nicht in dem Bereich liegt, dann soll das Programm ja beendet werden aber so würde man den Fehler ja abfangen und das Programm würde ja weiterlaufen? Müsste da dann noch ein

```
System.exit(0);
```

rein?

Den Wert könnte man dann ja nachher so überprüfen.

```
if(Math.random() < 0.4) // 40% chance
```


----------



## InfectedBytes (13. Jun 2015)

Da du bisher eine hashmap für das Inventar nutzt und den Namen als Key verwendest, geht das nicht. 
Aber du kannst einfach eine Liste als Inventar nehmen und diese durchsuchen. 

```
private ArrayList<Item> inventar = new ArrayList<Item>();
public Item get(String name) {
  return get(name, 1);
}

public Item get(String name, int wievieltes) {
  int found = 1;
  for(Item item : inventar) {
    if(item.getName().equals(name)) {
      if(found == wievieltes)
        return item;
      else
        found++;
    }
  }
  return null;
}
```
Mit so einer Methode könntest du dann z.B. sagen das du das zweite Schwert haben willst: get("Schwert", 2)

Das soll denn bitte eine ProzentVariable sein? 
Ein Prozentwert ist nichts weiter als eine Zahl. 


```
try
        {
            if(chanceAufAngriff > 1.00 || chanceAufAngriff < 0.00)
                throw new Exception("Der Wert muss zwischen 0 und 1 liegen!"); 
        }
        catch(Exception ex) { }
```
Das macht absolut überhaupt keinen Sinn.
Du wirfst eine Exception, fängst sie aber sofort wieder. D.h. selbst wenn eine falscher Wert eingegeben wird, machst du im Endeffekt ganz normal weiter. 

Entweder du wirfst eine Exception und lässt sie vom Aufrufer fangen, damit er weiß das er mist gebaut hat oder du korrigierst die Eingabe einfach:

```
if(chance>1) chance=1;
else if(chance<0) chance = 0;
```
Falls also etwas unsinniges eingegeben wird, so wird der Wert einfach auf den nächsten gültigen Wert gesetzt.

Falls das du wegen so einem Fehler das Programm beenden willst, dann wäre es das einfachste es so zu machen:

```
if(chance>1 || chance<0) System.exit();
```
Warum so kompliziert über eine selbstgefange Exception???

Und am Ende solltest du natürlich nicht <0.4 prüfen, sondern auf < chanceAufAngriff


----------



## Ion (13. Jun 2015)

Ja, das dachte ich mir schon. Dann muss man ja schon auf ein Liste zurückgreifen. Mit der Methode oben müsste man dann aber auch immer das wievielte angeben aber wie würde man das machen, so das der passende Gegenstand dann "automatisch" ausgewählt wird und man dieses nicht explizit mit angeben muss?

Mit prozent Variable meinte ich sowas wie einen Datentyp aber den gibt es ja so nicht, zumindest nicht ohne extra library? 

Natürlich ist ein Prozentwert letzendlich nur eine Zahl, das ist mir schon klar. Dafür eignet sich ja dann auch eigentlich nur ein double oder ein int.

Zu meinem "Beispiel"
Ja, das habe ich ja auch geschrieben. Kann man es denn dann auch irgendwie erreichen, das der Compiler das schon beim Kompilieren bemängelt, so wie wenn man einen falschen Datentyp etc. angibt? Ansonsten wären das ja sonst nur "Laufzeitfehler".

Wenn ich jetzt aber nur System.exit(); mache, dann kriegt der Benutzer ja keine Meldung, wie kann man denn so ein Fehlerfenster erzeugen in den man sagt, wo der Fehler aufgetreten ist?

Das wäre es dann aber auch echt mit diesen Thread. Ist sowieso eigentlich schon zu viel für einen Thread oder? Danke noch einmal für die ganze Hilfe.


----------



## InfectedBytes (13. Jun 2015)

Ion hat gesagt.:


> Ja, das dachte ich mir schon. Dann muss man ja schon auf ein Liste zurückgreifen. Mit der Methode oben müsste man dann aber auch immer das wievielte angeben aber wie würde man das machen, so das der passende Gegenstand dann "automatisch" ausgewählt wird und man dieses nicht explizit mit angeben muss?


Du solltest dir meine Antwort schon komplett ansehen^^
Das steht dort nämlich bereits: 

```
public Item get(String name) {
  return get(name, 1);
}
```
Wenn man einfach nur einen Gegenstand mit dem Namen haben will, so wird einfach der erste zurückgegeben. 
Falls man jedoch explizit einen anderen haben will, kann man eben auch direkt get("xyz", 123) angeben.

Theoretisch kann man es dem Compiler schon sagen, jedoch ist das relativ aufwendig und kein wirkliches Anfängerthema. 
Falls du es dir trotzdem anschauen willst (was ich nicht empfehlen würde), google einfach mal nach: eclipse annotation processor

Wenn deine hauptschleife grob so aussieht, ist es recht einfach:

```
public class Textadventure {
  public static boolean running;
  public void run() {
    running = true;
    while(running) {
      // do some stuff
    }
  }
}
```
Wenn du ein Fehlerfenster haben willst, kannst du auch einfach einen neuen JFrame anzeigen und anstatt System.exit() dann eben Textadventure.running = false setzen:

```
if(chance>1 || chance <0) {
  Textadventure.running = false;
  JFrame meldung = new JFrame();
  //...
}
```

Alternativ kannst du es auch mit Exceptions machen (vielleicht etwas angebrachter):

```
public class Textadventure {
  public void run() {
  try {
    while(running) {
      // do some stuff
    }
    } catch(Exception e) {
      JFrame meldung = new JFrame();
      // meldungstext kannst du z.B. mit e.getMessage() bekommen
    }
  }
}
```


```
if(chance>1 || chance<0) 
  throw new EXception("blablabla");
```
Natürlich musst du dann eben passende throws direktiven an die Methode hängen:

```
public void xyz() throws Exception {
...
}
```


----------

