Zahlenschieber 2048
Gleiche Zahlen zusammenschieben, bis 2048 dasteht — mit Pfeiltasten, Wischgesten oder Knöpfen, samt Bestenwert im Browser.
Ein Feld aus vier mal vier Kacheln, darauf Zweien und Vieren. Bei jedem Zug rutschen alle Kacheln in eine Richtung, und wo zwei gleiche aufeinandertreffen, verschmelzen sie zu ihrer Summe. Ziel ist eine Kachel mit 2048 — aber wer die schafft, spielt meist weiter.
Gesteuert wird mit den Pfeiltasten, mit Wischgesten auf dem Telefon oder mit den vier Knöpfen unter dem Feld. Nach jedem Zug erscheint an einer zufälligen freien Stelle eine neue Kachel: in neun von zehn Fällen eine 2, sonst eine 4. Das Spiel endet, wenn kein Zug mehr möglich ist — also wenn das Feld voll ist und keine zwei benachbarten Kacheln gleich sind.
2048 wurde im März 2014 vom damals neunzehnjährigen Italiener Gabriele Cirulli an einem Wochenende geschrieben, als Übung nach dem Vorbild zweier ähnlicher Spiele. Innerhalb weniger Wochen hatten es Millionen gespielt. Der Reiz liegt in einer einzigen Regel, aus der sich eine erstaunlich tiefe Strategie ergibt: Wer seine größte Kachel in einer Ecke hält und nie in die Gegenrichtung schiebt, kommt weit. Wer wild in alle vier Richtungen wischt, verliert schnell.
Der beste Punktestand wird in eurem Browser gespeichert — er bleibt also erhalten, wird aber nirgends übertragen.
Verwandtes im Archiv: Die Türme von Hanoi ist ein anderes Schiebespiel mit klarem Ziel, Sudoku verlangt ebenfalls vorausschauendes Denken, und Lights Out lebt wie 2048 von einer einzigen Regel.
Klickt einmal auf das Feld, dann könnt ihr die Pfeiltasten benutzen. Auf dem Telefon funktioniert Wischen.
So funktioniert das Script
Die ganze Spiellogik steckt in einer Funktion, die eine Viererzeile nach links schiebt. Alle vier Richtungen werden darauf zurückgeführt — das ist der Kniff, der aus einem unübersichtlichen Spiel ein kurzes Programm macht.
const gefuellt = zeile.filter(function (wert) { return wert !== 0; });
for (let i = 0; i < gefuellt.length; i++) {
if (i + 1 < gefuellt.length && gefuellt[i] === gefuellt[i + 1]) {
ergebnis.push(gefuellt[i] * 2);
i++;
} else {
ergebnis.push(gefuellt[i]);
}
}
Zuerst fallen alle Lücken weg — filter behält nur die belegten Kacheln. Dann läuft eine Schleife von links nach rechts und verschmilzt je zwei gleiche Nachbarn. Das i++ im Rumpf ist der wichtigste Handgriff: Es überspringt die zweite Kachel des verschmolzenen Paars, damit sie nicht gleich noch einmal mitverschmilzt.
Genau daran hängt eine Spielregel, die viele nicht kennen: Aus 2 2 4 wird beim Schieben 4 4 und nicht 8. Eine frisch verschmolzene Kachel kann im selben Zug nicht noch einmal verschmelzen. Ohne das Überspringen würde das Spiel deutlich zu einfach.
const umkehren = richtung === "rechts" || richtung === "runter";
if (umkehren) werte.reverse();
const ergebnis = zeileSchieben(werte);
if (umkehren) neu.reverse();
Für die anderen drei Richtungen wird nicht neu programmiert, sondern umgeformt: Nach rechts schieben ist dasselbe wie umdrehen, nach links schieben und wieder umdrehen. Für oben und unten wird statt einer Zeile eine Spalte aus dem Gitter geholt. Aus vier Richtungen wird so eine einzige Funktion — deutlich weniger Code und, was wichtiger ist, nur eine Stelle, an der ein Fehler stecken kann.
const vorher = JSON.stringify(gitter);
…
if (JSON.stringify(gitter) === vorher) return;
Nach jedem Zug muss geprüft werden, ob sich überhaupt etwas bewegt hat — sonst erschiene bei jedem Tastendruck gegen eine Wand eine neue Kachel, und das Feld liefe sofort voll. JSON.stringify macht aus dem verschachtelten Feld eine Zeichenkette, die sich einfach vergleichen lässt. Für ein Gitter aus sechzehn Zahlen ist das schnell genug und viel kürzer als ein Vergleich Feld für Feld.
if (freieFelder().length > 0) return true;
for (…) {
if (s < 3 && gitter[z][s] === gitter[z][s + 1]) return true;
if (z < 3 && gitter[z][s] === gitter[z + 1][s]) return true;
}
Das Spielende ist nicht einfach „Feld voll". Solange irgendwo zwei gleiche Kacheln nebeneinanderliegen, ist noch ein Zug möglich. Geprüft wird deshalb jedes Paar — einmal nach rechts, einmal nach unten. Die Abfragen s < 3 und z < 3 verhindern, dass über den Rand hinausgeschaut wird; jedes Paar wird dabei genau einmal betrachtet.
gitter[platz[0]][platz[1]] = Math.random() < 0.9 ? 2 : 4;
Die Verteilung neun zu eins zwischen 2 und 4 stammt aus dem Original und ist wohlüberlegt: Mehr Vieren würden das Feld schneller füllen und das Spiel deutlich härter machen.
feld.addEventListener("keydown", …);
<div id="zs-feld" tabindex="0" …>
Die Tastatur wird am Spielfeld abgehört und nicht am ganzen Dokument. Das tabindex="0" macht das <div> dafür überhaupt erst ansprechbar. Der Grund für diesen Umweg: Würde das Script die Pfeiltasten global abfangen, könnte man die Seite nicht mehr scrollen, solange sie offen ist — eine Unart, die man auf Spieleseiten oft antrifft.
Zum Anpassen: Ein Gitter von 5 × 5 macht das Spiel leichter, 3 × 3 fast unlösbar — dafür müsst ihr die 4 an allen Stellen durch die neue Größe ersetzen, am besten über eine Konstante. Eine Rückgängig-Funktion ist überraschend einfach: Merkt euch vor jedem Zug eine Kopie des Gitters und des Punktestands.
Script für die eigene Homepage
Kopiert euch den kompletten Code und fügt ihn an der Stelle eurer Seite ein, an der das Script erscheinen soll. Er läuft ohne weitere Dateien und ohne fremde Server.
Mehr aus der Kategorie Spiele
-
ASCII Minesweeper
-
Asteroids
-
Ausweichen
-
Ballspiel
-
Bennys Quiz
-
Blackjack
-
Blu Mania
-
BreakOut
-
Buchstaben zählen
-
Buchstabenpuzzle
-
Checkbox Spiel
-
Concentration
-
Der längste Drücker
-
Die Türme von Hanoi
-
Einmaleins Trainer
-
Escape
-
Galgenmännchen
-
Galgenmännchen 2
-
Game Over Game
-
Glücks Klick
-
Glücksbuttons
-
Ich sehe was
-
Kniffel
-
Labyrinth
-
Liebesrechner
-
Lights Out
-
Lights Out 2
-
Mastermind
-
Minesweeper
-
Mühle