In dieser Übung nutzen wir den Editor von MakeCode. Den Editor findest du auf unserer Website oben in der Navigation unter: Programmieren - Editor.
Permalink: https://makecode.com/_UiRhMbRRvWUM
Je nachdem, welcher Modus gerade Aktiv ist soll unterschiedlicher Code ausgeführt werden. Dafür erstellen wir eine Wenn-Dann-Abfrage und legen für jeden Modus eine Bedingung fest. Hier eine Kurze Übersicht der benötigten Modi. Am ende unter Punk 7 gibt es noch einmal eine Zusammenfassung und ausführliche Beschreibung eben dieser,
Setzten:
In diesem Modus können beide Spieler ihre Schiffe setzen. Das die Schiffe regelkonform gesetzt werden kann der Calliope nicht überprüfen - aber das fällt ja auch spätestens beim Spielen auf und da setzen wir mal auf ein Faires Spielverhalten.
Angriff:
Der Spieler, welcher sich in diesem Modus befindet kann ein Feld des anderen Spielers angreifen.
Verteidigung:
In dem Modus kann man nur auf den Angriff des anderen Spielers warten.
Gewonnen:
Das Spiel ist vorbei, der Spieler hat gewonnen.
Verloren:
Das Spiel ist vorbei, der andere Spieler hat gewonnen.
Senden Angriff:
Wenn der Spieler den Angriff ausgelöst hat wechselt der Calliope in diesen Modus, um die Koordinaten des angegriffenen Feldes an den Mitspieler zu funken.
Senden Verteidigung:
Wenn der Spieler den Angriff empfangen hat wechselt er in diesen Modus, um das Ergebnis, also ob ein Treffer erzielt wurde oder nicht, an den Mitspieler zurück zu funken.
Teamwahl:
Wer als erstes seine Schiffe fertig gesetzt hat beginnt mit dem Angriff. Da dieser erst stattfinden kann, wenn der Mitspieler auch seine Schiffe gesetzt hat "wartet" der Spieler so lange in diesem Modus.
Beim Start werden benötigte Variablen festgelegt:
Für die eigenen Schiffe und die eigenen Schüsse wird jeweils ein mehrdimensionales Array angelegt. Die mehrdimensionalen Arrays enthalten jeweils 5 Arrays mit je 5 Nummern, für jede LED (Pixel) auf dem Calliope eine. Die erste Dimension entspricht dem Y-Wert und die Zweite dem X-Wert auf der LED Matrix. Zu beginn sind alle Nummern auf 0 gesetzt. Im Spielverlauf werden diese Pixel auf unterschiedliche Werte gesetzt, welche jeweils einen bestimmten Zustand repräsentieren:
Schiffe:
0 = kein Schiff
1 = Ein Schuss des Gegners, welcher im Wasser gelandet ist
2 = Ein Treffer des Gegners auf ein eigenes Schiff
9 = Ein eigenes Schiff
Schüsse:
0 = noch nicht beschossenes Feld
1 = Ein eigener Schuss auf den Gegner, welcher im Wasser gelandet ist
9 = Ein Treffer auf das gegnerische Schiff
Die LED auf dem Calliope Mini können über X- und Y-Werte angesprochen werden. Die erste LED ist x=0,y=0. Die letzte LED x=4,y=4. Um das „Fadenkreuz“ zu beginn in die Mitte zu setzen werden die Variablen „fadenkreuz_x“ und „fadenkreuz_y“ beide auf 2 gesetzt.
Als nächstes Definieren wir eine Variable, in der der aktuelle Modus gespeichert wird. Je nach dem, welcher Modus aktiv ist, soll der MINI anderen Code ausführen. In der Dauerhaft-Schleife wird das mit einer umfangreichen Wenn-Dann-Abfrage umgesetzt. Zum Start müssen die Schiffe gesetzt werden, daher legen wir die Variable auf „setzen“ fest.
Als letztes definieren wir in der Variable „max_schiffe“, wie viele Schiffe gesetzt werden dürfen.
Desweiteren werden folgende Variablen benötigt, aber erst mal nicht weiter Definiert (ihr Wert ist also 0):
team: Darin wird gespeichert, wer als erstes Angreift.
schiffe_gesetzt: Speichert, wie viele Schiffe gesetzt wurden.
treffer: Speichert, wie viele Treffer der Gegner erzielt hat.
ergebniss: Speichert das Ergebniss des gegnerischen Angriffs.
angriff_x: Speichert die X-Koordinate des gegnerischen Angriffs
angriff_y: Speichert die Y-Koordinate des gegnerischen Angriffs
Da MakeCode die Übergabe von Variablen in Funktionen noch nicht unterstützt müssen zum zwischenspeichern diese Variablen erstellt werden.
anschalten_array
anschalten_wert
Setzen
Wenn die anzahl der gesetzten Schiffe der in „max_schiffe“ festgelegten Zahl entspricht, dann wird der Modus auf „teamwahl“ geändert und das Fadenkreuz auf die Mitte zurückgesetzt.
Im Modus Setzen sollen die gesetzten Schiffe und das Fadenkreuz dargestellt werden. Dazu wird die Funktion „LED_Setzen“ aufgerufen.
Angriff
Im Modus Angriff sollen die bisherigen Schüsse und das Fadenkreuz dargestellt werden. Dazu wird die Funktion „LED_Angriff“ aufgerufen.
Verteidigung
Im Modus Verteidigung wird der Wert “funk_ende = 0“ gesendet, um dem anderen MINI mitzuteilen, dass der Verteidigungsmodus Aktiv ist und somit eine neue „Funk-Unterhaltung“ für den nächsten Angriff beginnen kann.
Mit der Funktion „AufAngriffPruefen“ wird dann überprüft, ob vom nächsten Angriff bereits der X- und Y-Wert empfangen wurde und gegebenenfalls der Modus zu „senden_Verteidigung“ gewechselt.
Mit der Funktion „LED_Verteidigung werden die eigenen Schiffe und die bisherigen Schüsse des Gegners dargestellt.
Gewonnen
Im Modus gewonnen wird ein Smiley angezeigt
Verloren
Das Ergebnis wird an den anderen MINI gesendet, damit dieser weiß, dass er gewonnen hat.
Anschließend wird ein trauriger Smiley angezeigt.
Senden Angriff
Die RGB-LED wird auf Orange gesetzt.
Anschließend wird erst der Y-, dann der X-Wert des Fadenkreuzes als Angriff gesendet.
Senden Verteidigung
Die RGB-LED wird auf Blau gesetzt.
Der angegriffene Pixel wird in einer für-Schleife 20x geschalten. Also 10 mal an und 10 mal aus, mit einer pause von je 50 ms.
Die beiden Angriff Variablen werden auf -1 zurück gesetzt.
Das Ergebnis des Angriffes wird in der Variable “a_rueckgabe“ an den anderen MINI gesendet.
Teamwahl
Wenn die Variable „team“ bereits auf 1 steht, Dann geht der MINI in den Modus „verteidigung“.
Ansonsten wird der wert „team = 1“ an den anderen MINI gesendet, um dort die Variable auf den entsprechenden Wert zu setzen.
LED_Angriff(), LED_Setzen() und LED_Verteidigung()
Die RGB-LED wird je nach Modus auf eine Farbe gesetzt.
Alle LEDs werden aus geschallten
In den Modi Angriff und Setzen wird das Fadenkreuz gezeichnet, es leuchtet pausenlos.
Je nach Modus wird über unterschiedliche Pausen und dem Aufruf der Funktion „doAnschalten“ ein unterschiedliches Blinken realisiert. Dazu wird jeweils das Array „anschalten_array“ auf „schiffe“ oder „schuesse“ gesetzt und die Variable „anschalten_wert“ auf den Wert, bei dem die entsprechenden LEDs eingeschaltet werden sollen.
DoAnschalten()
Mit einer verschachtelten für-Schleife wird jeder Wert aus dem in „anschalten_array“ hinterlegten Array mit dem in „anschalten_wert“ hinterlegtem Wert verglichen.
Sind beide Werte gleich, dann wird die LED an der entsprechenden Position eingeschaltet.
AufAngriffPruefen()
Wenn die X- und Y-Werte des Angriffs nicht mehr auf dem Standardwert sind, also größer oder gleich 0 sind, dann wurde ein angriff erfolgreich übermittelt.
Wenn an der X- und Y-Position des Angriffes im Array „schiffe“ eine 0 ist, dann ist dort Wasser. Der Wert im Schiffe-Array wird also auf 1 gesetzt, um einen Wassertreffer dar zu stellen.
Das Ergebniss wird ebenfalls auf 1 gesetzt.
Ansonsten ist von einem Treffer aus zu gehen. Der Wert im Schiffe-Array wird auf 2 fest gelegt, um einen Treffer dar zu stellen.
Der Trefferzähler „treffer“ wird um eins erhöht.
Das Ergebnis wird auf 9 gesetzt.
Wenn die Anzahl der Treffer dem in „schiffe_max“ festgelegten Wert entspricht, dann sind alle gesetzten Schiffe getroffen und versenkt. Das Ergebnis wird auf 99 gesetzt und der Modus auf „verloren“ geändert.
Ansonsten wird der Modus zu „senden_verteidigung“ geändert.
Knopf A
Wenn der Modus auf Angriff oder Setzen steht werden Eingaben angenommen.
Der Y-Wert des Fadenkreuzes wird um eins erhöht.
Wenn der Y-Wert auf 5 steht und damit den Maximalen wert überseteigt wird der Wert auf 0 zurückgesetzt. Das Fadenkreuz erscheint also wieder am anderen Ende der Matrix.
Knopf B
Wie bei Knopf A, nur mit dem X-Wert.
Knopf A & B
Im Modus Setzen wird geprüft, ob an der stelle des Fadenkreuzes noch kein Schiff gesetzt ist, der Wert also 0 ist.
Wenn dies der Fall ist, dann wird an der entsprechenden Position der Wert auf 9 gesetzt.
Die Anzahl der Schiffe wird um eines erhöht.
Und zur bestätigung ein Ton von 500Hz für 1/16 Takt abgespielt.
Ansonsten wird das Mitlere C für einen Takt abgespielt.
Im Modus Angriff wird geprüft, ob an der Stelle noch kein Schuss abgegeben wurde, der Wert also noch 0 ist.
Wenn dies der Fall ist, dann wird zur bestätigung ein Ton von 500 Hz für 1/16 takt gespielt und der Modus auf „senden_angriff geändert.
Ansonsten wird das Mittlere C für einen Takt abgespielt.
Im Modus Verteidigung wird beim empfang der Variable „a_feld_y“ die lokale Variable „angriff_y“ auf den empfangen Wert gesetzt.
Für die Variable mit dem X-Wert ebenso.
Im Modus „senden_angriff“ wird beim Empfang der Variable „a-rueckgabe“ geprüft, ob diese den Wert 99 enthält.
Ist dies der Fall hat der andere MINI Verloren und der Modus wird auf „gewonnen“ geändert.
Ansonsten wird der empfangene Wert an die angegriffene Stelle im Schüssse-Array geschrieben.
Die RGB-LED wird auf Violet gesetzt.
Wenn der Empfangene Wert gleich 9 ist, dann bedeutet dies einen Treffer. Es wird ein Häckchen dargestellt.
Ansonsten wird ein X dargestellt.
nach einer Sekunde wird dann der Modus auf Verteidigung geändert. Der Angriff ist abgeschlossen.
Im Modus „senden_verteidigung“ und „teamwahl“ wird beim Empfang der Variable „funk_ende“ jeweils der Modus auf „Angriff“ geändert.
Im Modus Setzen wird beim Empfang der Variable „team“ die lokale Variable „team“ auf 1 gesetzt.
Setzten:
Dieser Modus ist aktiv, so bald der Calliope Mini gestartet wird.
In diesem Modus soll der Calliope ein aktives Feld darstellen, das mit den A und B Tasten gewechselt werden kann. Mit dem drücken beider Tasten soll an dem entsprechenden Feld ein Schifspunkt gesetzt werden.
Dort, wo bereits Schiffspunkte gesetzt wurden sollen die entsprechenden Pixel blinken.
Immer wenn ein Schiffspunkt gesetzt wurde soll die Variable „schiffe_gesetzt“ um eins erhöht werden.
Sobald die anzahl der gesetzten Schiffe der Variable „schiffe_max“ entspricht soll der Modus auf Teamwahl geändert werden.
Angriff:
Auch in diesem Modus wird ein aktives Feld dargestellt und mit den A und B Tasten gewechselt. Bei dem drück beider Tasten wird ein das entsprechende Feld beim Gegner angegriffen. Der Modus wird dazu auf „senden_angriff“ geändert.
Auf dem Calliope Mini sollen die bereits angegriffenen Felder blinken. Treffer auf die gegnerischen Schiffe sollen länger leuchten und Schüsse ins Wasser nur kurz.
Verteidigung:
In dem Modus gibt es keine Interaktionsmöglihckeiten. Die eigenen Schiffe leuchten dauerhaft. Treffer des Gegners blinken lang und die Gegnersichen Schiffe, welche im Wasser gelandet sind sollen kurz blinken.
Damit der gegnerische Calliope weiß, dass angriffe „empfangen“ werden können und der Calliope Mini gerade „passiv“ ist wird der Wert „funk_ende = 0“ gesendet.
So bald der Calliope ein Funksignal mit dem Namen „a_feld“ (das „a“ steht für „Angriff“) erhält prüft er das Ergebnis des Angriffes und schreibt dieses in die Variable „ergebniss“, sowie an der entsprechenden Stelle in das Array „Schiffe“.
Bei einem Treffer wird die Variable „treffer“ um eins erhöht. Entspricht die Variable „treffer“ der Variable „schiffe_max“, dann wird der Modus auf „verloren“ geändert. Ansonsten wechselt der Calliope zum Modus „senden_verteidigung“.
Gewonnen:
Es wird ein Smiley angezeigt und das Spiel ist zu ende.
Verloren:
Es wird ein trauriger Smiley angezeigt und das Spiel ist zu ende. Um den Calliope Mini des Gegners über das Ende zu informieren wird der Wert „a_rueckgabe = 99“ gesendet.
Senden Angriff:
Das Feld, welches angegriffen werden soll wird per Funk gesendet. Der Calliope wartet nun darauf, dass der gegnerische Calliope das Ergebniss des Angriffes zurücksendet.
Ist das Ergebnis „99“ wird der Modus auf „Gewonnen“ geändert.
Ist das Ergebnis „9“ wird für eine Sekunde ein Häckchen angezeigt und das Ergebniss an der entsprechenden Stelle in das Array „Schuesse“ geschreiben.
Ebenso bei einem Ergebnis von „1“, nur dass in diesem Fall für eine Sekunde ein „X“ angezeigt wird.
Im Anschluss wird der Modus auf „Verteidigung“ gesetzt.
Senden Verteidigung:
Der Angegriffene Punkt wird durch ein schnelles blinken der entsprechenden LED angezeigt.
Das Ergebniss des Angriffes wird so lange an den anderen Calliope gesendet, bis dieser durch das senden von „funk_ende“ signalisiert, dass er das Ergebniss erhalten hat und nun selbst im Verteidigungsmodus ist. Der Modus wird nun auf „angriff“ geändert.
Teamwahl:
Der Calliope, welcher zu erst in diesen Modus wechselt sendet das Signal „team = 1“ so lange aus, bis er mit dem empfang von „funk_ende“ erkennt, dass der Gegner nun im Modus „Verteidigung“ ist. Der Modus wird dann auf „Angriff“ gesetzt.
Beim empfang von „team=1“ des anderen Calliope wird dort der Wert „team“ auf „1“ gesetzt. Wenn dieser dann in den Modus „Teamwahl“ wechselt wird der Modus dort sofort weiter auf „Verteidigung“ geändert.