Die Aufgabenstellung
Bermuda ist ein kleines Spiel, das mit einer einfachen Textoberfläche in einem Applet realisiert werden kann und damit ideal zur Demonstration verwendbar ist.In einem Feld von 9x7 Punkten sind Schiffe verschwunden, die durch Anticken der Positionen gesucht werden können. Nach Anklicken zeigt die Position ein X, wenn ein Schiff gefunden wurde oder eine Zahl, die Auskunft gibt, in wieviele Richtungen (!) Schiffe gesehen werden. Ein Schiff kann also durch ein davor liegendes verdeckt werden.
Das Auffinden aller Schiffe soll erkannt und dem Anwender angezeigt werden. Er soll die Möglichkeit haben, das Spiel neu zu starten.
Das Spiel als Applet
Spielen Sie: es sollte funktionieren, wenn Ihr Browser Java unterstützt.
Die Sourcen
Die Klasse Schiff simuliert ein eigenes Schiff, das neben einer Position nur die Information enthält, ob es bereits entdeckt wurde.public class Schiff { private int x, y; private boolean gefunden; Schiff() { gefunden = false; x = 0; y = 0; } void setPos(int px, int py) { x = px; y = py; gefunden = false; } boolean istPos(int px, int py) { return (px==x && py==y); } void setGefunden(boolean parGefunden) { gefunden = parGefunden; } boolean istGefunden() { return gefunden; } } |
Die Klasse SpielFeld realisiert das Spielfeld von 9 x 7 Feldern in einem zweidimensionalen Array. In einem einfachen Array werden die vier Schiffe abgelegt. Das Spielfeld versteckt die Schiffe und sucht nach ihnen.
import java.util.Random; class SpielFeld { final int MaxX = 9; final int MaxY = 7; private char feld[][] = null; final int MAXSCHIFF = 4; private Schiff schiff[] = null; final char SCHIFF = 'X'; SpielFeld() { // Spielfeld vorbereiten feld = new char[MaxX][]; for (int x=0; x<MaxX; x++) { feld[x] = new char [MaxY]; for (int y=0; y<MaxY; y++) { feld[x][y] = '.'; } } // Schiffe vorbereiten schiff = new Schiff[MAXSCHIFF]; for (int i=0; i<MAXSCHIFF; i++) { schiff[i] = new Schiff(); } // Schiffe verteilen Random zufall = new Random(); for (int i=0; i<MAXSCHIFF; i++) { boolean kollidieren = false; do { int x = Math.abs(zufall.nextInt()) % MaxX; int y = Math.abs(zufall.nextInt()) % MaxY; schiff[i].setPos(x, y); kollidieren = false; for (int j=0; j<i; j++) { if (schiff[j].istPos(x, y)) { kollidieren = true; } } } while (kollidieren); } } public char get(int x, int y) { return feld[x][y]; } boolean alleGefunden() { boolean gefunden = true; for (int i=0; i<MAXSCHIFF; i++) { if (schiff[i].istGefunden()==false) { gefunden = false; } } return gefunden; } // ----- Suche die Schiffe und melde die Anzahl der Richtungen ----- // lokal zu suche: schau auf das Feld private int schauMal(int posX, int posY) { for (int i=0; i<MAXSCHIFF; i++) { if (schiff[i].istPos(posX, posY)) { return i+1; } } return 0; } // lokal zu suche: laufe eine Linie entlang private int linieLaufen(int posX, int posY, int diffX, int diffY) { // Verhindere Endlosschleife! Entweder diffX oder diffY muss !=0 sein. if (diffX==0 && diffY==0) return 0; // Vorgegebene Richtung bis zum Rand durchlaufen while (posX>=0 && posX<MaxX && posY>=0 && posY<MaxY) { posX += diffX; posY += diffY; // Gefunden? Suche in dieser Richtung abbrechen! if (schauMal(posX, posY)>0) return 1; } return 0; } // Aufruf zur Suche für posX, posY public char suche(int posX, int posY) { // haben wir bereits ein Schiff getroffen? int index = schauMal(posX, posY); if (index>0) { schiff[index-1].setGefunden(true); feld[posX][posY] = SCHIFF; } else { // suche in alle Richtungen int anzahl=0; for (int diffX=-1; diffX<=1; diffX++) { for (int diffY=-1; diffY<=1; diffY++) { anzahl += linieLaufen(posX, posY, diffX, diffY); } } feld[posX][posY] = (char)('0'+anzahl); } return feld[posX][posY]; } } |
BermudaApplet erweitert die Klasse JApplet und kümmert sich um die Darstellung und die Interaktion mit dem Benutzer.
import javax.swing.*; import java.awt.event.*; import java.awt.*; public class BermudaApplet extends JApplet implements MouseListener { SpielFeld sf = null; boolean spielEnde = false; // ist das Spiel beendet worden? String StatusStr = " "; public void init() { this.addMouseListener(this); // fange die Mausereignisse this.setSize(320,200); sf = new SpielFeld(); } // Anzeige des Spielfelds findet durch repaint statt public void paint(Graphics g) { for (int i=0; i<sf.MaxX; i++) { for (int j=0; j<sf.MaxY; j++) { String str = String.valueOf(sf.get(i,j)); g.drawString(str, (i+1)*20, (j+1)*20); } } g.drawString(StatusStr, 10, (sf.MaxY+1) * 20); } // der Benutzer tut was relevantes, er klickt mit der Maus public void mouseClicked(MouseEvent me) { if (!spielEnde) { int x = (me.getX()-10)/20; int y = (me.getY()-10)/20; char c = sf.suche(x, y); if (c==sf.SCHIFF) { if (sf.alleGefunden()) { // alle gefunden: GEWONNEN! spielEnde = true; StatusStr = "Gewonnen! Mausklick: neues Spiel"; } } } else { // sonderfall: Mausklick, um Sieg zu bestaetigen spielEnde = false; StatusStr = " "; sf = new SpielFeld(); } repaint(); } // zur Realisierung des Interface, auch wenn wir die Methoden nicht brauchen... public void mouseReleased(MouseEvent me) { } public void mousePressed(MouseEvent me) { } public void mouseEntered(MouseEvent me) { } public void mouseExited(MouseEvent me) { } } |