JavaScriptsSpiele

Buchstabenpuzzle

Ein Schiebepuzzle mit 15 Buchstaben und einer Lücke: Bringt A bis O wieder in die richtige Reihenfolge.

Dieses kleine Spiel ist die Bildschirmfassung eines uralten Geduldsspiels: In einem Rahmen aus vier mal vier Kästchen liegen 15 beschriftete Steine und eine Lücke. Verschieben lässt sich immer nur ein Stein, der direkt an die Lücke grenzt — er rutscht hinein, und die Lücke wandert an seinen alten Platz. Ziel ist es, die Buchstaben A bis O zeilenweise in die richtige Reihenfolge zu bringen, mit der Lücke rechts unten. Der ursprüngliche Code stammt von Dion.

Bedient wird das Spiel mit der Maus: Klickt auf ein Kästchen, das waagerecht oder senkrecht neben der Lücke liegt, und es wandert hinüber. Klicks auf alle anderen Kästchen bleiben wirkungslos — auch diagonal geht nichts. Im Feld darunter zählt das Script eure Züge mit, damit ihr euch mit anderen messen könnt: Wer schafft es mit den wenigsten Zügen?

Das Original dieses Puzzles ist über 140 Jahre alt. Es kam in den 1870er Jahren als „15-Puzzle“ auf und löste eine Modewelle aus; der amerikanische Rätselautor Sam Loyd machte es später mit einer angeblich unlösbaren Aufgabe berühmt. Genau darin liegt auch die Tücke: Von allen denkbaren Anordnungen der 15 Steine lässt sich nur die Hälfte durch Schieben in die geordnete Reihenfolge bringen. Weil dieses Script die Steine frei durcheinanderwürfelt, kann es euch also eine Ausgangslage vorsetzen, die sich beim besten Willen nicht lösen lässt. Wenn ihr partout nicht ans Ziel kommt, ist das keine Schande — ladet die Seite neu, dann wird frisch gemischt.

Weitere Geduldsspiele aus derselben Kategorie: Die Türme von Hanoi, das Schaltpuzzle Lights Out 2 und das Gedächtnisspiel Concentration. Wer statt Buchstaben lieber ein Bild zusammenschieben möchte, findet unter Dynamic Puzzle die passende Variante.

Spiele Baujahr 2006 läuft in deinem Browser

Ein Klick auf ein Kästchen neben dem leeren Feld schiebt es dorthin. Ziel ist die Reihenfolge A bis O mit dem leeren Feld rechts unten. Für eine neue Mischung ladet ihr die Seite neu.

Script von Dion

So funktioniert das Script

Das Script ist erstaunlich kurz: Es baut 16 Knöpfe, mischt die Buchstaben hinein (rndize) und prüft bei jedem Klick, ob der angeklickte Stein neben der Lücke liegt (move). Die ganze Buchführung besteht aus zwei Zahlen — bx und by merken sich, in welcher Spalte und welcher Zeile die Lücke gerade steckt. Wo welcher Buchstabe liegt, steht nirgends extra; das Brett selbst ist der Speicher.

for (let y = 0; y < 4; y++) {
  for (let x = 0; x < 4; x++) {
    const knopf = document.createElement("button");
    knopf.textContent = "   ";
    knopf.addEventListener("click", function () { move(x, y); });
    brett.appendChild(knopf);
    felder[4 * y + x] = knopf;
  }
}

Zwei ineinander geschachtelte Schleifen erzeugen das Brett: Die äußere zählt die Zeilen, die innere die Spalten. Jeder Knopf merkt sich in seinem Klick-Handler seine eigenen Koordinaten und wird zusätzlich in die Liste felder einsortiert. Die Rechnung 4 * y + x ist der Schlüssel zum ganzen Script: Sie macht aus einem Paar (Zeile, Spalte) eine einzige laufende Nummer von 0 bis 15. Zeile 2, Spalte 1 wird so zu Platz 9 in der Liste. Im Original wurde das Brett übrigens mit document.write geschrieben und über document.pad.elements[…] angesprochen — beides funktioniert heute nur noch mit Glück und ist deshalb ersetzt.

