JavaScriptsSpiele

Lights Out 2

Fünf mal fünf Felder, jeder Klick dreht das Feld und seine vier Nachbarn um — Ziel ist ein Brett ganz ohne Haken.

Lights Out ist ein Schaltpuzzle: Vor euch liegen 25 Felder in einem Raster aus fünf Zeilen und fünf Spalten. Klickt ihr ein Feld an, ändert sich nicht nur dieses Feld, sondern zugleich seine vier direkten Nachbarn — oben, unten, links, rechts. Ein gesetzter Haken verschwindet, ein leeres Feld bekommt einen. Ziel ist es, das Brett vollständig leer zu bekommen. Diese Fassung stammt von unserem User „Vollautomatisch“.

Zum Loslegen drückt ihr auf „Zufällig“: Das Script führt 25 bis 34 zufällige Klicks aus und erzeugt so eine Ausgangslage, die garantiert lösbar ist — denn was durch Klicks entstanden ist, lässt sich durch Klicks auch wieder rückgängig machen. Danach seid ihr dran. Wer nicht weiterkommt, klickt auf „Lösen“: Darunter erscheint dann eine Zugfolge in Feldkoordinaten, also etwa C2 -> A4 -> E1. Die Spalten heißen A bis E, die Zeilen 1 bis 5. Das Brett selbst bleibt dabei unverändert — ihr bekommt nur den Weg gezeigt und dürft ihn selbst nachklicken.

Zwei Eigenheiten des Spiels sind es wert, gekannt zu werden. Erstens: Die Reihenfolge der Züge ist völlig egal. Jeder Klick dreht dieselben fünf Felder um, und zweimal umdrehen hebt sich auf — deshalb zählt am Ende nur, welche Felder ihr gedrückt habt, nicht wann. Genau darum darf das Script die ausgegebene Lösung sogar durchmischen. Zweitens: Ein Feld zweimal zu drücken ist immer vergeblich, es stellt den Zustand von vorher wieder her. Eine kürzeste Lösung drückt also jedes Feld höchstens einmal.

Der Klassiker unter diesem Namen kam 1995 als Handheld von Tiger Electronics auf den Markt; das Prinzip mit dem Kreuz aus fünf Feldern ist seither in unzähligen Varianten nachgebaut worden. Die schlichtere Fassung ohne Zufallsstart und ohne Lösungsweg findet ihr bei uns unter Lights Out. Wer noch mehr Kopfnüsse sucht, wird bei Die Türme von Hanoi, Mastermind und dem Buchstabenpuzzle fündig.

Spiele Baujahr 2007 läuft in deinem Browser

Ein Klick setzt oder entfernt den Haken im angeklickten Feld und dreht zugleich seine vier direkten Nachbarn um. Ziel ist ein Brett ganz ohne Haken.

Eingesandt von Vollautomatisch

So funktioniert das Script

Das Script besteht aus vier Bausteinen: Es baut das Spielbrett auf (initFields), setzt bei jedem Klick die richtigen Felder um (aendere und lightsOut), erzeugt auf Wunsch eine zufällige Ausgangslage (random) und rechnet den Lösungsweg aus (solve). Das Spielbrett ist dabei nichts weiter als eine Reihe von Ankreuzfeldern: Jedes Feld ist eine ganz normale Checkbox mit einer durchnummerierten id von feld_1 oben links bis feld_25 unten rechts.

function aendere ( feld )
{
  feld = parseInt(feld);
  if (document.getElementById('feld_' + feld).checked == true)  { document.getElementById('feld_' + feld).checked = false; }
  else if (document.getElementById('feld_' + feld).checked == false)  { document.getElementById('feld_' + feld).checked = true; }
}

Das ist die kleinste und wichtigste Funktion: Sie dreht ein einzelnes Feld um. Über 'feld_' + feld wird aus der Nummer der Name der id zusammengesetzt — bei der 13 also feld_13. Steht dort ein Haken, wird er entfernt, steht keiner, wird einer gesetzt. checked ist die Eigenschaft, mit der man in JavaScript den Zustand eines Ankreuzfeldes liest und setzt.

