7.7 KiB
Explain the code
Eigene Erklärung einer Funktion
public Level1World(int score, int leben) aus der Klasse Level1World:
Diese Funktion hat die Integer (Ganzzahlen) score und leben als Übergabeparameter.
Die Übergabeparameter legen fest, wie viele Punkte und Leben ein Spieler am Start des Spiel haben.
In der Methode selber, wird mit "super" auf den Konstruktor der Elternklasse LabyrinthWorld zugegriffen.
Es wird eine Instanz von Level1World erstellt, die von LabyrinthWorld erbt.
Mit der Methode "baueLevel", wird mit der Variable "KARTE" (festes Feld mit final deklariert)
aus der Level1World-Klasse eine Welt erzeugt.
KI-Erklärung der Funktion
Das ist der Konstruktor der Klasse Level1World – er wird immer dann ausgeführt, wenn irgendwo im Code new Level1World(...) steht (z. B. beim Levelwechsel in Level2World.naechstesLevel() mit new Level1World(), was intern this(0, 3) und damit letztlich diesen Konstruktor mit score=0, leben=3 aufruft). Zeile für Zeile:
Kopfzeile public Level1World(int score, int leben): Der Konstruktor nimmt zwei int-Werte entgegen. Diese kommen entweder als Startwerte (0 Punkte, 3 Leben) oder – falls der Spieler bereits Level 1 zum zweiten Mal betritt (z. B. nach Game Over) – mit fortgeschrittenem Punktestand. super(KARTE[0].length(), KARTE.length, 40, score, leben, "Level 1");: Das ist zwingend die erste Anweisung in jedem Konstruktor, der eine Elternklasse mit eigenem Konstruktor besitzt – Java erlaubt hier keine andere Reihenfolge. Aufgerufen wird der Konstruktor von LabyrinthWorld, mit sechs Argumenten:
KARTE[0].length() – Länge der ersten Zeile des Karten-Arrays, also die Anzahl der Spalten (Zeichen pro Zeile in der Textkarte) KARTE.length – Anzahl der Zeilen im Array, also die Anzahl der Kartenreihen 40 – Zellgröße in Pixel pro Gitterfeld score, leben – werden 1:1 durchgereicht "Level 1" – der Name, der später im HUD angezeigt wird
LabyrinthWorld's Konstruktor nutzt diese Werte, um über super(spalten, zeilenOhneHUD + 1, zellGroesse) wiederum den World-Konstruktor aufzurufen (die tatsächliche Weltgröße plus einer zusätzlichen HUD-Zeile), und speichert score, leben und levelName in den entsprechenden Feldern der Klasse. baueLevel(KARTE);: Nach Abschluss des super(...)-Aufrufs existiert die Welt bereits in der richtigen Größe, ist aber noch leer. Diese Zeile ruft die von LabyrinthWorld geerbte Methode baueLevel(...) auf und übergibt ihr das statische Karten-Array KARTE dieser Klasse. baueLevel liest das Array Zeichen für Zeichen aus und platziert je nach Zeichen (#, ., P, E) die passenden Actor-Objekte (Wand, Punkt, Maus, Katze) an der entsprechenden Gitterposition in der Welt.
Prompt → Verify
(a) Was tut die KI generierte Funktion?
Die KI erzeugte eine neue Klasse "Kaese", mit dessen die Maus ein Power-Up erhält und Katzen besiegen kann.
(b) Welche Zeile verstehe ich nicht?
Prompt (Claude: Modell Sonnet 5):
Erkläre mir folgende Methode, was diese im Programm macht:
private GreenfootImage erzeugeKaeseBild()
{
GreenfootImage bild = new GreenfootImage(16, 16);
bild.setColor(new Color(255, 205, 40));
bild.fillOval(0, 0, 16, 16);
bild.setColor(new Color(205, 150, 20));
bild.fillOval(3, 3, 3, 3);
bild.fillOval(9, 8, 3, 3);
bild.fillOval(5, 11, 2, 2);
return bild;
}
Wieso ist diese Methode als private und nicht als public deklariert?
Antwort:
Was die Methode macht
erzeugeKaeseBild() gehört zur Klasse Kaese und erzeugt im Code (ohne externe Bilddatei) ein 16×16 Pixel großes Bild, das im Spiel als Käse-Symbol dargestellt wird. Sie wird im Konstruktor von Kaese aufgerufen und das Ergebnis per setImage(...) dem Actor zugewiesen.
Zeile für Zeile:
-
GreenfootImage bild = new GreenfootImage(16, 16);– Erzeugt eine leere Zeichenfläche von 16×16 Pixeln (standardmäßig transparent). -
bild.setColor(new Color(255, 205, 40));– Stellt die "Zeichenfarbe" auf ein kräftiges Gelb (RGB-Werte: viel Rot, mittel Grün, wenig Blau). -
bild.fillOval(0, 0, 16, 16);– Zeichnet eine gefüllte Ellipse (hier: einen Kreis, da Breite = Höhe = 16) beginnend bei Position (0,0) mit 16 Pixeln Breite und Höhe. Das ist der gelbe Grundkörper des Käses und füllt die gesamte Bildfläche aus. -
bild.setColor(new Color(205, 150, 20));– Wechselt die Zeichenfarbe zu einem dunkleren Gelb-Braun (für die "Käselöcher"). -
bild.fillOval(3, 3, 3, 3);/bild.fillOval(9, 8, 3, 3);/bild.fillOval(5, 11, 2, 2);– Zeichnet drei kleine, unterschiedlich positionierte und unterschiedlich große Kreise über den gelben Grundkörper. Das sind die typischen "Löcher" im Käse, an drei verschiedenen Stellen platziert, damit es nicht zu symmetrisch/künstlich aussieht. -
return bild;– Gibt das fertig gezeichnete Bild an den Aufrufer zurück (den Konstruktor vonKaese).
Kurz gesagt: Die Methode "malt" ein kleines Käse-Icon Schritt für Schritt wie mit einem Zeichenprogramm – erst die Grundform, dann Details darüber.
Warum private und nicht public?
Weil diese Methode ein reines internes Implementierungsdetail der Klasse Kaese ist – sie wird ausschließlich von Kaese selbst benötigt (im Konstruktor aufgerufen), nicht von anderen Klassen.
Das folgt dem Prinzip der Kapselung (Encapsulation): Eine Klasse sollte nach außen nur zeigen, was sie kann (ihre öffentliche Schnittstelle, z. B. "ein Käse-Objekt lässt sich erzeugen und in die Welt einfügen"), aber nicht wie sie es intern umsetzt.
Konkrete Gründe, warum public hier keinen Sinn ergäbe:
-
Kein Anwendungsfall von außen: Keine andere Klasse (
Maus,LabyrinthWorld, ...) muss jemals "nur das Bild erzeugen, ohne ein Kaese-Objekt anzulegen". Der einzige sinnvolle Aufrufer ist der eigene Konstruktor. -
Freiheit für spätere Änderungen: Da die Methode
privateist, kann sie beliebig umbenannt, umgeschrieben oder sogar entfernt werden (z. B. später durch ein echtes Bild aus der Bildergalerie ersetzt), ohne dass irgendein anderer Code im Projekt kaputtgeht. Wäre siepublic, müsste man sicherstellen, dass niemand sonst im Projekt darauf zugreift, bevor man sie ändert. -
Weniger Möglichkeiten für Fehler: Wäre die Methode
public, könnte theoretisch jede andere KlasseneuesKaesenObjekt.erzeugeKaeseBild()aufrufen und selbst irgendwelche Bilder damit erzeugen und herumreichen – das hat aber nichts mit der eigentlichen Aufgabe der Methode zu tun und würde nur unnötige Abhängigkeiten schaffen.
Eine gute Faustregel, die du auch deinen Schüler:innen mitgeben kannst: Eine Methode ist so lange private, bis es einen konkreten Grund gibt, sie von außen aufrufbar zu machen. Man startet also mit der restriktivsten Sichtbarkeit und öffnet sie nur bei Bedarf – nicht umgekehrt.
Find-the-Bug / Code-Review
Die KI hat das Spiel mit Herzen erweitert.
Anstelle, dass die Maus aber ein Leben dazugewinnt, wenn sie ein Herz erhält, werden ihre Leben auf eins gesetzt.
Das ist der Bug in folgender Methode von LabyrinthWorld:
public void lebenGewonnen()
{
leben = 1;
aktualisiereHUD();
}
So wird der Fehler behoben:
public void lebenGewonnen()
{
leben ++;
aktualisiereHUD();
}
Selbst → KI-Vergleich
Die von mir erzeugte Funktion ist verständlicher, da sie auf das bereits existierende Projekt aufbaut und eine einfachere Implementierung verwendet. Der KI-Code ist zwar strukturierter und erfüllt mehr den "Best-Practice" Kriterien, jedoch erfordert der KI-Code viele Java-Kenntnisse.