Einführung in Zustandsautomaten
Bearbeite den Abschnitt zur Einführung in Zustandsautomaten unter inf-schule.de. Bearbeite die Programmieraufgaben mit Scratch wie angegeben oder mit Greenfoot.
Informiere Dich über Konstanten und Enum-Typen in Java. Inwiefern können sie hier hilfreich sein?
Aufgabe - Zeichenstift
Bearbeite den Abschnitt Fallstudie - Zeichenstift mit Scratch wie angegeben oder mit Greenfoot. (Achtung: In Greenfoot musst Du verhindern, dass beim Drücken einer Taste der Zustand evtl. mehrfach hin- und herwechselt)
Aufgabe - Feuer frei

Du sollst ein kleines Greenfoot-Spiel fertig programmieren, bei dem eine Mutter ihrem Kind Essen zuwirft. Je länger Du die Leertaste drückst, desto weiter wirft sie. Eine fertige Version des Spiels kannst Du Dir zum Testen herunterladen. Eine Vorlage zum Spiel, das die entsprechenden Grafiken und einige Teile der Implementierung enthält, kannst Du Dir ebenfalls herunterladen.
Das Problem bei der Implementierung ist: Es gibt in Greenfoot keine Methode, um das Loslassen einer Taste zu erkennen.
Überlege Dir wie zustandsbasierte Modellierung Dir hier helfen kann, zeichne ein Zustandsdiagramm und implementiere das System.
Übersicht zu UML-Zustandsdiagrammen
- Zustände werden in abgerundeten Kästen dargestellt
- Ein Zustand hat einen Namen und kann haben:
- Eintrittsaktion: Wird beim Betreten eines Zustands ausgeführt. Diese wird mit dem reservierten Wort
entry/...
markiert. - Austrittsaktion: Wird beim Verlassen ausgeführt und mit
exit/...
markiert. - Aktivitäten: Werden während eines Zustands dauerhaft ausgeführt und mit
do/...
markiert. - interne Transitionen: Beliebige Ereignisse, die keinen Zustandsübergang bewirken, aber Aktionen auslösen können.Eintritts- und Austrittsaktionen werden nicht ausgeführt.
- Transitionen bezeichnen die Übergänge zwischen Zuständen. Sie sind markiert mit dem Ereignis, das sie auslösen. Zusätzlich kann in eckigen Klammern eine Bedingung (engl. Sprechweise: guard) angegeben werden. Durch Schrägstrich getrennt kann eine Aktion angegeben werden, die beim Übergang ausgeführt wird.
- Ein Zustandsdiagramm besitzt genau einen Startzustand, der durch einen ausgefüllten Kreis dargestellt wird.
- Ein Zustandsdiagramm kann beliebig viele Endzustände besitzen. Diese werden durch einen ausgefüllten "Doppelkreis" dargestellt.
Aufgabe - Streuner
Als streunender Hund kann man viel erleben. Überlege Dir welche Zustände ein streunender Hund haben kann, und welche Ereignisse auftreten können. Stelle Deine Überlegungen als UML-Zustandsdiagramm dar.
Implementiere Dein System in Greenfoot.
Modellierung einer Ampel
Im oben dargestellten Screencast siehst Du eine vereinfachte Ampelsteuerung.
- Betrachte den Film und zeichne ein passendes Zustandsdiagramm.
- Du benötigst für die Implementierung Nebenläufigkeit. Eine Möglichkeit dies hier umzusetzen bieten z.B. die Klassen
Timer
undTimerTask
. Seit Java 5 existiert mit der KlasseScheduledThreadPoolExecutor
noch eine weitere Alternative, die insbesondere durch Lambda-Ausdrücke interessant ist. Ein Beispiel für deren Anwendung siehst Du unten. Teste und vergleiche die beiden Varianten. Nutze die Dokumentation der Java-API, um die Beispiele zu verstehen. - Implementiere das Modell.
Timer-Beispiel
import java.util.*; class PingPongTimer { Timer timer; public PingPongTimer() { timer = new Timer(); ping(); } private void ping() { System.out.println("Ping"); timer.schedule(new TimerTask() { @Override public void run() { pong(); } }, 2000); } private void pong() { System.out.println("Pong"); timer.schedule(new TimerTask() { @Override public void run() { ping(); } }, 2000); } public void anhalten() { System.out.println("Stop"); timer.cancel(); } }
ScheduledThreadPoolExecutor-Beispiel
import java.util.concurrent.*; class PingPongExecutor { ScheduledThreadPoolExecutor timer; public PingPongExecutor() { timer = new ScheduledThreadPoolExecutor(1); ping(); } private void ping() { System.out.println("Ping"); timer.schedule(() -> pong(), 2, TimeUnit.SECONDS); } private void pong() { System.out.println("Pong"); timer.schedule(() -> ping(), 2, TimeUnit.SECONDS); } public void anhalten() { System.out.println("Stop"); timer.shutdownNow(); } }