Frage von gut4fr5g4, 175

javafx snake mit OO exception?

http://hastebin.com/qexexakise.avrasm

Ich habe mir diesmal wirklich mühe (WIRKLICH viel mühe) gegeben und, so gut, wie ich kann, snake geschrieben, bin noch dabei, die bewegung umzusetzen, habe den code diesmal sogar so gemacht, dass wenn man einen wert ändert, sich das spiel ohne weitere eingaben automatisch anpasst anpasst, also um die maße zu ändern einfach einmal ändern an einer stelle und die maße des fensters, des spielfeldes etc. passen sich an, wenn man das so sagen kann

Ich habe überall kommentare gemacht, zur übersichtlichkeit, und nun wenn ich es ausführe und dann w a s oder d drücke, bekomme ich eine exception:

Exception in thread "Timer-0" java.lang.NullPointerException at mainPackage.Spielfeld.Feld(Spielfeld.java:51) at mainPackage.Move$2.run(Move.java:24) at java.util.TimerThread.mainLoop(Unknown Source) at java.util.TimerThread.run(Unknown Source)

Ich weiß ja, dass ich auf den Rectangle-Array irgendwie keinen zugriff habe oder so, aber woran liegt das? ich habe ihn doch definiert und so

Bitte helft mir und sagt mir wenn ihr schon dabei seid, wie der quellcode jetzt ist und was ich wieder besser machen muss (bitte beleidigt mich jetzt nicht, ich bin eben noch nicht der beste, ich probiere mich ja immer weiter zu verbessern [sachliche negative kritik ist erwünscht])

Ich hoffe jemand hilft mir! :D

LG

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von KnusperPudding, Community-Experte für Java, 80

Das Problem hat Androidhecker bereits beschrieben.

Die Lösung für diesen Fehler: 

Erstelle folgenden Konstruktor in deiner Klasse Move:

public Move(Spielfeld spielfeld) {
    this.objekt1 = spielfeld;
}

Dadurch kannst du in Move auf das Spielfeld zugreifen ohne dort ein neues Spielfeld zu erstellen.

in deiner Main sieht das dann so aus:

Spielfeld objekt1 = new Spielfeld();
Move objekt2 = new Move(objekt1);

Allerdings wenn dieses Problem behoben ist, treten andere Probleme auf.

sagt mir wenn ihr schon dabei seid, wie der quellcode jetzt ist und was ich wieder besser machen muss 

Vorerst nur kleinere Dinge:

  • Keine Umlaute in Methoden verwenden: äöü sondern dafür ae oe ue verwenden*.Einige schwören darauf die Anwendung komplett in englisch zu halten. Ich persönlich bin der Meinung, dass der Programmierer seinen eigenen Code leicht verständlich lesen können soll. (Natürlich ausnahmen wenn man für ein internationales Unternehmen arbeitet)
  • Methoden sollte man immer klein Schreiben: "void Bewegung" -> "void Bewegung".
  • Variablen-Zugriffsrechte: In der Regel lässt man Variablen nicht von außen ändern und sollten daher private sein. für einen Zugriff von Außen sollte man getter und setter verwenden.

Was die Codestruktur betrifft, würde ich nochmal genauer ins Detail gehen, aber auf die kürze bekomme ich das Snake-Spiel noch nicht richtig zum laufen.

 *= Einige Source-Verwaltungen ersetzen Sonderzeichen wie äöüß durch Kryptische Zeichnen. Was dann bei Aktualisierung deinen Code unbrauchbar machen könnte.

Kommentar von gut4fr5g4 ,

Habe es jetzt fast fertig und von dir un androhecker gesagten dinge beachtet, ich hoffe, du nimmst dir nochmal die zeit und guckst es dir nochmal an (schicke es so gegen abend nochmal rein! danke!!!)

Kommentar von KnusperPudding ,

Ja, ich werde nochmal rein schauen. 

Kommentar von gut4fr5g4 ,

Methoden sollte man immer klein Schreiben: "void Bewegung" -> "void Bewegung".

das versteh ich jetzt nicht, wie du das meinst?

Was muss jetzt am anfang klein, was groß?

also klassen klein, packages klein, und was noch?

Kommentar von gut4fr5g4 ,

hat sich schon erledigt,

