Vorbereitung
Laden Sie sich folgendes zip-File herunter: 06-connect-4.zip
Das Archiv enthält mehrere Unterverzeichnisse mit dem Spiel.
01-connect-4 und testen Sie diesen Code. Studieren Sie auch die Ausgabe auf der Console.div.className = feldklassen[wert]; und der CSS-Datei.
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.
getWert(div) die den Wert als Zahl zurück gibt (benutzen Sie die Number()-Funktion, damit man nicht den String (Zeichenkette) erhält.setWert(div, wert), die das wert-Attribut setzt und auch die entsprechende Klasse.reset-Funktion, die alle Felder auf grau setzt (verwenden Sie dazu folgendes):for (let div of spieldfeld.children) { // ... }
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.reset-Funktion.Das Spiel kann auf zwei Arten enden:
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.
// 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; }
Um das Spielende anzuzeigen, könnte ein «Popup» verwendet werden.
display:none; formatiert ist<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%)…
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: 04-computer-opponent.zip