Merge pull request 'unterrichtseinheit' (#1) from unterrichtseinheit into main
Reviewed-on: #1
This commit is contained in:
commit
c96bc1a918
9 changed files with 176 additions and 0 deletions
BIN
unterrichtseinheit/Anforderungskatalog.docx
Normal file
BIN
unterrichtseinheit/Anforderungskatalog.docx
Normal file
Binary file not shown.
21
unterrichtseinheit/Bildungsplan.md
Normal file
21
unterrichtseinheit/Bildungsplan.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
• Bundesland: Baden-Württemberg<br>
|
||||
• Schulart: Berufliches Gymnasium (TGI)<br>
|
||||
• Klassenstufe: 11. Klasse. Vorkenntnisse nicht erforderlich.<br>
|
||||
• Kompetenzen: <br>
|
||||
Die Schülerinnen und Schüler erstellen und implementieren einfache Spiele.
|
||||
|
||||
Aus <https://www.bildungsplaene-bw.de/In_OS#TGI+%28Wahlbereich%29%3A+Spielprogrammierung>
|
||||
|
||||
Zusätzlich erwerben die Sus die Kompetenz, Programme nach dem OOP Paradigma zu erstellen, welches für die Jahrgangsstufe 2 erforderlich ist.
|
||||
|
||||
• Stoffverteilungsplan: 2. Halbjahr der 11. Klasse. <br>
|
||||
Es sind keine Voraussetzungen seitens der SuS erforderlich.<br>
|
||||
• Zielformulierung je Stunde: Die SuS können eine IDE bedienen, Python installieren und ein eigenes Projekt erstellen. <br>
|
||||
• Material & Methode: PC, Arbeitsblatt. Methode: Objects First.
|
||||
|
||||
Programmiersprache und Framework: Java und Greenfoot. Vorbereitung für die Prüfung und OOP.
|
||||
IDE: VsCode
|
||||
|
||||
Webseiten, für das Schulprojekt:<br>
|
||||
https://www.informatikzentrale.de/greenfoot-3-lernen/<br>
|
||||
https://cseducators.stackexchange.com/questions/666/justification-for-an-objects-early-approach-to-introductory-programming
|
||||
BIN
unterrichtseinheit/Differenzierung.docx
Normal file
BIN
unterrichtseinheit/Differenzierung.docx
Normal file
Binary file not shown.
BIN
unterrichtseinheit/Makroplanung.docx
Normal file
BIN
unterrichtseinheit/Makroplanung.docx
Normal file
Binary file not shown.
52
unterrichtseinheit/Mikroplanung.md
Normal file
52
unterrichtseinheit/Mikroplanung.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
## Mikroplanung: Unterrichtseinheit "Kollision & Interaktion"
|
||||
|
||||
Diese Planung umfasst die Doppelstunde (Stunden 5-6) des Greenfoot-Projekts in der Eingangsklasse (11. Klasse TGI).
|
||||
|
||||
### 1. Stundenlernziel
|
||||
**Hauptlernziel:** Die Schüler können die Kollision zwischen Pac-Man und Sammelobjekten erkennen und diese bei Berührung aus der Welt entfernen.
|
||||
|
||||
**Teilziele:**
|
||||
* Die Lernenden wenden If-Bedingungen gezielt für die Kollisionslogik an.
|
||||
* Die Lernenden verstehen Objektinteraktionen durch Methodenaufrufe (z. B. `this.intersects(punkt)`).
|
||||
* Die Lernenden vertiefen das grundlegende Konzept von Klassen und Instanzen.
|
||||
|
||||
---
|
||||
|
||||
### 2. Tabellarischer Verlaufsplan (90 Minuten)
|
||||
|
||||
| Phase (Zeit) | Lehreraktivität (L) | Schüleraktivität (SuS) | Sozialform / Medien |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **Einstieg** (10 Min) | L präsentiert ein fehlerhaftes Spiel: Die Spielfigur läuft durch Objekte hindurch. L fragt nach dem Problem. | SuS erkennen das Problem und formulieren Lösungsansätze ("Wenn Pac-Man die Pille berührt..."). | Plenum / Beamer |
|
||||
| **Erarbeitung 1** (30 Min) | L verweist auf die Greenfoot-API zur Kollisionserkennung, die Lerntheke (eine Sammlung welche die wichtigsten Greenfoot-Methoden enthält) und gibt Hilfekarten aus. | SuS programmieren die Kollisionsabfrage in der `act()`-Methode mittels If-Abfragen, um Objekte zu entfernen. | Einzelarbeit / PC |
|
||||
| **Sicherung** (15 Min) | L bittet 1-2 SuS um ein kurzes "Code-Review". L sichert Fachbegriffe wie Methodenaufruf und Instanz. | SuS erklären ihren Quellcode am Beamer und begründen ihre Methodenwahl. Restliche SuS korrigieren Fehler. | Plenum / Beamer |
|
||||
| **Erarbeitung 2 / Transfer** (25 Min) | L erteilt Differenzierungsaufträge: Erweiterung der Mechaniken (Pflicht- vs. Zusatzaufgaben). | SuS wenden das Prinzip auf neue Objekte an (z. B. Power-Ups) oder bauen Soundeffekte ein (nur leistungsstarke SuS). | Einzelarbeit / PC |
|
||||
| **Abschluss** (10 Min) | L fasst Konzepte (Verzweigung, Kollision) zusammen. Ausblick: "Wie speichern wir die gesammelten Punkte?". | SuS speichern Projekte und gleichen ihren Stand mit dem verbindlichen Grundniveau ab. | Plenum |
|
||||
|
||||
---
|
||||
|
||||
### 3. Didaktische Reduktion
|
||||
Die komplexe mathematische Abfrage einer 2D-Kollision (wie das Vergleichen von X/Y-Koordinaten mittels Vergleichs- und arithmetischer Operatoren) wird durch das Greenfoot-Framework stark vereinfacht. Anstatt mathematische Hitboxen zu berechnen, nutzen die SuS vorbereitete Methoden wie `this.intersects(punkt)`.
|
||||
**Begründung:** Das Hauptziel der Eingangsklasse TGI ist das Verständnis der Objektorientierung. Der kognitive Fokus liegt daher auf den Nachrichten zwischen Objekten und den Kontrollstrukturen (If-Abfragen für die Kollisionslogik), nicht auf der Vektormathematik.
|
||||
|
||||
---
|
||||
|
||||
### 4. Differenzierung (Pauschal & Quantitativ/Qualitativ)
|
||||
Um die stark schwankenden Vorkenntnisse (z. B. Realschüler mit Scratch vs. Anfänger) aufzufangen, werden folgende Maßnahmen eingesetzt:
|
||||
|
||||
* **Gestufte Hilfekarten (Pauschal):**
|
||||
* *Stufe 1:* Leitfrage ("Welche If-Bedingung wird benötigt, wenn der Spieler ein Objekt berührt?").
|
||||
* *Stufe 2:* Teilhinweis mit Codefragment.
|
||||
* *Stufe 3:* Vollständiges Lösungsbeispiel für die Kollision.
|
||||
* **Pflicht- und Kürbereich (Quantitativ & Qualitativ):**
|
||||
* *Grundniveau (Pflicht):* Einfache Sammelobjekte werden bei Kollision fehlerfrei entfernt.
|
||||
* *Erweitertes Niveau (Kür):* Leistungsstarke SuS integrieren Power-Ups oder verknüpfen die Kollision zusätzlich mit Soundeffekten.
|
||||
|
||||
---
|
||||
|
||||
### 5. Bezug zum Bewertungsbogen
|
||||
Diese Stunde bereitet die SuS essenziell auf die Säule **"Code & Technik"** vor, welche 50% der Bewertung ausmachen. Folgende Kriterien können nach dieser Stunde nachweisbar überprüft werden:
|
||||
|
||||
* **Kontrollstrukturen & Logik (20%):** Korrekter Einsatz von If-Bedingungen und fehlerfreie Kollisionsabfrage.
|
||||
* **Objektorientierung (15%):** Saubere Kommunikation zwischen Objekten (z. B. Spieler ruft Methode beim Punkt auf).
|
||||
* **Bewertungsbogen Spielablauf:** "Funktioniert die Kollision?" (5 Punkte) und "Werden Methoden sinnvoll eingesetzt?" (5 Punkte).
|
||||
BIN
unterrichtseinheit/PacManClone.zip
Normal file
BIN
unterrichtseinheit/PacManClone.zip
Normal file
Binary file not shown.
BIN
unterrichtseinheit/PacManCloneKIVariante.zip
Normal file
BIN
unterrichtseinheit/PacManCloneKIVariante.zip
Normal file
Binary file not shown.
BIN
unterrichtseinheit/Spielskizze.docx
Normal file
BIN
unterrichtseinheit/Spielskizze.docx
Normal file
Binary file not shown.
103
unterrichtseinheit/Umsetzung_Begleiten.md
Normal file
103
unterrichtseinheit/Umsetzung_Begleiten.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Explain the code
|
||||
## Eigene Erklärung einer Funktion
|
||||
<b>public Level1World(int score, int leben)</b> aus der Klasse <b>Level1World</b>: <br>
|
||||
Diese Funktion hat die Integer (Ganzzahlen) score und leben als Übergabeparameter.<br>
|
||||
Die Übergabeparameter legen fest, wie viele Punkte und Leben ein Spieler am Start des Spiel haben.<br>
|
||||
In der Methode selber, wird mit "super" auf den Konstruktor der Elternklasse LabyrinthWorld zugegriffen. <br>
|
||||
Es wird eine Instanz von Level1World erstellt, die von LabyrinthWorld erbt.<br>
|
||||
Mit der Methode "baueLevel", wird mit der Variable "KARTE" (festes Feld mit final deklariert) <br>
|
||||
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?
|
||||
<b>Prompt (Claude: Modell Sonnet 5): </b><br>
|
||||
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: <br>
|
||||
## 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 von `Kaese`).
|
||||
|
||||
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:
|
||||
|
||||
1. **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.
|
||||
|
||||
2. **Freiheit für spätere Änderungen**: Da die Methode `private` ist, 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 sie `public`, müsste man sicherstellen, dass niemand sonst im Projekt darauf zugreift, bevor man sie ändert.
|
||||
|
||||
3. **Weniger Möglichkeiten für Fehler**: Wäre die Methode `public`, könnte theoretisch jede andere Klasse `neuesKaesenObjekt.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. <br>
|
||||
Anstelle, dass die Maus aber ein Leben dazugewinnt, wenn sie ein Herz erhält, werden ihre Leben auf eins gesetzt. <br>
|
||||
Das ist der Bug in folgender Methode von LabyrinthWorld: <br>
|
||||
public void lebenGewonnen()
|
||||
{
|
||||
leben = 1;
|
||||
aktualisiereHUD();
|
||||
}
|
||||
So wird der Fehler behoben:<br>
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in a new issue