ist das mit dem setter getter notwendig, weil ich finde das gerade irgendwie sinnlos, man kann ja einfach die variable übergeben

Kommentar von KnusperPudding ,

ist das mit dem setter getter notwendig

Ja, ist es.

Innerhalb einer Klasse kannst du auf deine Variable natürlich direkt zugreifen. Aber spätestens wenn du von anderen Klassen auf diese Variable ohne Getter und Setter zugreifst, wird es unsauber.

Getter und Setter lassen sich zudem Code-Technisch erweitern, indem man beispielsweise Listener hinzufügt oder andere Aktionen geschehen sollen.

Man braucht nicht für jede Variable Getter und Setter. nur da wo es Sinn macht.

Kommentar von KnusperPudding ,

Klassen groß:

public class MeineKlasse{

}

Methoden klein:

private void test() {

}

package klein:

package com.test.gf;

Variablen und Parameter klein:

private void test(String value) {

}
private String test;

Konstanten komplett groß:

public final static int FRIDAY = 6;
Kommentar von gut4fr5g4 ,

und wo macht ein getter setter sinn? also immer wenn ich eine variable in einer anderen klasse ändere oder wie? 

Was bringt nochmal ein static bei int, double, etc.

Kommentar von KnusperPudding ,

Vor kurzem hat jemand hier wegen dem  static-Bezeichner gefragt und es gab eigentlich ziemlich gute Antworten:

https://www.gutefrage.net/frage/java-stimmt-das-ueber-static?foundIn=tag_overvie...

Kurzfassung: Das brauchst du wenn es die Methode oder Variable nur einmal (Instanz-unabhängig) geben soll.

Wo getter und setter sinn machen? Es gibt zich unterschiedliche Anwendungsbeispiele. Wie bereits beschrieben, wenn zusätzlicher Code notwendig wird wie bei Listenern und bezüglich der Nachvollziehbarkeit bei Änderungen dieser Variable.

Wenn du nochmal ein funktionierendes Beispiel deines Snake-Spiels bereit stellst, erkläre ich dir das daran.

PS: Rein interessehalber: Wieso verwendest du keine 2D Array als Spielbrett?

Kommentar von gut4fr5g4 ,

Ich verwende keine 2D-Arrays, weil ich es mir irgendwie mit 1d angewöhnt habe, aber ich kann auch 2d-arrays reinmachen später :)

nur so grob zusammengefasst (dass ich mir ne regelmäßigkeit einprägen kann), wann brauche ich denn den getter setter also grob gesagt

Kommentar von KnusperPudding ,

grob gesagt

wenn du Instanz-Variablen hast, die auch für den Zugriff von außen bestimmt sind.  

und wenn du beim set noch andere Dinge machen möchtest. wie prüfen ob der übergebene wert überhaupt erlaubt ist, etc.

Kommentar von gut4fr5g4 ,

was sind instanz-variablen

Kommentar von KnusperPudding ,
public class Test {
    private String value;
}

Eine Variable die ihre Gültigkeit nur innerhalb einer Instanz hat.

In deinem Code in der Klasse Spielfeld wären das Beispielsweise die Variablen für die X und Y Koordinate.

Kommentar von gut4fr5g4 ,

muss ich den getter setter so machen? 

int x;
void setter(int x){
this.x=x;
}

//Methode zur Bearbeitung von "x" 

int getter(){
return x;
}

oder muss ich die Bearbeitung in den setter/getter schreiben?

Kommentar von KnusperPudding ,

getter und setter sollten eigentlich berechtigterweise public sein.

oder muss ich die Bearbeitung in den setter/getter schreiben?

wenn du mit bearbeiten die Wertzuweisung meinst, dafür ist der Setter bestimmt:

public void setX(int x) {
    this.x = x;
}

wäre aber eben hauptsächlich für Aufrufe von außen gedacht, es sei denn man möchte hier noch Logiken implementieren.

Kommentar von gut4fr5g4 ,

wenn du zum beispiel jetzt x in einer anderen klasse um 10 addierst, kommt das dann in den setter oder in eine seperate methode?

Kommentar von KnusperPudding ,
class AndereKlasse {
    
    private Spielfeld spielfeld;

    private void machIrgendwas() {
         spielfeld.setX(spielfeld.getX() + 10);
    }
}
Kommentar von gut4fr5g4 ,

