Wie ich 2048 an einem Wochenende gebaut habe — die ganze Spielschleife
2026-06-29
Ich habe kürzlich 2048 zu ToolKoala hinzugefügt, und die schönste Überraschung war, wie klein das eigentliche Spiel ist. Die Animationen und der Feinschliff brauchen Zeit, aber die Regeln — schieben, verschmelzen, erzeugen, auf Game over prüfen — passen in etwa sechzig Zeilen. So funktioniert die ganze Schleife.
Das Brett ist nur ein flaches Array
Das Gitter ist 4×4, aber ich speichere es als flaches Array aus 16 Zahlen, wobei 0 leer bedeutet:
[2, 0, 0, 4,
0, 2, 0, 0,
0, 0, 0, 0,
4, 0, 0, 2]
Flache Arrays sind leicht zu kopieren, zu vergleichen und in localStorage zu speichern. Zeile r, Spalte c liegt am Index r * 4 + c.
Eine Funktion erledigt die eigentliche Arbeit
Jeder Zug — links, rechts, oben, unten — ist dieselbe Operation auf einer Linie aus vier Kacheln: schiebe alles zu einem Ende und verschmelze gleiche Nachbarn einmal. Das ist eine einzige Funktion:
function compress(line) {
const arr = line.filter(v => v) // die Nullen entfernen
const res = []
let gained = 0
for (let i = 0; i < arr.length; i++) {
if (arr[i] === arr[i + 1]) { // zwei gleiche Kacheln berühren sich → verschmelzen
res.push(arr[i] * 2)
gained += arr[i] * 2
i++ // die gerade verschmolzene überspringen
} else {
res.push(arr[i])
}
}
while (res.length < 4) res.push(0) // wieder auf Länge 4 auffüllen
return { line: res, gained }
}
Das i++ nach einer Verschmelzung ist die Regel, die verhindert, dass 4 4 4 4 zu einer einzigen 16 kollabiert. Es wird zu 8 8 — jede Kachel verschmilzt höchstens einmal pro Zug.
Vier Richtungen aus einer Richtung
Ich habe nur "nach links schieben" geschrieben. Die anderen drei verwenden es wieder:
- Rechts — die Zeile umkehren, nach links komprimieren, zurück umkehren.
- Oben / Unten — das Brett spaltenweise statt zeilenweise lesen, dann dieselbe Links/Rechts-Logik.
Ein Zug greift sich also jede Zeile oder Spalte, kehrt sie optional um, führt compress aus und schreibt sie zurück. Kein separater Code für jeden Pfeil — nur, welche Linie ich lese und ob ich sie umdrehe.
Erzeugen, dann prüfen, ob du feststeckst
Nach einem Zug, der das Brett tatsächlich verändert hat, erscheint eine neue Kachel in einer zufälligen leeren Zelle — meistens eine 2, gelegentlich eine 4. Dann prüfe ich, ob noch ein Zug möglich ist: Gibt es leere Zellen oder zwei gleiche Nachbarn? Wenn nicht, ist es Game over.
function canMove(g) {
if (g.includes(0)) return true // leere Zelle → ja
// jeder gleiche horizontale/vertikale Nachbar → eine Verschmelzung ist noch möglich
// ...mit einer kleinen Schleife geprüft...
return false
}
Die Prüfung "hat sich das Brett tatsächlich verändert?" ist wichtig: Wenn ein Zug nichts bewirkt, solltest du keine kostenlose neue Kachel bekommen. Links gegen eine Wand zu drücken muss eine Leeroperation sein.
Der Bug, der mich gelehrt hat, Refs zu verwenden
Die erste Version las das Brett direkt aus dem React-State innerhalb des Tasten-Handlers. Bei schneller Tastenwiederholung konnten zwei Pfeildrücke feuern, bevor React neu rendert, sodass der zweite ein veraltetes Brett las und Züge verloren gingen. Die Lösung war, eine ref zu führen, die das neueste Brett und den Punktestand spiegelt, und den Zug-Handler die Ref lesen zu lassen. Der State steuert, was du siehst; die Ref steuert die Logik. Danach verhält es sich selbst beim Hämmern der Pfeiltasten korrekt.
Fortsetzen und Bestwert, alles lokal
Zwei Dinge leben in localStorage: dein Bestwert und das aktuelle Brett. Speichere das Brett bei jedem Zug; lösche es, wenn das Spiel endet. Beim Laden, wenn es ein gültiges unbeendetes Spiel gibt, stelle ich es wieder her und zeige einen kleinen "Fortsetzen"-Hinweis — dasselbe Muster, das ich für Sudoku und Wortsuche verwende. Nichts wird hochgeladen; dein Spiel gehört dir, auf deinem Gerät.
Probier es aus
Du kannst 2048 hier spielen — Tastatur oder Wischen, und es funktioniert offline, sobald die Seite geladen ist. Wenn du solche Dinge magst, hat der Sudoku-Generator einen interessanteren Algorithmus dahinter.
Häufige Fragen
Ist 2048 schwer zu programmieren? Der Kern ist überraschend klein — eine "eine Linie schieben und verschmelzen"-Funktion, wiederverwendet für alle vier Richtungen, plus das Erzeugen einer Kachel und die Prüfung auf Game over. Der Feinschliff (Animationen, Touch-Steuerung, Fortschritt speichern) ist es, wo die meiste Zeit hingeht.
Wie funktioniert die Verschmelzungsregel? Wenn zwei Kacheln mit derselben Zahl zusammengeschoben werden, verbinden sie sich zu einer Kachel mit dem doppelten Wert — und jede Kachel kann pro Zug nur einmal verschmelzen, sodass eine Reihe aus vier 2ern zu zwei 4ern wird, nicht zu einer 8.
Wie werden die vier Richtungen behandelt? Du musst nur eine Richtung implementieren. Rechts ist Links mit umgekehrter Zeile; Oben und Unten sind dieselbe Logik, angewendet auf Spalten statt Zeilen.
Speichert ToolKoalas 2048 mein Spiel? Ja — dein Bestwert und das aktuelle Brett werden im lokalen Speicher deines Browsers abgelegt, sodass du den Tab schließen und später weitermachen kannst. Es verlässt nie dein Gerät.
— Milo 🐨