P. Pfahler, E. Stümpel
Programmieren in Java, Winter 1997/98
Lösung des 1. Übungsblatt
Aufgabe 1:
==========
Anhängend finden Sie ein Java Applet für ein einfaches 3x4-Schiebespiel.
Aus dem Programm sind die Kommentare entfernt worden. Kommentieren Sie
dieses Programm neu und ändern Sie es in ein 4x4-Schiebespiel.
Dieses Applet kann außer in einem Java-fähigen Web-Browser auch mit dem
"appletviewer" ausgeführt werden. In beiden Fällen brauchen Sie eine
HTML-Datei, die etwa so aussieht:
Slider Applet
Hier kommt das Applet slider":
-------------------------------
//------------------------------------------------------
// (Slider - Jan 12, 1991)
// by Julie Ton
// Modified : Slider.java - October 20, 1996
// Modified : Slider.java - August 15, 1997 (peter)
// Modified : Slider.java - October 24, 1997 (g. mein)
//-------------------------------------------------------
import java.awt.*; //Import von Java-Klassen aus den Java API Packages
import java.applet.Applet; //werden so unter der abgekürzten Schreibweise verfügbar
/*
* Die Applet Klasse muß die Superklasse jedes Applets sein.
* Sie definiert ein Standard-Interface zwischen Applets und
* ihrer Umgebung.
*
* Vererbungshierachie:
*
* java.lang.Object
* |
* +----java.awt.Component
* |
* +----java.awt.Container
* |
* +----java.awt.Panel
* |
* +----java.applet.Applet
*
* Die Applet Klasse definiert eine Menge von Methoden, die
* vom System aufgerufen werden, wenn bestimmte Ereignisse
* auftreten.
* Jedes selbstgechriebene Applet muß zumindest einige dieser
* Methoden überschreiben, um wie gewünscht abzulaufen.
* Drei solche hier überschriebene Methoden sind init(),
* paint(Graphics g) und mouseUp (Event evt, int x, int y).
* (mouseUp existiert seit Java 1.1 nicht mehr und wird vom
* Compiler angemäkelt (deprecated).)
*/
public
class slider extends Applet
{ //KONSTANTEN-Definitionen:
static final int MAX_ROW = 4; //Zeilen- und
static final int MAX_COL = 4; //Spaltenzahl des Schiebespiels
static final int IMAGE_WIDTH = 100; //Breite und
static final int IMAGE_HEIGHT = 100; //Hoehe eines(!) Spielsteins
static int Piece [] = { 2, 12, 6, 13, //Verteilung der Steine fuer den
5, 4, 9, 14, //Startzustand
7, 8, 3, 15,
10, 11, 1, 16};
static final int BLANK = -1; //zeigt an, dass eine berechnete Steinposition
//außerhalb des Spielsfelds liegt
static final int MAX_PIECES = MAX_ROW * MAX_COL; //Anz. Steine insgesamt
static int Blank_Index; //Index für das leere Feld
static int Hilite_Up ; //Index des oberen,
static int Hilite_Down ; //unteren,
static int Hilite_Left ; //linken und
static int Hilite_Right ; //rechten Nachbarn des leeren Feldes
public void init() //Initialisiert das Applet bei jedem (re-)load
{
repaint(); //Methode aus java.awt.Componet, die die Komponente
//neu zeichnet (ruft die update-Methode der
//Komponente auf, die alles mit der
//Hintergrundfarbe füllt und die paint-Methode
//aktiviert ( (0,0) ist die linke obere Ecke im
//Graphik-Kontext )
for (int i = 0; i < MAX_PIECES; i++) { //Bestimme die Position des höchstwertigen
if (Piece [i] == (MAX_PIECES)) { //Steines; dieser wird als leeres Feld
Blank_Index = i; //ausgegeben
break;
}
}
Set_Hilite_Pieces (); //Methodenaufruf zum Färben der Nachbarsteine
//des leeren Feldes
}
void Set_Hilite_Pieces () //Bestimme die Indices der Nachbarsteine des
{ //leeren Feldes
int row = Blank_Index / MAX_COL; //Zeilen-
int col = Blank_Index % MAX_COL; //und Spaltenindex des leeren Feldes
Hilite_Up = row > 0 ? Blank_Index - MAX_COL : BLANK; //Berechnung der Indices der
Hilite_Down = row < MAX_ROW-1 ? Blank_Index + MAX_COL : BLANK; //Nachbarsteine, falls außerhalb
Hilite_Left = col > 0 ? Blank_Index - 1 : BLANK; //des Spielfeldes Index=BLANK (s.o.)
Hilite_Right = col < MAX_COL - 1 ? Blank_Index + 1 : BLANK;
}
public void paint (Graphics g) //überschreibt paint-Methode von java.awt.Componet
{ //Zeichnet das Applet
int col, row, index;
int x, y;
g.drawRect (0,0,IMAGE_WIDTH * MAX_COL + 2, //Methode der Klasse Graphics (java.awt.Graphics)
IMAGE_HEIGHT * MAX_ROW + 2); //Zeichnet Rechteck von (0,0) aus mit Breite, Höhe wie angegeben
index = 0;
for (row = 0 ; row < MAX_ROW ; row++) //Durchlauf durch alle Steinpositionen
{
for (col = 0 ; col < MAX_COL ; col++, index++)
{
x = col * IMAGE_WIDTH + 2; //(x,y) linke obere Ecke des zu malenden Steines
y = row * IMAGE_HEIGHT + 2;
if (index == Hilite_Up
|| index == Hilite_Down
|| index == Hilite_Left
|| index == Hilite_Right) //Falls Nachbarstein des leeren Feldes:
g.setColor (Color.blue); // Steinfarbe=Blau
else if (index == Blank_Index) //Falls leeres Feld:
g.setColor (Color.yellow); // Steinfarbe=Gelb
else g.setColor (Color.black); //Sonst Steinfarbe=Schwarz
g.drawRect (x, y, IMAGE_WIDTH - 2, IMAGE_HEIGHT - 2); //Zeichne Steinumriß
g.fillRect (x, y, IMAGE_WIDTH - 2, IMAGE_HEIGHT - 2); //Fülle mit Steinfarbe
g.setColor (Color.orange); //Farbe=Orange
g.setFont(new Font("Courier", Font.BOLD, 16)); //Schriftart und Größe
int xoff;
if (Piece [index] < 10) xoff = 3; //bestimme passende offsets zur mittigen Positionierung
else if (Piece [index] < 100) //1-, 2- und höherstelliger Zahlen
xoff = 6;
else xoff = 9;
x = x + (IMAGE_WIDTH / 2) - xoff; //Bestimme (x,y) Position der Beschriftung
y = y + (IMAGE_HEIGHT / 2) + (IMAGE_HEIGHT / 6); //für den Stein
if (index == Blank_Index) //Falls leeres Feld
g.drawString(" ", x, y); // keine Beschriftung
else g.drawString(String.valueOf (Piece [index]), x, y); //Sonst Steinnummer
}
}
}
// Methode, die bei dem Mause-Event "Taste losgelassen"
public boolean mouseUp (Event evt, int x, int y) //überschreibt paint-Methode von java.awt.Componet
{ //Note: mouseUp() is deprecated. As of JDK version 1.1,
//replaced by processMouseEvent(MouseEvent).
//! wer einmal in den Java API Packages gestöbert hat, der
// ist auf obige Anmerkung gestoßen, die darauf hinweist,
// daß diese Funktion seit der Umstellung von 1.0xx auf 1.1xx
// so nicht mehr existiert ("deprecated=verworfen"), was sich
// auch bei der Übersetzung mit einer WARNING bemerkbar macht :)
int col = x / IMAGE_WIDTH; //Spalten- und Zeilennummer des selektierten Steines
int row = y / IMAGE_HEIGHT; //aus der Mausposition berechnen
if (col < 0 || col >= MAX_COL || row < 0 || row >= MAX_ROW) //Falls außerhalb des Spielfeldes
return false; // tue nichts
int selected_index = col + (row * MAX_COL); //Sonst berechne Index im Array
if (Valid_Move (selected_index)) //prüfe, ob gültiger Spielzug (nur die Nachbarsteine des
{ //leeren Feldes sind beweglich!
int temp = Piece [selected_index];
Piece [selected_index] = Piece [Blank_Index];
Piece [Blank_Index] = temp;
Blank_Index = selected_index; //leeres Feld und ausgewählten Stein vertauscht
Set_Hilite_Pieces (); //bestimme die neuen Nachbarsteine des leeren Feldes
repaint (); //zeichne das Spielfeld neu
}
return true;
}
boolean Valid_Move (int selected_index) //prüft, ob gültiger Spielzug (Nachbarstein selektiert?)
{
return (selected_index == Hilite_Up ||
selected_index == Hilite_Down ||
selected_index == Hilite_Right ||
selected_index == Hilite_Left);
}
}