Show pageOld revisionsBacklinksBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== 4-Gewinnt ====== <WRAP todo> **Vorbereitung** Laden Sie sich folgendes zip-File herunter: {{lehrkraefte:blc:informatik:ffprg1-2023:js-connect-4:06-connect-4.zip}} Das Archiv enthält mehrere Unterverzeichnisse mit dem Spiel. </WRAP> ===== Spielfeld generieren, CSS-Tricks ===== <WRAP todo> * Studieren Sie den HTML, CSS und JS-Code im Verzeichnis ''01-connect-4'' und testen Sie diesen Code. Studieren Sie auch die Ausgabe auf der Console. * Schaffen Sie es, dass die Farbe eines Felds auf rot (oder blau) gesetzt wird, wenn man darauf klickt? * Verstehen Sie den Zusammenhang zwischen der Zeile ''div.className = feldklassen[wert];'' und der CSS-Datei. * Wenn Sie möchten, finden Sie besseren CSS-Code für die Felder (angefangen bei den Farben). Es sind mit CSS auch runde Felder bzw. Hintergrundbilder möglich. </WRAP> ===== Spielfeld Zustand speichern und manipulieren ===== So wie es im Moment programmiert ist, ist die Information über den Feldzustand an zwei Orten gespeichert: Im Attribut ''wert'' und in der Klasse des jeweiligen Elements (eine von ''feldleer'', ''feldeins'' und ''feldzwei''). Zum Auslesen und Setzen dieser Werte ist das aber unpraktisch. <WRAP todo> * Schreiben Sie eine Funktion ''getWert(div)'' die den Wert als Zahl zurück gibt (benutzen Sie die ''Number()''-Funktion, damit man nicht den String (Zeichenkette) erhält. * Schreiben Sie eine Funtion ''setWert(div, wert)'', die das ''wert''-Attribut setzt und auch die entsprechende Klasse. * Testen Sie die Funktion, indem Sie damit das Feld jeweils «eins weiter» schalten beim Klicken. * Implementieren Sie eine ''reset''-Funktion, die alle Felder auf grau setzt (verwenden Sie dazu folgendes): <code javascript> for (let div of spieldfeld.children) { // ... } </code> * Implementieren Sie eine Funktion ''getDiv(spalte, zeile)'', die das richtige Element aus den 42 Elementen zurückliefert mit ''spielfeld.children.item(nummer)'', wobei ''nummer'' natürlich aus ''spalte'' und ''zeile'' berechnet werden muss. </WRAP> ===== Spielablauf ===== <WRAP todo> * Überlegen Sie sich, was alles bekannt sein muss, um einen beliebigen Spielzustand im «Vier gewinnt» zu beschreiben und wie man dies in Variablen speichern könnte. * Fügen Sie diese Variablen im Code hinzu und initialisieren Sie diese in der ''reset''-Funktion. * Bei einem klick auf ein Feld soll überprüft werden, ob überhaupt noch ein Stein in die entsprechende Spalte gesetzt werden kann, und wenn ja, auf welcher Höhe. * Die Farben sollen immer abwechseln. </WRAP> ===== Spielende überprüfen ===== Das Spiel kann auf zwei Arten enden: * Alle Plätze sind besetzt * Jemand hat vier in einer Reihe Der erste Fall kann relativ einfach überprüft werden, indem einfach gezählt wird, wie viele Steine schon gesetzt wurden. Der zweite Fall hat viel mehr Fleisch am Knochen. Überlegen Sie sich Strategien dazu. ==== Mögliche Lösung ==== <code javascript> // Zugriff auf Feld etwas vereinfachen: function getValueAt(x,y) { // wenn x,y nicht auf dem Brett, 0 züruckgeben // sonst den Wert vom Feld x,y } // Gibt die Anzahl gleicher Felder an, wenn man bei (startx, starty) startet und in Richtung (dx,dy) weiter geht. // Ist das Startfeld schon 0, wird sofort 0 zurückgegeben function count(startx, starty, dx, dy) { let wert = getValueAt(startx,starty); // Wert auf Startfeld if (wert==0) return 0; // Keine Nuller zählen let anzahl = 0; while (wert==getValueAt(startx,starty)) { // Immer noch das Gleiche? anzahl++; startx+=dx; // Vorwärts starty+=dy; } return anzahl; } // Liefert true, wenn die Position (x, y) Teil eines Vierers ist function pruefen(x, y) { let dirs = [[1,0], [1,1], [0,1], [-1,1]]; // Trigonometrisch, 45 Grad Schritte. for (let d of dirs) { let anzahl = count(x, y, d[0], d[1]) + count(x, y, -d[0], -d[1]) - 1; if (anzahl>=4) { return true; } } return false; } </code> ==== Popup-Nachricht / Gewinnsteine markieren ==== Um das Spielende anzuzeigen, könnte ein «Popup» verwendet werden. * Z.B. ein div, das normalerweise mit ''display:none;'' formatiert ist * Oder ein ''<dialog>''. Um die Gewinnsteine zu markieren, erweitern Sie die Funktion ''pruefen'' um einen Parameter (z.B. ''mark=false''), der angibt, ob die Felder markiert werden sollen. Fügen Sie eine zusätzliche Klasse in der CSS-Datei an, die angibt, wie die Felder markiert werden sollen, z.B. durch eine CSS-Animation mit ''filter:brightness(150%)''... ===== Computergegner ===== Idee: Bis zu einer gewissen Tiefe alle möglichen Züge durchprobieren und jeweils den besten davon auswählen und dessen Bewertung zurückgeben. Ist die maximale Tiefe erreicht, wird die Spielsituation heuristisch bewertet. Eine mögliche, minimale Implementation finden Sie hier: {{lehrkraefte:blc:informatik:ffprg1-2023:js-connect-4:04-computer-opponent.zip}} lehrkraefte/blc/informatik/ffprg1-2023/js-connect-4/start.txt Last modified: 2023/05/16 09:49by Ivo Blöchliger