function move(x, y) {
  const ax = Math.abs(bx - x);
  const ay = Math.abs(by - y);
  if (((ax * ay) == 0) && ((ax + ay) == 1)) {

Das ist der eleganteste Teil des Scripts. Math.abs liefert den Abstand ohne Vorzeichen: ax ist der Spaltenabstand zwischen angeklicktem Stein und Lücke, ay der Zeilenabstand. Die Bedingung prüft nun zwei Dinge auf einmal. ax * ay == 0 heißt: Mindestens einer der beiden Abstände ist null — der Stein liegt also in derselben Zeile oder derselben Spalte wie die Lücke, niemals schräg. Und ax + ay == 1 heißt: Zusammen ergeben die Abstände genau eins — der Stein ist also unmittelbarer Nachbar. Nur wenn beides zutrifft, wird geschoben. Zwei Zeilen Mathematik ersetzen hier ein Dutzend Sonderfälle für Ränder und Ecken.

felder[4 * by + bx].textContent = felder[4 * y + x].textContent;
felder[4 * y + x].textContent = "   ";
bx = x; by = y; zaehler.value++;

Geschoben wird durch Tauschen der Beschriftungen: Die Lücke bekommt den Buchstaben des angeklickten Steins, der angeklickte Stein wird zur neuen Lücke (drei Leerzeichen als Kennzeichen), und bx/by zeigen jetzt auf die neue Position der Lücke. Die Kästchen selbst bleiben, wo sie sind — es wandert nur die Aufschrift. Zum Schluss zählt zaehler.value++ den Zug im Anzeigefeld hoch.

const alpha = "ABCDEFGHIJKLMNO ";
for (let i = 0; i < 16; i++) {
  x = 0;
  y = 0;
  while (felder[4 * y + x].textContent != "   ") {
    x = Math.floor(Math.random() * 4);
    y = Math.floor(Math.random() * 4);
  }
  felder[4 * y + x].textContent = alpha.substring(i, i + 1);
}

So wird gemischt: Das Script geht die Zeichenkette alpha von A bis O durch (das 16. Zeichen ist ein Leerzeichen, das ist die Lücke) und sucht für jedes Zeichen einen Platz. Die while-Schleife würfelt so lange Zeile und Spalte neu aus, bis sie ein noch unbeschriftetes Kästchen erwischt hat. Math.floor(Math.random() * 4) ist die Standardformel für eine Zufallszahl von 0 bis 3: Math.random() liefert eine Kommazahl zwischen 0 und knapp 1, mal 4 genommen und abgerundet ergibt das 0, 1, 2 oder 3.

Eine Kleinigkeit ist dabei über die Jahre unbemerkt geblieben, und sie ist ein hübsches Lehrstück: Die Suche startet jedes Mal bei x = 0, y = 0 und prüft erst danach, ob gewürfelt werden muss. Beim allerersten Durchgang ist das Kästchen oben links aber noch frei — die Schleife läuft also gar nicht an, und das A landet ausnahmslos auf dem ersten Platz. Wer das ändern will, würfelt einmal vor der Schleife oder setzt x und y gleich zu Beginn auf zufällige Werte.

Anpassen lässt sich das Spiel vor allem über zwei Stellen: Die Zeichenkette alpha bestimmt die Beschriftung — dort dürfen ebenso gut Ziffern oder eigene Zeichen stehen, solange das letzte Zeichen die Lücke bleibt. Und wer ein größeres Brett möchte, ersetzt alle Vieren durch die neue Kantenlänge und passt die Zeichenkette entsprechend an; das Raster im Stylesheet muss dann ebenfalls mehr Spalten bekommen.

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