muss ich den getter setter auch bei der stage machen? die ändere ich ja auch in einer anderen klasse, bei meinem quellcode?

Kommentar von gut4fr5g4 ,

http://hastebin.com/eranorocay.avrasm

So guter quellcode? Wenn nein, was muss ich ändern, LG! :D

Kommentar von KnusperPudding ,

Ein Setter heißt bei einer Methode eigentlich setValue und nicht setterValue. Aber ich schaue es mir an.

Kommentar von KnusperPudding ,

PS: Werde mir jetzt einmal ausnahmsweise die Mühe für einen vollständigen Review geben. In der Hoffnung dass dann das ein oder andere klarer wird.

Kommentar von gut4fr5g4 ,

Danke für deine Hilfe, ich muss an dieser Stelle sagen, dass ich das sehr zu schätzen weiß, dass du dir so oft die Zeit nimmst, meine Fragen zu beantworten und dir jetzt auch alles ins Detail anguckst.

Danke (gibt nicht viele, die so gute Antworten bringen und du bist, wie ich finde der hilfreichste User hier im Forum im Bereich Java (und @androhecker auch))!

LG und schönen Abend noch! :D

Kommentar von KnusperPudding ,

Okay. Würde man mir das zum Codereview vorlegen, würde ich den Code folgendermaßen ändern:

Klasse Game (Deine ehemalige Main-Klasse)

http://hastebin.com/ihihicosuz.java

Anmerkungen:

> Die Klasse ist umbenannt, da man eigentlich mehrere ausführbare Anwendungen in einem Projekt haben kann und ich auch für die Starter-Klassen versuche "sinnvolle Namen" zu vergeben.

> Wertzuweisungen sind überflüssig wenn man die Variable nicht verwendet wie hier:

stage = objekt1.getterStage();

Weshalb ich das weg lasse.

> Die Benamung von Variablen sollten immer 'sinnvoll' sein. Also sowas wie "objekt1" ist schwerer zu lesen.

> Die Snake muss nicht in der Game-Klasse erstellt werden, vor allem da Spielbrett und Snake sich ja kennen müssen, deshalb kann das im Spielbrett erfolgen.


Klasse: Snake

http://hastebin.com/ikiwukebob.java

Anmerkungen:

> Das was du als Snake benannt hast in deiner Snake-Klasse wäre etwas unpraktisch, da die Klasse bereits so heißt, daher ist das in "Position" umbenannt, da die Array die Position der Schlange darstellt.

> Der dazugehörige Setter wurde entfernt, da die Position nicht von außen gesetzt werden sollte.

> Bei der Kollisionsprüfung sollte man nach bester Möglichkeit Schleifen vermeiden, da diese Prüfung bei jeder Bewegung ausgeführt wird.

> Bei der Kollisionsprüfung habe ich einen Teil noch weggelassen, den du noch ergänzen kannst: Die Kollision mit der Schlange selbst.


Klasse: Spielbrett

http://hastebin.com/jeqeyutiqu.java


Anmerkungen:

> Die Initialisierung deiner Instanz-Variablen habe ich in den Konstruktor verschoben, denn so ist leichter erkennbar welche Variablen ausgetauscht werden können und welche erst durch setter oder anderen Wertzuweisungen verändert werden.

> Die SCALE-Konstante hattest du zuvor fix als Zahl verwendet. Modifizierst du die Zahl, vergrößert oder verkleinert sich das Spielfeld.

> Getter und Setter habe ich nur für Variablen stehen lassen, die nach 'außen' notwendig sind.

> Die Methode wertUebergabeSnake setzt die initiale Startposition der Schlange, das sollte in der Schlangen-Klasse erfolgen. deshalb hier entfernt.


PS: Nur wenn man sein Wissen 'weiter gibt' erweitert das den eigenen Horizont. Ich bin bei weitem nicht perfekt. Freut mich wenn ich helfen kann.

Kommentar von gut4fr5g4 ,

"Freut mich wenn ich helfen kann", auf jeden Fall, deine Antworten sind echt IMMER hilfreich, nochmal Danke an dieser Stelle, für diese lange und ich denke sehr zeitaufwendige Erklärung, hat mir sehr geholfen, ich habe jetzt einige Sachen mehr verstanden! 