if ( (feld > 6) && (feld < 10) || (feld > 11) && (feld < 15) || (feld > 16) && (feld < 20))
{
  … feld-5, feld-1, feld+1, feld+5 umdrehen …
}
else
{
  switch (feld)
  {
    case 1: aendere(2); aendere(6); break;
    …

lightsOut kümmert sich um die Nachbarn und muss dabei aufpassen, wo es steht. Für die neun Felder mitten im Brett ist die Sache einfach: Weil die Felder zeilenweise durchnummeriert sind, liegt der linke Nachbar immer bei feld-1, der rechte bei feld+1, der obere fünf Nummern davor und der untere fünf danach. Für alle Felder am Rand stimmt diese Rechnung nicht — bei Feld 5 (rechts oben) wäre feld+1 das Feld 6, das aber schon in der nächsten Zeile ganz links liegt. Deshalb sind alle Randfälle einzeln in einer switch-Anweisung aufgezählt. switch ist eine Art Weiche: Sie springt zu genau dem case, der zum Wert passt, und break beendet den Zweig.

if ( (i > 0) && (i < 26) )  { html += '<td><input type="checkbox" name="feld" id="feld_' + i + '"></td>'; }
…
document.getElementById('lo2-brett').innerHTML = html;

Die 25 Felder samt Beschriftung von Hand ins HTML zu tippen wäre mühsam, also baut das Script die Tabelle in einer Schleife als Text zusammen und setzt sie am Ende mit innerHTML in den leeren Behälter lo2-brett. Im Original stand hier document.write — ein Befehl, der Text direkt in die Seite schreibt, während sie noch geladen wird. Das funktioniert nur genau in diesem Moment und überschreibt die ganze Seite, wenn man es später aufruft; deshalb ist es heute durch innerHTML ersetzt.

for (var n = 1; n < 26; n++)
{
  (function (feld) {
    document.getElementById('feld_' + feld).addEventListener("click", function () { lightsOut(feld); });
  })(n);
}

Danach bekommt jedes der 25 Felder seinen Klick-Handler. Den Haken im angeklickten Feld setzt der Browser selbst — das macht ein Ankreuzfeld von Haus aus —, um die vier Nachbarn kümmert sich lightsOut. Die zusätzliche Klammer-Konstruktion drumherum sorgt dafür, dass sich jeder Handler seine eigene Nummer merkt und nicht alle 25 am Ende dieselbe verwenden.

for (var i = 1; i < 21; i++)
{
  if (document.getElementById('feld_' + i).checked == true)  { draws[nummer] = (i + 5); nummer++; aendere(i + 5); lightsOut(i + 5); }
}

Das ist das Herz des Lösers, und dahinter steckt ein hübscher Trick, den Lights-Out-Spieler „Lichter jagen“ nennen: Man geht die Zeilen von oben nach unten durch und drückt unter jedem gesetzten Haken das Feld eine Zeile tiefer (deshalb i + 5). Damit ist die obere Zeile sauber, und der Rest wandert nach unten. Nach vier Durchgängen bleibt nur noch die unterste Zeile übrig. Für die gibt es keine Zeile mehr darunter — hier helfen die validate-Abfragen: Sie prüfen ein paar feste Muster in der letzten Zeile und drücken dann ein oder zwei bestimmte Felder in der obersten Zeile. Danach räumt derselbe Jagd-Durchgang das Brett vollständig leer.

for (var j = 0; j < copy.length; j++)
{
  for (var i = 0; i < copy.length; i++)
  {
    if ( (copy[i] == copy[j]) && (copy[i] != "") && (i != j) )  { copy[i] = ""; copy[j] = ""; }
  }
}

Weil beim Rechnen dasselbe Feld mehrfach gedrückt werden kann und zweimal Drücken sich aufhebt, wird die Zugliste anschließend aufgeräumt: Zwei gleiche Einträge streichen sich gegenseitig und werden durch eine leere Zeichenkette ersetzt. Übrig bleibt die kurze Liste, die als Lösungsweg ausgegeben wird — vorher noch von mischen durchgeschüttelt, weil die Reihenfolge bei diesem Spiel ohnehin keine Rolle spielt.

Im Original hing diese Mischfunktion als Array.prototype.shuffle an allen Arrays der Seite. Das ist bequem, kann aber fremde Scripts auf derselben Seite durcheinanderbringen, deshalb ist daraus die gewöhnliche Funktion mischen(liste) geworden. Wollt ihr die Ausgangslage schwerer machen, dreht ihr an den Zahlen in parseInt(Math.random() * 10 + 25) — das sind die 25 bis 34 Zufallsklicks des Knopfes „Zufällig“.

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