api:projects:minesweeper:spielfeld:start
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— | api:projects:minesweeper:spielfeld:start [2024/08/31 10:03] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Projekt Minesweeper: | ||
+ | [[../ | ||
+ | Ein Objekt der Klasse Spielfeld enthält viele Objekte der Klasse Zelle und stellt damit das gesamte Spielfeld im Grafikbereich dar. Starte das Programm unten, decke mit der Maus verschiedene Zellen auf und entdecke - ausgehend von der Methode '' | ||
+ | |||
+ | < | ||
+ | <div class=" | ||
+ | <script type=" | ||
+ | Spielfeld sp = new Spielfeld(10, | ||
+ | sp.init(); | ||
+ | |||
+ | while(true); | ||
+ | |||
+ | /** | ||
+ | * Ein Objekt der Klasse Spielfeld enthält und verwaltet alle Zellen. | ||
+ | */ | ||
+ | class Spielfeld { | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | this.spalten = spalten; | ||
+ | this.zeilen = zeilen; | ||
+ | this.minenAnzahl = minenAnzahl; | ||
+ | zellen = new Zelle[spalten][zeilen]; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Instanziere alle Zellen und " | ||
+ | */ | ||
+ | | ||
+ | // Erzeuge zunächst Zellen ohne Minen. | ||
+ | for(int spalte = 0; spalte < spalten; spalte++) { | ||
+ | | ||
+ | | ||
+ | zellen[spalte][zeile] = new Zelle(this, ZellBild.hintergrund_leer, | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | // " | ||
+ | for(int i = 0; i < minenAnzahl; | ||
+ | | ||
+ | | ||
+ | int spalte = Math.floor(Math.random() * spalten); | ||
+ | int zeile = Math.floor(Math.random() * zeilen); | ||
+ | Zelle zelle = zellen[spalte][zeile]; | ||
+ | if(zelle.getInhalt() != ZellBild.mine) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | |||
+ | // Zähle für jede nicht-Minen-Zelle die Nachbarminen und stelle die | ||
+ | // Anzahl als Zahlengrafik dar. | ||
+ | for(int spalte = 0; spalte < spalten; spalte++) { | ||
+ | | ||
+ | | ||
+ | Zelle zelle = zellen[spalte][zeile]; | ||
+ | if(zelle.getInhalt() == ZellBild.hintergrund_leer) { | ||
+ | int nachbarbomben = zähleNachbarMinen(zelle); | ||
+ | | ||
+ | zelle.setZustand(ZellBild.zahl_0 + nachbarbomben, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | | ||
+ | return minenAnzahl; | ||
+ | } | ||
+ | |||
+ | | ||
+ | int nachbarMinen = 0; | ||
+ | for(int dx = -1; dx <= 1; dx++) { | ||
+ | | ||
+ | if(dx != 0 || dy != 0) { | ||
+ | int spalte = zelle.getSpalte() + dx; | ||
+ | int zeile = zelle.getZeile() + dy; | ||
+ | | ||
+ | if(zellen[spalte][zeile].getInhalt() == ZellBild.mine) { | ||
+ | | ||
+ | }; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | return nachbarMinen; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Zerstört alle Zellen des Spielfelds | ||
+ | */ | ||
+ | | ||
+ | for(int spalte = 0; spalte < spalten; spalte++) { | ||
+ | | ||
+ | |||
+ | zellen[spalte][zeile].destroy(); | ||
+ | zellen[spalte][zeile] = null; | ||
+ | |||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Berechnet die x-Koordinate des Pixels am linken Rand der übergebenen Spalte. | ||
+ | */ | ||
+ | | ||
+ | return 21 + 32 * spalte; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Berechnet die y-Koordinate des Pixels am oberen Rand der übergebenen Zeile. | ||
+ | */ | ||
+ | | ||
+ | return 116 + 32 * zeile; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Wird von Zelle.onMouseUp aufgerufen und deckt die Zelle auf. | ||
+ | * Enthält sie keine Mine und enthalten auch die Nachbarzellen keine Minen, so werden | ||
+ | * rekursiv alle benachbarten Zellen aufgedeckt, die ebenfalls keine Minen enthalten | ||
+ | * und deren Nachbarzellen ebenfalls keine Minen enthalten. | ||
+ | */ | ||
+ | | ||
+ | zelle.aufdecken(); | ||
+ | if(zelle.getInhalt() == ZellBild.hintergrund_leer) { | ||
+ | // Falls weder die Zelle noch die Nachbarzellen Minen enthalten, | ||
+ | // dann untersuche die acht benachbarten Zellen: | ||
+ | | ||
+ | for(int dy = -1; dy <= 1; dy++) { | ||
+ | if(dx != 0 || dy != 0) { | ||
+ | int spalte = zelle.getSpalte() + dx; | ||
+ | int zeile = zelle.getZeile() + dy; | ||
+ | if(spalte >= 0 && spalte < spalten && zeile >= 0 && zeile < zeilen) { | ||
+ | // Hole das benachbarte Zellen-Objekt | ||
+ | Zelle zelle = zellen[spalte][zeile]; | ||
+ | | ||
+ | klickAufZelle(zelle); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Fürs Intro: Zufällige Zelle öffnen | ||
+ | */ | ||
+ | | ||
+ | int spalte = Math.floor(Math.random() * spalten); | ||
+ | int zeile = Math.floor(Math.random() * zeilen); | ||
+ | klickAufZelle(zellen[spalte][zeile]); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Markiere die Zelle mit einer Fahne | ||
+ | */ | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Entferne die Fahnen-Markierung der Zelle | ||
+ | */ | ||
+ | | ||
+ | zelle.setZustand(zelle.getInhalt(), | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Nachdem das Spiel verloren ist, werden alle Zellen aufgedeckt. | ||
+ | */ | ||
+ | | ||
+ | for(int spalte = 0; spalte < spalten; spalte++) { | ||
+ | | ||
+ | | ||
+ | Zelle zelle = zellen[spalte][zeile]; | ||
+ | if(zelle.istZugedeckt()) { | ||
+ | | ||
+ | if(zelle.getInhalt() == ZellBild.mine) { | ||
+ | | ||
+ | } else { | ||
+ | | ||
+ | } | ||
+ | } else { | ||
+ | zelle.aufdecken(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Gibt genau dann true zurück, wenn alle Minen markiert und alle anderen | ||
+ | * Zellen aufgedeckt sind. | ||
+ | */ | ||
+ | | ||
+ | for(int spalte = 0; spalte < spalten; spalte++) { | ||
+ | | ||
+ | Zelle zelle = zellen[spalte][zeile]; | ||
+ | if(zelle.istZugedeckt() && !zelle.hatFahne()) return false; | ||
+ | } | ||
+ | } | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | }</ | ||
+ | |||
+ | <script type=" | ||
+ | // Indizes der Sprites für die verschiedenen Zellbilder | ||
+ | class ZellBild { | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Die Klasse Zelle repräsentiert eine quadratische Zelle des Spielfeldes. Sie wird mithilfe von | ||
+ | * zwei Sprites gezeichnet: dem Hintergrund (Zell-Objekt ist selbst ein Sprite) und dem Vordergrund | ||
+ | * (gleichnamiges Attribut). | ||
+ | */ | ||
+ | class Zelle extends Sprite { | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | // Jede Zelle " | ||
+ | // öffentliche Methoden aufrufen. | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | super(spielfeld.spalteToX(spalte), | ||
+ | vordergrund = new Sprite(spielfeld.spalteToX(spalte), | ||
+ | this.spielfeld = spielfeld; | ||
+ | this.spalte = spalte; | ||
+ | this.zeile = zeile; | ||
+ | setZustand(zustand, | ||
+ | } | ||
+ | |||
+ | | ||
+ | return inhalt; | ||
+ | } | ||
+ | |||
+ | | ||
+ | return zeile; | ||
+ | } | ||
+ | |||
+ | | ||
+ | return spalte; | ||
+ | } | ||
+ | |||
+ | | ||
+ | return zugedeckt; | ||
+ | } | ||
+ | |||
+ | | ||
+ | return fahne; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Ändert sich der Zustand der Zelle, so sorgt die Methode setZustand dafür, | ||
+ | * dass die Bilder der Sprites entsprechend gesetzt werden. | ||
+ | */ | ||
+ | | ||
+ | if(zugedeckt) { | ||
+ | | ||
+ | vordergrund.setImageIndex(ZellBild.fahne); | ||
+ | } else { | ||
+ | vordergrund.setImageIndex(ZellBild.zugedeckt); | ||
+ | } | ||
+ | } else { | ||
+ | | ||
+ | } | ||
+ | this.zugedeckt = zugedeckt; | ||
+ | this.fahne = fahne; | ||
+ | this.inhalt = inhalt; | ||
+ | } | ||
+ | |||
+ | | ||
+ | super.destroy(); | ||
+ | vordergrund.destroy(); | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Wird vom Browser aufgerufen, wenn der Mauszeiger sich von außen in die Zelle hineinbewegt | ||
+ | */ | ||
+ | | ||
+ | if(zugedeckt) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Wird vom Browser aufgerufen, wenn der Mauszeiger sich aus der Zelle | ||
+ | * hinausbewegt. | ||
+ | */ | ||
+ | | ||
+ | vordergrund.tint("# | ||
+ | getWorld().setCursor(" | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Wird vom Browser aufgerufen, wenn eine der Maustasten nach unten gedrückt wird. | ||
+ | */ | ||
+ | | ||
+ | vordergrund.tint("# | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Wird vom Browser aufgerufen, wenn eine der Maustasten losgelassen wird. | ||
+ | */ | ||
+ | | ||
+ | |||
+ | if(key == 0) { // linke Maustaste, also aufdecken | ||
+ | | ||
+ | // Mine erwischt? | ||
+ | | ||
+ | inhalt = ZellBild.mine_explodiert; | ||
+ | setZustand(inhalt, | ||
+ | return; | ||
+ | } | ||
+ | | ||
+ | } else { | ||
+ | // Rechte Maustaste => Fahne setzen oder löschen | ||
+ | | ||
+ | if(!fahne) { | ||
+ | | ||
+ | } else { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | | ||
+ | setZustand(inhalt, | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ |
api/projects/minesweeper/spielfeld/start.txt · Zuletzt geändert: 2024/08/31 10:03 von 127.0.0.1