Grundlagen der Programmierung 2 SS 2005 - Datei Memory.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Memory extends JFrame
{
private JLabel timeLabel;
private TimeCounter time;
// Konstruktor
public Memory()
{
super("Memory");
// Unser Zeitmesser
time = new TimeCounter(this);
// Nur ein Listener-Objekt fuer alle Felder:
MemoryListener memListener = new MemoryListener(time);
Container content = this.getContentPane();
content.setLayout(new BorderLayout());
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(4, 4));
// Buttons fuer die Felder erzeugen:
for (int i = 0; i < 16; i++)
{
CharButton b = new CharButton(this.getCharacter());
buttonPanel.add(b);
b.addActionListener(memListener);
b.cover();
}
// Label fuer die Zeitanzeige
timeLabel = new JLabel("00:00", JLabel.CENTER);
timeLabel.setFont(new Font(null, Font.PLAIN, 20));
// Elemente auf den ContentPane packen
content.add(buttonPanel, BorderLayout.CENTER);
content.add(timeLabel, BorderLayout.SOUTH);
setSize(300, 350);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
// Zeitmessung starten
time.start();
}
// Die Beschriftungen der Felder:
private String[] labels = { "A", "B", "C", "D", "E", "F", "G", "H", "A",
"B", "C", "D", "E", "F", "G", "H" };
private int labelsLength = labels.length;
private String getCharacter()
{
// Waehlt einen Label zufaellig aus dem Array
// und entfernt ihn daraus.
int pos = (int) (Math.random() * 100) % labelsLength;
String c = labels[pos];
// Luecke im Array schliessen:
for (int i = pos + 1; i < labelsLength; i++)
{
labels[i - 1] = labels[i];
}
labelsLength--;
return c;
}
public void drawCurrentTimeString(String timeString)
{
timeLabel.setText(timeString);
}
public static void main(String[] args) throws Exception
{
Memory m = new Memory();
}
}
// separate Klasse fuer den Listener:
class MemoryListener implements ActionListener
{
// Die bisher aufgedeckten Felder:
private CharButton firstSelection = null;
private CharButton secondSelection = null;
// Zaehler fuer die bisher entdeckten Paare
private int pairsFound = 0;
// Referenz auf den Zeitmesser
private TimeCounter time;
// Konstruktor
public MemoryListener(TimeCounter time)
{
super();
this.time = time;
}
public void actionPerformed(ActionEvent e)
{
// Das gerade gewaehlte Feld:
CharButton flipped = (CharButton) e.getSource();
// Drei Zustaende:
// kein, ein, zwei Feld(er) ist/sind aufgedeckt:
if (firstSelection == null)
{
// kein Feld - nun das erste:
firstSelection = flipped;
flipped.setEnabled(false);
flipped.uncover();
}
else if (secondSelection == null)
{
// ein Feld - nun das zweite:
flipped.setEnabled(false);
flipped.uncover();
secondSelection = flipped;
if (firstSelection.getChar().equals(secondSelection.getChar()))
{
// Die Marken sind gleich:
firstSelection.setBackground(Color.BLACK);
secondSelection.setBackground(Color.BLACK);
// Neue Wahl vorbereiten:
firstSelection = null;
secondSelection = null;
// Zaheler erhoehen
pairsFound++;
// Spiel beendet?
if (pairsFound == 8)
{
// Zeitmesser stoppen
time.stopIt();
JOptionPane.showMessageDialog(null,
"You have completetd the game in "
+ time.getTimeString() + "!", "Memory",
JOptionPane.INFORMATION_MESSAGE);
}
}
else
{
// Die Marken sind verschieden
// Sie bleiben aufgedeckt bis zur naechsten Wahl
}
}
else
{
// Nach einem Fehlversuch wurde drittes Feld aufgedeckt:
flipped.setEnabled(false);
flipped.uncover();
firstSelection.cover();
firstSelection.setEnabled(true);
firstSelection = flipped;
secondSelection.cover();
secondSelection.setEnabled(true);
secondSelection = null;
}
}
}
// Hilfsklasse: Button-Unterklasse mit verdeckbarer Beschriftung:
class CharButton extends JButton
{
private String myLabel;
CharButton(String lab)
{
super(lab);
myLabel = lab;
}
void uncover()
{
setText(myLabel);
}
void cover()
{
setText("");
}
String getChar()
{
return myLabel;
}
}
// Klasse zum Messen der Zeit
class TimeCounter extends Thread
{
// wie spät war es als das Spiel gestartet wurde?
private long startTime;
// Referenz auf den Memory-Frame
private Memory mem;
// Kontrollvariable für den Thread
private boolean running;
// Konstruktor mit Uebergabe des Memory-Frames
public TimeCounter(Memory owner)
{
mem = owner;
}
// liefert die seit Spielbeginn vergangene Zeit in Sekunden
private int getDuration()
{
long deltaTime = System.currentTimeMillis() - startTime;
// vergangene Zeit in Millisekunden in Sekunden umrechnen
// dabei wird abgerundet
return (int) (deltaTime / 1000L);
}
// Wandelt die aktuelle Zeit in einen passenden String um
public String getTimeString()
{
int time = getDuration();
// Bestimmung von Minuten und Sekunden
int minutes = time / 60;
int seconds = time % 60;
String timeString;
// Fuehrende Nullen erkennen und String zusammenfuegen
if (minutes < 10)
timeString = "0" + minutes;
else
timeString = String.valueOf(minutes);
if (seconds < 10)
timeString += ":0" + seconds;
else
timeString += ":" + seconds;
return timeString;
}
public void run()
{
running = true;
startTime = System.currentTimeMillis();
while (running)
{
// Zeitspanne im Fenster anzeigen:
// direkter Aufruf ist gefährlich, weil Swing-Komponenten
// nur aus einem Thread (dem Event-Thread) heraus benutzt
// werden dürfen.
// mem.drawCurrentTimeString(getTimeString());
// So ist es richtig:den Aufruf in ein Runnable-Objekt kapseln
// und an den Event-Thread übergeben. Dieser ruft die run-Methode
// des Objekts auf, sobald keine anderen Events mehr zu verarbeiten
// sind.
SwingUtilities.invokeLater(
new Runnable()
{
public void run ()
{ mem.drawCurrentTimeString(getTimeString()); }
}
);
// Fuer 1000 ms warten
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
}
}
public void stopIt()
{
running = false;
}
}
Generiert mit Camelot | Probleme mit Camelot? | Geändert am: 27.05.2005


