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); } }