Und durch die gute Erklärung zu deinem Codebeispiel kann ich alles sehr gut nachvollziehen!

Schönen Tag noch! :D

Kommentar von KnusperPudding ,

Danke und ebenso einen schönen Tag (bzw Wochenende). 

Programmieren lernen ist nicht immer unbedingt leicht, es gibt immer Stellen da steht man aus unerklärlichen Gründen 'auf dem Schlauch'.

Ich wurde auch oft bei meinen Fragen als ich Java gelernt habe, an Google verwiesen und hab Wochen und Monate damit verbracht mir das letztendlich alleine bei zu bringen und kann daher durchaus nachvollziehen wie es sich anfühlt wenn man keine Person hat, die einem gewisse Dinge erklärt.

Jedenfalls Hut ab, dass du dir das aus Eigeninitiative vor einer Ausbildung aneignest.

Kommentar von gut4fr5g4 ,

"keine Person hat, die einem gewisse Dinge erklärt" Hab ja dich! :D

Kommentar von gut4fr5g4 ,

achja eine frage noch zu deinem code: 

Wieso kein getter bei der stage? wieso hast du da nur einen setter benutzt?

Kommentar von KnusperPudding ,

Weil kein weiterer Zugriff von außen auf die Stage statt findet:

Die Stage stammt aus der start Methode der Application, wird an das Spielfeld weiter gegeben, welches das im gleichen auch an die Snake weiter gibt.

Auch wenn man theoretisch hätte einen getter einbauen können, so wäre das 'überflüssiger Code'. - Bzw. es wird auch verhindert, dass die Stage via getter von außen verändert wird, da man die Variable damit nach außen preis gibt.

Kommentar von gut4fr5g4 ,

aber das ist nur bei der stage so oder? also bei int double, etc ist das nicht so oder doch?

Kommentar von KnusperPudding ,

Es kommt immer drauf an, ob es 'gebraucht' wird oder nicht:

Instanz-Variablen sollten private sein, egal ob ein komplexer Datentyp oder primitiver.  - Zugriffe nach außen via getter und setter.

Ist es nicht vorgesehen, dass eine Variable nach außen vor dringt, lässt man das weg.

Antwort
von androhecker, 125

Du erstellst für die Klasse Move deine eigene Instanz von Spielfeld, dessen kästchen Array ist jedoch leer.

Noch ein bisschen Kritik:

1. Dein Timer wird nicht beendet, wenn das Fenster geschlossen wird -> es läuft ewig im Hintergund weiter.

2. Keine Umlaute in irgendwas.

3. Soll Move ein Substantiv sein? Sieht mir eher nach einem Verb aus, Klassen sind keine Dinge gemacht werden, sondern sie sind Dinge.

4. Wenn du eine Konstante groß schreibst, sollte sie auch final, also konstant sein.

5. Methodennamen vorne IMMER klein.

6. Dein if Konstrukt im Timertask ist höchst ineffizient. Ein else if wäre besser, ein switch sähe noch schöner aus.

7. Dann solltest du deine Zugriffslevel auch richtig setzen, wenn du die Fehler nicht selber siehst, kann dir da auch ein IDE helfen.

Kommentar von gut4fr5g4 ,

danke für die kritik! muss ich wohl doch noch einiges ändern, ich dachte projekte groß, packages klein und klassen groß am anfang?

ja if im timer habe ich jetzt viel effizienter gemacht

Wie kann ich denn den array "aktualisieren"?

Kommentar von androhecker ,

Nein nein. Du erstellst zwei Mal ein Spielfeld, in Main und in Move. Du brauchst aber nur ein einziges.

Kommentar von gut4fr5g4 ,

achso, habs jetzt geändert 

muss ich dann die Klassen so schreiben: "mainklasse" oder so: "mainKlasse"?

Kommentar von androhecker ,

Nein, Klassen vorne groß und CamelCase. Und Klasse oder Class schon gar nicht in den Name. Das ganze sollte so aussehen: (com, oder sonstige Domain tld).(example bzw deine Domain).(Programmname klein).(Programmname groß mit CamelCase) Das vordere sind deine Pakete und das letzte deine Hauptklasse in deinem Hauptpaket.

Kommentar von gut4fr5g4 ,

Ich meine Move im sinne von bewegung (also die bewegung -> the move)

Kommentar von androhecker ,

