JavaScriptsSpiele

Minesweeper

Der Klassiker im Browser: zehn mal zehn Felder, vierzehn versteckte Minen, eine laufende Uhr.

Wer kennt den Klassiker nicht: Minesweeper, das Minensuchspiel, das jahrzehntelang jedem Windows beilag. Unser User Martin Bender hat uns diese JavaScript-Variante geschickt — sie läuft ohne einzige Grafikdatei, das ganze Spielfeld besteht aus hundert eingefärbten Feldern.

Das Spielfeld ist zehn mal zehn Felder groß, darin verstecken sich vierzehn Minen. Ihr klickt die Felder an, von denen ihr annehmt, dass sie frei sind. Ist es ein freies Feld, färbt es sich gelb und zeigt an, wie viele Minen in den acht Feldern ringsherum liegen. Steht dort nichts, war die Umgebung leer — dann deckt das Script gleich alle angrenzenden Felder mit auf und färbt sie grün. Aus diesen Zahlen lässt sich Feld für Feld erschließen, wo die Minen liegen müssen.

Eine Besonderheit gibt es im Vergleich zum Windows-Spiel: Ihr müsst auf den Rechtsklick verzichten. Die Minen könnt ihr also nicht mit einem Fähnchen markieren, sondern müsst sie euch merken. Sobald alle freien Felder aufgedeckt sind, ist das Spiel gewonnen — die Minen erscheinen dann dunkelgrün. Trefft ihr eine Mine, endet die Partie sofort und alle Minen werden rot angezeigt. Die Uhr rechts oben startet mit dem ersten Klick und zählt die Sekunden; „Neues Spiel“ mischt die Minen neu und stellt sie zurück.

Zum Anfangen ein Tipp aus der Minesweeper-Praxis: Der erste Klick ist immer geraten. Danach lohnt es sich, an den Rändern zu beginnen, denn Randfelder haben nur fünf Nachbarn statt acht und lassen sich leichter eindeutig auflösen. Bei 14 Minen auf 100 Feldern liegt die Minendichte bei 14 Prozent und damit etwas unter der des klassischen Anfängerfeldes.

Eine zweite, rein zeichenbasierte Fassung dieses Spiels haben wir mit dem ASCII Minesweeper im Archiv. Wer lieber ein ganzes Feld umschalten möchte, findet bei Lights Out Knobelstoff, und Zahlenrätsel gibt es beim Sudoku-Generator.

Spiele Baujahr 2009 läuft in deinem Browser
MINENSUCHE 0000

14 Minen auf 100 Feldern. Die Zahl in einem Feld sagt, wie viele Minen es berührt.

Eingesandt von Martin Bender

So funktioniert das Script

Das Script hat vier Aufgaben: Es baut das Spielfeld auf, verteilt die Minen (init), reagiert auf Klicks (klick und oeffne) und lässt eine Uhr laufen (startsek). Der gesamte Spielstand steckt dabei in zwei Feldern — in der Programmierung heißen solche nummerierten Sammlungen Arrays.

const area = new Array(100);
const area2 = new Array(100);

area merkt sich, was auf einem Feld liegt: entweder der Buchstabe "M" für eine Mine oder eine Zahl, nämlich die Anzahl der Minen ringsherum. area2 merkt sich, wie das Feld gerade aussieht — die Farbe dient dem Script zugleich als Zustand: #008080 (Blaugrün) heißt „noch zu“, #ffff00 (Gelb) „aufgedeckt mit Zahl“, #00ff00 (Grün) „leeres Feld“. Beide Arrays haben genau 100 Plätze und keine Zeilen und Spalten: Das Feld in Zeile 3, Spalte 5 hat schlicht die Nummer 35. Diese Nummerierung zieht sich durch das ganze Script.

mine = Math.round(Math.random()*99);
if(area[mine] === "M")
{
  z1--;
  continue;
}
area[mine] = "M";

So werden die Minen verteilt. Math.random() liefert eine Zufallszahl zwischen 0 und 1, mal 99 und gerundet ergibt das eine Feldnummer. Liegt dort schon eine Mine, wird der Schleifenzähler mit z1-- zurückgedreht und der Durchgang mit continue übersprungen — so wird derselbe Durchgang noch einmal versucht, bis wirklich 14 verschiedene Felder eine Mine haben.

