Viele Anwendungen kennen verschiedene Zustände. Zum Beispiel eine Stoppuhr: ruhend bei 00:00:00, Zeit laufend, Zwischenzeit anzeigen, Endzeit anzeigen oder ähnlich.
Die kleine Simulation oben zeigt die Grundidee von Zuständen in Anwendungen.
Welche Zustände kennt die kleine Applikation?
Richtig, drei Zustände 'Start', 'Spiel' und 'Ende'.
Welche Ereignisse lassen die Simulation von einem Zustand in einen anderen wechseln?
Grafisch lässt sich dies als Zustandsdiagramm darstellen:
Mit welcher Programmstruktur lassen sich Zustände einfach programmieren?
Mit der switch
-Anweisung lässt sich die Unterscheidung der Zustände einfach realisieren:
switch(zustand) { case 0: startBildschirm(); break; case 1: spielen(); break; case 2: endBildschirm(); break; }
Erweitern Sie das Programm so, dass mit der Taste 's' vom Zustand 2 (Ende) direkt in den Zustand 1 (Spiel) gewechselt werden kann. Prüfen Sie zwei Möglichkeiten...
// Deklaration globale Variablen int zustand = 0; int xPos; int yPos; int richtung; int v = 2; // setup()-Prozedur wird beim Programmstart einmal ausgeführt void setup() { size(300, 300); textSize(24); textAlign(CENTER, CENTER); } // draw()-Prozedur wird während Laufzeit dauernd wiederholt void draw() { switch(zustand) { case 0: startBildschirm(); break; case 1: spielen(); break; case 2: endBildschirm(); break; } } // wird bei jedem Tastendruck einmal ausgeführt void keyPressed() { if (key=='S' || key=='s' && zustand == 0) { initialisieren(); zustand = 1; } if (key==ENTER && zustand == 2 || key==RETURN && zustand == 2) { zustand = 0; } } void startBildschirm() { background(150,150,255); fill(30, 50, 255); text("Anleitung...\n\nlos gehts mit 's'", width/2, height/2); } void initialisieren() { xPos = int(random(width)); yPos = int(random(height)); richtung = int(random(4)); } void spielen() { background(255, 196, 47); fill(210, 40, 50); bewegen(); test(); ellipse(xPos, yPos, 20, 20); } void bewegen() { switch(richtung) { case 0: yPos = yPos - v; break; case 1: xPos = xPos + v; break; case 2: yPos = yPos + v; break; case 3: xPos = xPos - v; break; } } void test() { if (xPos < 0 || xPos > width || yPos < 0 || yPos > height) { zustand = 2; } } void endBildschirm() { background(30, 255, 50); fill(30, 50, 255); text("Ende\nrestart mit RETURN", width/2, height/2); }
Man kann einerseits eine weitere if
-Anweisung in die Prozedur keyPressed
einfügen:
if (key=='S' || key=='s' && zustand == 2) { initialisieren(); zustand = 1; }
Einfacher lässt sich dies mit einer erweiterten if
-Anweisung in der Prozedur keyPressed
realisieren:
if (key=='S' || key=='s' && zustand == 0 || zustand == 2) { initialisieren(); zustand = 1; }
Wie sieht das erweiterte Zustandsdiagramm aus? Zeichnen Sie!
Zustände werden optimal als Konstanten implementiert. Z.B. in Java:final int START = 0;
final int SPIEL = 1;
etc.
Verbessern Sie den Programmcode aus Aufgabe 4 entsprechend. Wo braucht es überall Anpassungen?
Haben Sie die Konstante START bei der Initialisierung der Variable Zustand verwendet (vgl. Zeile 7)?
// Deklaration Zustands-Konstanten final int START = 0; final int SPIEL = 1; final int ENDE = 2; // Deklaration globale Variablen int zustand = START; int xPos; int yPos; int richtung; int v = 2; // setup()-Prozedur wird beim Programmstart einmal ausgeführt void setup() { size(300, 300); textSize(24); textAlign(CENTER, CENTER); } // draw()-Prozedur wird während Laufzeit dauernd wiederholt void draw() { switch(zustand) { case START: startBildschirm(); break; case SPIEL: spielen(); break; case ENDE: endBildschirm(); break; } } // wird bei jedem Tastendruck einmal ausgeführt void keyPressed() { if (key=='S' || key=='s' && zustand == START) { initialisieren(); zustand = SPIEL; } if (key==ENTER && zustand == 2 || key==RETURN && zustand == 2) { zustand = START; } } void startBildschirm() { background(150,150,255); fill(30, 50, 255); text("Anleitung...\n\nlos gehts mit 's'", width/2, height/2); } void initialisieren() { xPos = int(random(width)); yPos = int(random(height)); richtung = int(random(4)); } void spielen() { background(255, 196, 47); fill(210, 40, 50); bewegen(); test(); ellipse(xPos, yPos, 20, 20); } void bewegen() { switch(richtung) { case 0: yPos = yPos - v; break; case 1: xPos = xPos + v; break; case 2: yPos = yPos + v; break; case 3: xPos = xPos - v; break; } } void test() { if (xPos < 0 || xPos > width || yPos < 0 || yPos > height) { zustand = ENDE; } } void endBildschirm() { background(30, 255, 50); fill(30, 50, 255); text("Ende\nrestart mit RETURN", width/2, height/2); }