Ist trotzdem nicht ganz passend, die Klasse implementiert nur eine Methode, das könntest du genauso gut einfach in Spielfeld setzen. Wie schon gesagt, du solltest möglichst mit realen Objekten arbeiten. Die Klasse Snake, welche die Methode move() implementiert wäre wesentlich sinnvoller.

Kommentar von gut4fr5g4 ,

okay stimmt, ich packe dann die move in die klasse snake :D 

ich bin jetzt fast fertig! :D 

kannst mir dann ja, wenn du dann noch zeit und lust hast sagen ob das dann gut ist! :)

LG

Kommentar von androhecker ,

Klassennamen sind vorne immer noch groß, Snake und Move. Wo ist der Link zum Code?

Kommentar von gut4fr5g4 ,

ist noch was dazwischen gekommen, ich kann ihn doch erst morgen oder so schicken :/

Kommentar von gut4fr5g4 ,

Wann ist ein getter/setter sinnvoll?

Kommentar von androhecker ,

Eigentlich so gut wie immer.

Kommentar von gut4fr5g4 ,

also wirklich IMMER, wenn ich eine varible in einer anderen klasse aufrufe und diese zum beispiel nur minimal verändere, muss ich nen getter setter benutzen?

Kommentar von androhecker ,

Solltest du jedenfalls.

Kommentar von gut4fr5g4 ,

okay, mache ich

Kommentar von gut4fr5g4 ,

was bedeutet static bei variablen?

Kommentar von androhecker ,

Dass sie nicht an eine Instanz gebunden sind, also man kann sie aufrufen ohne eine Instanz zu haben. Konstanten sollte man zB als statisch machen, weil sie dann nicht für jede Instanz gespeichert werden -> weniger verbrauchter Arbeitsspeicher.

Kommentar von gut4fr5g4 ,

nenn mal ein beispiel für eine an eine instanz gebundene variable (weil kanst ja jede theoretisch ohne instanz abrufen oder woe meinst =c)

Kommentar von androhecker ,

Nein kann man nicht, man gehe mal von der Klasse Test aus. Wenn diese die statische Variable text enthält, kann man von außen (falls Zugriffsrechte vorhanden) direkt mittels Test.text darauf zugreifen oder innerhalb der Klasse auch in statischen Methoden. Bei Instanzvariablen muss man zuerst eine Instanz erstellen, also new Test(), damit überhaupt eine Variable text existiert. Dann gibt es aber auch wieder rum nur Zugriff über nicht statische Methoden oder von außen über das Objekt, also mit new Test().text. Du musst dir das so denken, eine Klasse ist in der Regel ein Bauplan für ein Objekt, also sind alle Instanzvariablen und Methoden Teil des erstellten Objektes. Statische Variablen/Methoden gehören dagegen zu keinem Objekt sondern nur zur Klasse.

Kommentar von gut4fr5g4 ,

ok danke! :D

Kommentar von gut4fr5g4 ,

muss ich den getter setter auch bei der stage machen? die ändere ich ja auch in einer anderen klasse, bei meinem quellcode?

Kommentar von androhecker ,

Ja.

Kommentar von gut4fr5g4 ,

ist denn auch der getter notwendig? denn ich habe es ohne ausprobiert und es hat trotzdem funktioniert

Kommentar von androhecker ,

Private Variablen und Getter ist immer besser als eine öffentliche Variable.

Kommentar von gut4fr5g4 ,

http://hastebin.com/eranorocay.avrasm

So guter quellcode? Wenn nein, was muss ich ändern, LG! :D

Kommentar von androhecker ,

Konstanten private static final machen und auch benutzen, nicht 20 als Feldgröße setzen und später wieder 20 beim Array eingeben. Auch scheint mir die ganze Logik hinter dem Spiel nicht sehr effektiv zu erscheinen, du brauchst zB in deathSnake 6 for Loops?