if(!((mine - 11) < 0) && (mine % 10 !== 0))
  if(area[mine - 11] !== "M")
    area[mine - 11]++;

Direkt nach jeder Mine werden die acht Nachbarfelder hochgezählt. Weil alles in einer Reihe von 100 Feldern liegt, sind die Nachbarn schlicht die Nummern -11, -10, -9, -1, +1, +9, +10 und +11. Die beiden Bedingungen davor verhindern das Überlaufen an den Rändern: mine - 11 < 0 fängt die oberste Zeile ab, und mine % 10 !== 0 sorgt dafür, dass ein Feld in der linken Spalte keine Nachbarn in der rechten Spalte bekommt. Der Operator % (Modulo) liefert den Rest einer Division; bei der Nummerierung in Zehnerschritten ist dieser Rest genau die Spaltennummer.

if((area2[nr] === "#008080") && (area[nr] === 0))
  oeffne(nr);
if(area2[nr] === "#008080")
{
  frei++;
  area2[nr] = '#ffff00';
  ...
}

Das ist der Kern des Klickens. Ist das angeklickte Feld noch zu und hat es keine Mine in der Nachbarschaft, ruft das Script oeffne() auf. Diese Funktion färbt das Feld grün und klickt anschließend selbst auf alle acht Nachbarn — die rufen bei Bedarf wieder oeffne() auf, und so pflanzt sich die Öffnung über die ganze leere Fläche fort. So etwas nennt man Rekursion: Eine Funktion ruft sich über Umwege selbst wieder auf. Die Kette endet von allein, sobald überall Felder mit Zahlen erreicht sind, denn deren Farbe ist dann nicht mehr #008080.

Der Zähler frei läuft dabei mit: Er zählt jedes aufgedeckte Feld. Erreicht er 100 - minen, also 86, ist kein freies Feld mehr übrig — die Partie ist gewonnen, und alle Minen werden dunkelgrün markiert.

function startsek()
{
  if((frei !== 0) && (spiel === true))
    document.getElementById("sek").textContent = Math.round((new Date() - sekunden) / 1000);
  setTimeout(startsek, 1000);
}

Die Uhr ist bewusst einfach gehalten: Beim ersten Klick merkt sich sekunden mit new Date() den Startzeitpunkt. startsek zieht diesen Zeitpunkt von der aktuellen Zeit ab, teilt durch 1000 (Millisekunden in Sekunden) und trägt das Ergebnis ein. Am Ende ruft sie sich über setTimeout nach einer Sekunde selbst wieder auf — die Uhr hält sich also selbst am Laufen. Im Original stand hier setTimeout("startsek()", 1000) mit dem Funktionsnamen als Text; diese Schreibweise gilt heute als unsicher, deshalb wird die Funktion jetzt direkt übergeben.

zelle.addEventListener("click", function () { klick(nr); });

Das Spielfeld selbst entsteht in einer doppelten Schleife über zehn Zeilen und zehn Spalten. Jedes Feld bekommt die id feld0 bis feld99 und einen Klick-Zuhörer, der sich seine eigene Nummer merkt. Früher wurde das Feld mit document.write als Tabelle in die Seite geschrieben — das funktioniert nur noch während des Ladens der Seite und ist hier durch echte Elemente ersetzt.

Zum Anpassen: Die Zeile const minen = 14; ganz oben bestimmt den Schwierigkeitsgrad — 10 Minen sind gemütlich, 20 sind sportlich. Die Farben stehen als Hex-Werte im Script und kommen jeweils doppelt vor (einmal in area2, einmal für die Anzeige); wenn ihr sie ändert, müsst ihr beide Stellen anfassen, weil das Script die Farbe als Gedächtnis benutzt. Das Zeichen "✶" für eine gefundene Mine dürft ihr durch jedes andere Zeichen ersetzen — im Original stand hier ein Buchstabe in der Schriftart Wingdings, der außerhalb von Windows nicht als Bombe erscheint.

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