Kommentar von gut4fr5g4 ,

 ich muss jede seite detecten und die collision mit sich selbst (habe das jetzt in 5 for loops abgeändert 

Kommentar von gut4fr5g4 ,

was sind konstanten?

Kommentar von androhecker ,

Das solltest du wissen, eine Variable die ihren Wert immer behält. Bei dir ist das bei einigen Variablen der Fall (hast sie glaube ich auch mit Caps geschrieben), du hast sie aber nicht auf final gesetzt, also dass ihr Wert nicht geändert werden kann.

Kommentar von 4sdfxD ,

achso und wieso müssen die static sein?

Kommentar von androhecker ,

Weil sie unabhängig von der Instanz sind, die Feldgröße gilt für jedes Spielfeld das du erstellst, dann brauchst du nicht einen seperaten Wert für alles.

Kommentar von androhecker ,

Wieso erstellst du dauernd einen neuen Account?

Kommentar von gut4fr5g4 ,
Kommentar von androhecker ,

Sieht schon besser aus.

Kommentar von gut4fr5g4 ,

und was kann ich noch verbessern? also was ist noch verbesserungswürdig? bitte ins detail gehen

Kommentar von androhecker ,

Erst mal für eine Sprache entscheiden, am besten Englisch. Dann Namen verbessern, die Methode feld() hat keinen gerade aussagekräftigen Namen, genauso klingt deathSnake also Tod Schlange nicht gerade nach etwas, was man tut.

Kommentar von gut4fr5g4 ,

ok, das ändere ich, mit getter und setter und so alles gut?

Was kann ich sonst noch verbessern (Will mich jetzt immer weiter auf einen guten quellcode hinarbeiten, damit ich dann weiß, wie ein guter quellcode aussieht, ohne, dass ich es mir aus dem internet hole, was ich anfangs machen wollte, aber dann GLÜCKLICHERWEISE doch nicht getan habe)

LG

Kommentar von androhecker ,

Für mehr muss ich mir die Semantik mal anschauen, vom reinen aussehen bis auf äußerst lange Methoden nicht mehr so viel Schlimmes zu sehen.

Kommentar von gut4fr5g4 ,

und was ist das noch wenige schlimme? weil wenn du sagst "nicht mehr SO viel schlimmes", dann muss es ja noch etwas schlechtes geben

Kommentar von gut4fr5g4 ,

http://hastebin.com/iqudahuzef.avrasm

bei dieser klasse, muss ich bei den hboxen und so auch die sichtbarkeit und so vorschreiben, wenn nein, wann muss ich das davor schreiben und wann nicht? :c

Kommentar von androhecker ,

Das bezieht sich dann eher auf die Semantik, man könnte den Code übersichtlicher schreiben.

Kommentar von androhecker ,

Wenn du die HBox in einer Methode definierst, dann hat sowieso bloß die Methode darauf Zugriff.

Kommentar von gut4fr5g4 ,

stimmt

kannst du dir dann den quellcode nochmal genauer anschauen und sagen, was ich besser machen kann? bzw im detail sagen, was schlecht ist?

Kommentar von androhecker ,

Also speziell in der Spielfeld Klasse würde ich noch die Methode gameField umbennen. Dann würde ich den Code etwas mehr strukturieren, du definierst alles in einem großen Block, das macht es schwerer zu lesen. Am besten definierst du zum Beispiel alle statischen Konstanten ganz oben und lässt darunter ein bis zwei Zeilen frei. Die X und Y Konstanten könnte man auch in FIELD_WIDTH und FIELD_HEIGHT umbennen. Dann kannst du auch die Methoden etwas kleiner halten, wenn diese immer nur eine Sache machen, braucht man gar keine Kommentare mehr, weil sich das meiste von selbst und durch den Methodennamen erklärt.

Kommentar von gut4fr5g4 ,

Ach muss ich immer zwischen 2 worten bei einer final variable ein "_" machen?

Kommentar von androhecker ,

Ja, wie denn sonst.

Kommentar von gut4fr5g4 ,

Ja kann ja sein, dass man schreibt: "FIELDWIDTH", aber habs jetzt überall geändert :D

also soll ich alle hboxen und so und die vboxen in der klasse erstellen und dann unten in der methode definieren?

Kommentar von androhecker ,

Nein sollst du nicht, wenn du die Variablen nur in der einen Ausführung der Methode brauchst, müssen sie auch keine Objektvariablen sein.

Kommentar von gut4fr5g4 ,

ok und was kann ich noch ändern?

Kommentar von gut4fr5g4 ,

??

Kommentar von gut4fr5g4 ,

sag mal pls :D

Keine passende Antwort gefunden?

Fragen Sie die Community

Weitere Fragen mit Antworten