Sie sind auf Seite 1von 14

Programmierpraktikum Sommer 2023 Department Mathematik / Informatik

April 2023 Dr. Vera Weil


Meilenstein 1
Abgabetermin: Montag, 15. Mai 2023, 10:00 Uhr
(Muss um 10 Uhr auf dem Server sein!)
Termin zur Einsichtnahme: Achten Sie auf die Ankündigungen in Ilias.

Inhaltsverzeichnis
1 Formales 1
1.1 Bearbeiten der Lösung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Einreichung, Prüfung und Bewertung Ihrer Lösung . . . . . . . . . . . . . . . . 3
1.3 Weiteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4 Vorbereitung ("Aufgabe 0") - Klonen Sie das Repository . . . . . . . . . . . . . . 4

2 Aufgaben 5
2.1 Aufgabe 1 - Arrays und Zufall - 45 Punkte . . . . . . . . . . . . . . . . . . . . . 5
2.2 Aufgabe 2 - Vererbung und Comparable - 75 Punkte . . . . . . . . . . . . . . . 6
2.3 Aufgabe 3 - Arraylists und Strings - 80 Punkte . . . . . . . . . . . . . . . . . . . 8
2.4 Aufgabe 4 - Graphische Benutzeroberfläche - 140 Punkte . . . . . . . . . . . . . 11

1 Formales

1.1 Bearbeiten der Lösung


(1) MS1 ist eine Einzelleistung. Erstellen Sie Ihre Lösung selbst und stellen Sie diese nicht
zur Verfügung. Andernfalls kann Ihnen das als Täuschungsversuch angekreidet werden.

(2) Maschinenunabhängigkeit. Alle Ihre Programme müssen maschinenunabhängig lau-


fen. Das heißt insbesondere, dass Sie keine absoluten Pfade verwenden dürfen und dass
Sie die Namen der Dateien und Ordner, auf die Sie zugreifen, sowie deren Dateiendungen
klein schreiben müssen.
Beachten Sie auch, dass verschiedene Betriebssysteme unterschiedliche Zeichen für Zeile-
numbrüche etc. verwenden. Sie müssen alle Ihre .java-Dateien in utf8-Kodierung spei-
chern; gerade bei Windows ist utf8 leider nicht standardmäßig in Eclipse eingestellt.
Fehler, die auf der falschen Kodierung beruhen, gehen zu Ihren Kosten.
Weiterhin müssen Sie zum Einlesen von Daten
getResourceAsStream(String name) oder getResource(String name)
der Klassen java.lang.Class oder java.lang.ClassLoader benutzen.

1
Bei der Bezeichnung der Bilddatei in der GUI-Aufgabe muss also alles klein geschrieben
sein, auch die Endung. Um das im Repo hinterlegte Bild „siegel.jpg“ zu verwenden, lautet
der zu verwendende String /resources/siegel.jpg.

(3) Umgang mit dem Repo. Ändern / Löschen Sie nicht die vorgegebene Ordnerstruktur /
Packages in den Repositories. Hinzufügen von weiteren Klassen in die jeweiligen Packages
ist kein Problem. Wenn nicht anders angegeben, sollen alle Klassen in das gleiche Package
gespeichert werden, in dem auch die Hauptklasse (also die mit der main-Methode) gespei-
chert ist. Ausnahme: Für die GUI-Aufgabe dürfen Sie bei Bedarf auch weitere Packages
hinzufügen.

(4) Kommentare. Wir empfehlen dringend, Ihre Dateien ordentlich, ggf. sogar im Javadoc-
Style zu dokumentieren. Beispiele für Javadoc-Kommentare: siehe Kommentare in der
API-Spezifikation.

(5) Java 17. Wir kompilieren mit Java 17. Fehler, die aufgrund einer anderen Java-Version
entstehen, gehen zu Ihren Lasten. Sie dürfen nur die Java-Standardbibliothek benutzen.

(6) Modifikatoren. Deklarieren Sie

• alle Getter und Setter sowie Konstruktoren und Klassen als public,
• alle von uns verlangten Methoden als public,
• alle Attribute (Klassen- und Objektattribute) als private, und statten Sie die ent-
sprechende Klasse mit allen entsprechenden Gettern und Settern aus; diese sind nach
der Konvention zu benennen (das ist per se erfüllt, wenn Sie diese automatisch durch
Eclipse generieren lassen, z.B.),
• alle abstrakten Methoden in Interfaces ohne Modifikator (sie sind dann automatisch
abstract und public),
• alle Methoden, die in der Hauptklasse stehen, als public und static,

es seid denn, wir wünschen uns explizit einen anderen Modifikator. Andere Modifika-
toren als die von uns vorgeschriebenen können zu hohem Punktverlust führen. Bei der
GUI-Aufgabe (in welcher Methoden, Attribute, etc. nicht vorgegeben sind) sollten Sie
sich an die Konventionen halten.

(7) Konstruktoren (bezieht sich nicht auf GUI): Es sind ausschließlich die Konstruktoren
zu implementieren, die explizit in der Aufgabenstellung genannt sind.

(8) Hilfsmethoden und -variablen (bezieht sich nicht auf GUI): Hilfsmethoden sind er-
laubt und müssen bei Verwendung mitgepusht werden. Initialisieren Sie im Konstruk-
tor (Hilfs-)variablen, verwenden Sie im Konstruktor Hilfsmethoden oder implemen-
tieren Sie im Konstruktor Zuweisungen, ohne, dass diese Vorgänge explizit in der

2
Aufgabe verlangt werden, so müssen alle Ihre Methoden auch ohne diese Konstruktor-
Vorgänge funktionieren. Ihre Methoden müssen weiterhin auch unabhängig von Attribut-
Initialisierungen bei Deklaration funktionieren (es sei denn, wir haben diese Initialisierung
explizit verlangt). Weiterhin werden Vorgänge in der main-Methode von unseren Tests
nicht beachtet. Initialisieren Sie dort also keine Elemente, die zwingend für die Lösung
der Aufgaben notwendig sind, da wir die main-Methode ja nicht zum Testen verwenden
werden (siehe auch (11)).

(9) Bezeichnungen und Modifikatoren: Halten Sie sich genau an die Vorgaben, vor allem
was die Modifikatoren und Bezeichnungen angeht. Getter und Setter bezeichnen Sie an-
hand der gängigen Konventionen (bei automatischer Generierung mit Eclipse sind diese
beispielsweise eingehalten).

(10) Attribute: Abkürzend schreiben wir Attribut statt Objektattribut. Handelt es sich bei
einem Attribut um ein Klassenattribut, so schreiben wir das explizit in die Aufgabenstel-
lung.

(11) Ausgaben auf die Konsole (bezieht sich nicht auf die GUI-Aufgabe): Die einzige Me-
thode, welche bei Abgabe Ausgaben auf die Konsole machen darf, ist die main-Methode
der jeweiligen Aufgabe. Haben Sie noch Ausgaben (also print-Befehle), die Sie zwecks
Selbstkontrolle in Methoden eingebaut haben, so kommentieren Sie diese aus oder lö-
schen Sie diese. Ausgaben, die außerhalb der main-Methode erzeugt werden, führen zu 0
Punkten in unserem Testsystem.

(12) Angenommen, Ihre S-Mail lautet mmu@smail.uni-koeln.de, so ist Ihr S-Mail-Kürzel


mmu. Die URL für MS1 (z.B.) wäre dann:
ssh://mmu@progserver.informatik.uni-koeln.de:4711/srv/pp/git/pp23/MS1/mmu.git
Für weitere Informationen, siehe git-Starthilfe.

1.2 Einreichung, Prüfung und Bewertung Ihrer Lösung


(1) Name und Matrikelnummer. In jeder Ihrer .java-Dateien geben Sie ganz oben als
Kommentar Ihren Namen und Ihre Matrikelnummer an. Damit bestätigen Sie, dass Sie
die Lösung eigenständig verfasst haben.

(2) Einreichung. Einreichung nur mit git auf unserem Server. Pushen Sie früh genug. Zum
angegebenen Zeitpunkt muss Ihre Lösung bereits auf unserem Server sein, denn zu diesem
Zeitpunkt wird die Kopie Ihres Repos gezogen.

(3) Kompilierbarkeit. Ihr Programm muss kompilieren und in angemessener Zeit terminie-
ren, sonst erhalten Sie dafür 0 Punkte. Sie müssen also insbesondere dafür sorgen, dass
alle Ihre Klassen kompilierbar sind: Wenn eine Klasse nicht kompilierbar ist, so heißt

3
das übersetzt: Für alle Methoden in der Klasse erhalten Sie 0 Punkte, auch, wenn ein
Teil der Methoden funktionieren würde, wenn die ganze Klasse kompilierbar wäre.

(4) Prüfen Ihrer Lösung. Wir testen im Wesentlichen aufgabenabhängig mit Testfällen
bzw. per Hand auf Funktionalität. Wenn Sie im Laufe Ihrer Lösung Hilfsmethoden in der
Klasse implementieren, so pushen Sie diese mit. Wenn Sie also Ihre Methoden in weitere
Teilmethoden unterteilen sollten, so ist das vollkommen in Ordnung. Beachten Sie, dass
bei den Testfällen beispielsweise auch leere Arrays oder Strings zum Testen verwendet
werden können (es sei denn, wir schließen das explizit aus).
Wir werden Ihre main-Methode nicht zum Testen verwenden (es sei denn, wir geben das
explizit an). Wir empfehlen, dass Sie Ihren Code vor Abgabe selbst gründlich testen.

(5) Bestehensgrenze: Um Meilenstein 1 zu bestehen, benötigen Sie 100 Punkte im algorith-


mischen Teil (Aufgaben 1 bis 3). Die GUI-Aufgabe ist zum Bestehen von Meilenstein 1
irrelevant. Insgesamt gibt es im Portfolio (Meilenstein 1 und Meilenstein 2) 1400 Punk-
te zu erreichen. Die erreichten Punkte aller Aufgaben von Meilenstein 1 fließen in die
Bewertung des Portfolios ein.

(6) Einsichtnahme zu Meilenstein 1: Die Einsichtnahme ist nur für diejenigen, die
nicht bestanden haben. Sie ist freiwillig, eine Teilnahme wird aber empfohlen, insofern
Ihnen nicht klar ist, warum Sie MS1 nicht bestanden haben. Anmeldung nicht erforder-
lich. Termin und Format siehe Ilias. Diejenigen, die bestanden haben, können bei Bedarf
innerhalb von 2 Wochen nach der Einsichtnahme Ihre Bewertung in den Fragestunden
besprechen.

1.3 Weiteres
(1) Es gelten die Angaben auf dem Orgablatt / aus der Einführungsveranstaltung / aus den
anderen Unterlagen auf Ilias, insofern sie den Angaben auf diesem Blatt nicht wider-
sprechen. Im Falle von Widersprüchlichkeiten oder Ungenauigkeiten sowohl auf diesem
Blatt als auch in Verbindung mit anderen Informationen auf Ilias bitten wir Sie, sich
schnellstmöglich mit dem Team in Verbindung zu setzen.

(2) Vergessen Sie nicht, die Umfrage auf Ilias auszufüllen, die sich darauf bezieht, mit welchem
System wir die GUI-Aufgabe von MS1 bewerten sollen (Windows, MacOS).

1.4 Vorbereitung ("Aufgabe 0") - Klonen Sie das Repository


Klonen Sie Ihr Repository mit den Zugangsdaten, die Sie von uns erhalten haben. Schauen Sie
dazu in die git-Starthilfe. Name des Repos: siehe 1.1, (12). Wir gehen davon aus, dass Sie nach
den Übungsstunden in der Woche vom 24.4. (wieder) in der Lage sind, Repositories zu klonen
und mit git zu arbeiten.

4
2 Aufgaben

2.1 Aufgabe 1 - Arrays und Zufall - 45 Punkte


Im Repo finden Sie ein Package namens random. Die Klasse RANDOM_main.java enthält die
main-Methode. Diese dürfen Sie zum Testen verwenden, da sie bei unseren Tests nicht verwen-
det wird.

Erstellen Sie in der Klasse RANDOM_main.java die Methode calcArray(int[] arr). Diese
Methode soll basierend auf den folgenden Regeln ein neues int-Array erstellen, welches genau-
so lang ist wie das übergebene Array arr. Das neue Array soll nach den folgenden Vorgaben
befüllt und zurückgegeben werden.

(a) Falls die Länge von arr gerade und nicht größer als 10 ist:
In der ersten Hälfte des neuen Arrays werden die Werte aus der zweiten Hälfte von arr
gespeichert. In der zweiten Hälfte des neuen Arrays dann die Werte aus der ersten Hälfte
von arr. Dabei bleibt die Reihenfolge der Werte innerhalb der Hälften gleich.
Beispiel: Bei [1,2,3,4,5,6] als Übergabeparameter ist das neue Array [4,5,6,1,2,3].

(b) Falls die Länge von arr gerade und größer als 10 ist:
In dem neuen Array wird in jeder Zelle eine zufällige Zahl gespeichert. Der Wert dieser
zufällig gewählten Zahl ist mindestens 0 und ist höchstens die Anzahl der Zellen von arr.
Allerdings darf am Ende im neuen Array keine Zahl mehrfach vorkommen.
Beispiel: Bei arr = [-5,-4,-3,-2,-1,0,1,2,3,4,5,6] wäre eine zulässige Lösung
z.B. [2,11,6,0,9,12,4,8,3,10,1,5].

(c) Falls die Länge von arr ungerade ist:


Berechnen Sie den Durchschnitt1 D aller Werte in arr mit Ausnahme des Wertes, der bei
arr in der mittleren Zelle steht. Das neue Array unterscheidet sich nur in der mittleren
Zelle von dem übergebenen Array: In dieser Zelle wird ein zufälliger Wert gespeichert.
Dieser hat mindestens den Wert 0 und höchstens den Wert D.
Beispiel: Bei arr = [3,-1,4,2,5] sind in der mittleren Zelle die Werte 0, 1 oder 2
zulässig. Also z.B. [3,-1,2,2,5].

Hinweis(e):

(a) Erinnerung: Beachten Sie unbedingt die formalen Vorgaben aus Abschnitt 1, z.B. auch
in Bezug auf Konsolenausgaben oder Getter und Setter.

(b) Sie dürfen davon ausgehen, dass der Durchschnitt nie kleiner als 0 ist.
1
Mit Durchschnitt ist hier der Durchschnitt als int-Variable unter Verwendung der Abrundungsfunktion
gemeint. Für das Array [1,2,4,8] beträgt der mathematisch korrekte Durchschnitt 3, 75, welcher hier also auf 3
abgerundet werden soll.

5
2.2 Aufgabe 2 - Vererbung und Comparable - 75 Punkte
Im Repo finden Sie das Package compara. Dort existiert die Klasse COMPARA_main.java, welche
die main-Methode enthält. Diese main-Methode dürfen Sie zum Testen Ihrer Klassen verwenden,
da sie bei unseren Tests nicht verwendet wird.

(a) Erstellen Sie eine Klasse namens Fussballer, welche das Interface Comparable aus
der Standardbibliothek implementiert. Als Attribut erhält Fussballer eine int-Variable
gehalt. Erstellen Sie den Konstruktor Fussballer(int gehalt). Durch Aufruf des Kon-
struktors wird die entsprechende Variable gesetzt.

(b) Erstellen Sie die Klasse Torwart, welche von Fussballer erbt. Torwart hat das int[]-
Attribut gehalteneBaelle. Die Länge des Arrays entspricht der Anzahl der Spiele, in
denen der Torwart zum Einsatz kam, der Eintrag in der Zelle mit Index i steht für die
Anzahl an Bällen, die er in Spiel i gehalten hat. Hierbei steht Spiel 0 für das erste Spiel
der Saison. Statten Sie Torwart mit dem Konstruktor Torwart(int gehalt, int[]
gehalteneBaelle) aus, welcher die entsprechenden Werte setzt.

(c) Erstellen Sie die Klasse Feldspieler, welche ebenfalls von Fussballer erbt. Feldspieler
besitzt die int[]-Attribute tore und fouls. Die Länge der beiden Arrays entspricht der
Anzahl der Spiele, in denen der Feldspieler zum Einsatz kam. Der Eintrag in der Zelle mit
Index i in tore steht für die Anzahl der Tore, die der Feldspieler in Spiel i erzielt hat. Der
i-te Eintrag in fouls gibt an, wie viele Fouls der Spieler in dem jeweiligen Spiel begangen
hat. Statten Sie Feldspieler mit dem Konstruktor Feldspieler(int gehalt, int[]
tore, int[] fouls) aus, welcher die entsprechenden Attribute setzt.

(d) Bei der Implementierung des Interfaces muss, insofern bei der Rückgabe (siehe API-
Spezifikation) eine negative Ganzzahl verlangt wird, der Wert -1 zurück gegeben werden
(und kein beliebiger, negativer Wert). Analog darf kein beliebiger positiver Wert, sondern
+1 zurück gegeben werden.

(e) Bei der Implementierung müssen Sie weiterhin folgende Vorgaben erfüllen: Seien a und b
zwei Objekte vom Typ Fussballer bzw. Torwart oder Feldspieler. Es gibt verschie-
dene Fälle:

(1) a und b sind beide vom Typ Torwart:


Hat a in den Spielen, in denen er eingesetzt wurde, im Durchschnitt2 mehr Bälle
gehalten als Spieler b im Durschnitt in den Spielen gehalten hat, in denen letzterer
eingesetzt wurde, so ist a größer als b. Ist stattdessen dieser Durchschnittswert für
b größer als für a, so ist a kleiner als b. Falls beide Werte gleich sind, so ist der
2
Mit Durchschnitt ist hier der Durchschnitt als int-Variable unter Verwendung der Abrundungsfunktion
gemeint. Für das Array [1,2,4,8] beträgt der mathematisch korrekte Durchschnitt 3, 75, welcher hier also auf 3
abgerundet werden soll.

6
Spieler größer, der in mehr Spielen eingesetzt wurde, falls es einen solchen gibt. Gibt
es solch einen Spieler nicht, sind a und b gleich.
(2) a und b sind beide vom Typ Feldspieler:
Hat a in dem Spiel unter seinen Einsätzen, in dem er am meisten Tore erzielt hat,
mehr Tore gemacht als Spieler b in dem Spiel erzielt hat, in welchem dieser unter
seinen Einsätzen am meisten Tore erzielt hat, so ist a größer als b. Ist der entspre-
chende Wert für b größer als für a, so ist a kleiner als b. Sind beide Werte gleich,
so ist der Spieler größer, der über all die Spiele, in denen er eingesetzt wurde, ins-
gesamt weniger Fouls begangen hat, sollte es einen solchen geben. Sind auch diese
Werte gleich, so sind auch a und b gleich.
(3) a und b sind nicht beide vom Typ Torwart und nicht beide vom Typ Feldspieler:
Hat a ein höheres Gehalt als b, so ist a größer als b. Ist das Gehalt von b größer als
das von a, so ist a kleiner als b. In jedem anderen Fall sind a und b gleich.

Beispiele:

(1) Falls a und b jeweils Torwarte sind und gehalteneBaelle für a den Wert [0, 1,
2, 4] und für b den Wert [1,6,2] hat, so ist a kleiner als b (Durschnittsbedingung
in (1)).
(2) Seien a und b beide Feldspieler. tore habe für a den Wert [0,1,1,2,1,0,0] und
für b den Wert [0,0,2,2], fouls habe für a den Wert [2,3,0,1,1,0,0] und für
b den Wert [3,3,1, 0]. Dann haben a und b in dem Spiel, in dem sie am meisten
Tore erzielt haben, jeweils 2 Tore gemacht. Da a und b insgesamt auch gleich viele
Fouls begangen haben, sind a und b gleich (Bedingung (2)).
(3) Falls a weder vom Typ Feldspieler noch vom Typ Torwart ist, b vom Typ Feldspieler
ist und gehalt für a den Wert 2000 und für b den Wert 1000 hat, so ist a größer als
b (Bedingung (3)).

Hinweis(e):

(1) Erinnerung: Beachten Sie unbedingt die formalen Vorgaben aus Abschnitt 1, z.B.
auch in Bezug auf Konsolenausgaben oder Getter und Setter.
(2) Sie dürfen davon ausgehen, dass tore und fouls die gleiche Länge haben, alle
beschriebenen Arrays nicht-leer sind und nichtnegative Einträge haben.
(3) Es ist essentiell, dass bei den Klassen, bei denen das explizit verlangt wird, das
angegebene Interface auch tatsächlich von dieser Klasse implementiert wird: Die
Implementation muss also explizit in der Deklaration der Klasse angegeben werden,
sonst führt das zu hohem Punkteverlust.

7
2.3 Aufgabe 3 - Arraylists und Strings - 80 Punkte
Im Repo finden Sie das Package permutations mit der Klasse PERMUTATIONS_main.java,
welche auch die main-Methode enthält. In dieser Aufgabe ist jede ArrayList eine ArrayList
mit String-Objekten.
Ziel der Aufgabe ist es, Permutationen von Tupelschreibweise in Zykelschreibweise umzuwan-
deln und diese anschließend auf Strings anzuwenden. Eine Permutation auf einen String anzu-
wenden bedeutet, die einzelnen Characters im String zu vertauschen. Einfachheitshalber be-
schränken wir uns auf Permutationen von Strings der Länge kleiner oder gleich 10. Bevor wir
zur Aufgabenstellung kommen, beschreiben wir kurz, wie die verschiedenen Schreibweisen zu
verstehen sind:

Tupelschreibweise: Im Folgenden interpretieren wir ein int-Array pArray als Permutati-


on in Tupelschreibweise. Dabei entsprechen die Einträge in pArray genau den Werten
beginnend bei 0 bis zur Länge von pArray (exklusive), in beliebiger Reihenfolge.
Wenden wir die Permutation auf einen String s an, durchlaufen wir das Array und ver-
tauschen die einzelnen Characters des Strings wie folgt: Steht in der Zelle mit Index i in
pArray der Wert j, dann wird der i-te Character im ursprünglichen String s an die Zelle
mit Index j verschoben.
Beispiel:

• Sei pArray = [0,1,2,3,4,5], s = "abcdef". Dann ist der permutierte String


"abcdef".
• Sei pArray =[2,3,0,5,4,1], s = "abcdef". Dann ist der permutierte String "cfabed".

Zykelschreibweise: Wir interpretieren eine ArrayList pCycles mit String-Objekten, deren


Characters int-Variablen entsprechen, als Permutation in Zykelschreibweise.
Wenden wir die Permutation auf einen String s an, durchlaufen wir die Arraylist pCycles
und wenden jeden Zykel c (d.h. jeden String in der Arraylist) folgendermaßen auf den
ursprünglichen String s an: Sei c der Form "k1 k2 . . . kn ", mit ki ∈ {0, . . . , 9}. Dann
wenden wir c auf den String s an, indem jeweils der Character in der Zelle mit Index ki
in die Zelle mit Index ki+1 verschoben wird und der Character in der Zelle mit Index kn
in die Zelle mit Index k0 verschoben wird.
Beispiel:

• Sei pCycles = {”0”, ”1”, ”2”, ”3”, ”4”, ”5”}, s = "abcdef". Dann ist der permutierte
String "abcdef".
• Sei pCycles = {”051”, ”2”, ”34”}, s = "abcdef". Hier kann der erste Zykel gelesen
werden als "Der Character an Position 0 in s wird zu Position 5 verschoben, der
Character an Position 5 in s wird zu Position 1 und der Character an Position 1 in s

8
zu Position 0 verschoben.". Anwenden des ersten Zykels ergibt den String "bfcdea".
Anwenden des zweiten Zykels verändert den String nicht und Anwenden des dritten
Zykels ergibt den String "bfceda", was dem Ergebnis entspricht.

(a) Erstellen Sie eine Klasse namens Permutation. Als Attribut erhält Permutation ein
ArrayList-Objekt pCycles, welches Objekte vom Typ String speichert.

(b) Erstellen Sie den Konstruktor Permutation(int[] pArray). Durch Aufruf des Kon-
struktors wird die Variable pCycles gesetzt. Dazu wird die Permutation, welche in pArray
in Tupelschreibweise gespeichert ist, in Zykelschreibweise umgewandelt und anschließend
im Attribut pCycles gespeichert. Das bedeutet, Sie dürfen davon ausgehen, dass die
Einträge von pArray genau die Werte beginnend bei 0 und bis exklusive der Länge von
pArray in beliebiger Reihenfolge enthält.
Beispiel:

• Sei pArray =[0,1,2,3,4,5], dann ist pCycles ={"0","1","2","3","4","5"}.


• Sei pArray =[2,3,0,5,4,1], dann ist pCycles ={"02","135","4"}.

Damit die Ausgabe eindeutig ist, soll pCycles zusätzlich nach dem ersten im jeweiligen
String vorkommenden Character sortiert sein. Da hier jeder Character nur einmal in allen
Strings vorkommen kann, erhalten wir so eine eindeutige Sortierung. Außerdem sollen die
in pCycles gespeicherten Strings so angeordnet sein, dass der erste Character im String
dem kleinsten vorkommenden Integer entspricht. Insbesondere folgt damit, dass der erste
Character des ersten Strings in pCycles immer ’0’ ist.
Beispiel:

• Sei pArray =[0,1,2,3,4,5], dann ist pCycles ={"0","1","3","2","4","5"} kei-


ne korrekte Ausgabe. Korrekt wäre {"0","1","2","3","4","5"}.
• Sei pArray = [2,3,0,5,4,1], dann ist pCycles = {"02","4","135"} keine kor-
rekte Ausgabe. Genauso ist pCycles ={"02","513","4"} keine korrekte Ausgabe.
Korrekt wäre {"02","135","4"}.

(c) Implementieren Sie in der Klasse Permutation die Methode permuteString(String s)


mit Rückgabetyp String. Sei n die Summe der Längen der Strings in pCycles. Passen Sie
zunächst die Länge des Strings s an: Falls s länger als n ist, wird s abgeschnitten, sodass
der String Länge n hat. Ist s kürzer als n, so werden so viele 0en an s hinten angehängt,
dass der String die Länge n hat. Anschließend soll die Permutation, welche durch pCycles
in Zyklenschreibweise gegeben ist, auf s angewendet werden und der permutierte String
zurückgegeben werden.
Hinweis: Es soll s permutiert zurück gegeben werden, kein neuer String.

9
(d) Überschreiben Sie in der Klasse Permutation die toString() Methode. Sei pCycles ge-
geben durch {c1 , c2 , . . . , cn }, dann ist der zurückgegebene String der Form "(c1 )(c2 ) . . . (cn )"
(ohne Leerzeichen).
Beispiel:

• Sei pCycles ={"0","1","2","3","4","5"}, dann gibt die Methode toString()


den String "(0)(1)(2)(3)(4)(5)" zurück.
• Sei pCycles ={"051","2","34"}, dann gibt die Methode toString() den String
"(051)(2)(34)" zurück.

Hinweis(e):

(1) Erinnerung: Beachten Sie unbedingt die formalen Vorgaben aus Abschnitt 1, z.B. auch
in Bezug auf Konsolenausgaben oder Getter und Setter.

(2) Sie dürfen davon ausgehen, dass pArray stets genau die Werte beginnend bei 0 bis ex-
klusive der Länge von pArray in beliebiger Reihenfolge enthält.

(3) Sie dürfen davon ausgehen, dass die Menge der Characters, die in den Strings in pCycles
gespeichert sind, stets genau den int-Werten 0, . . . , n mit n < 10 entsprechen.

(4) Das String-Array pCycles enthält Strings. In den Beispielen haben wir dies mit Anfüh-
rungszeichen oben links und oben rechts (") verdeutlicht. Gespeichert ist aber jeweils
natürlich nur die Zeichenkette, die zwischen den Anführungszeichen enthalten ist.

10
2.4 Aufgabe 4 - Graphische Benutzeroberfläche - 140 Punkte
Im Repo finden Sie ein Package namens gui. Die Klasse GUI_main.java enthält die main-
Methode und darf nicht verändert werden. Im Gegensatz zu den vorherigen Aufgaben
werden wir also hier explizit die main-Methode zum Prüfen Ihrer Lösung aufrufen.
Ziel dieser Aufgabe ist es, eine erste grafische Benutzeroberfläche zu erstellen. Sie werden unter
anderem mit dem Bild Siegel (siegel.jpg) arbeiten, welches im Repo im Ordner resources
zu finden ist. Ein Beispiel, wie das beschriebene Fenster aussehen könnte, finden Sie in den
Abbildungen auf Seite 14.

(1) Erstellen Sie die Klasse MyFrame, welche von JFrame erbt. Das damit erzeugte Fenster
muss 600 × 600 (Breite mal Höhe) Pixel groß sein und in der Mitte des Bildschirms
angezeigt werden. Die Größe des Fensters muss anschließend erkennbar verstellbar sein,
jedoch eingeschränkt durch eine sinnvolle minimale Größe (die einzelnen Komponenten
sollten fehlerfrei und vollständig angezeigt werden). Sorgen Sie außerdem dafür, dass das
Programm endet, sobald man das Fenster schließt.

(2) Der Inhalt von MyFrame wird in zwei verschiedene Bereiche aufgeteilt: Am oberen Rand
befindet sich die Menütafel, welche ein Achtel der Höhe des Fensters einnimmt. Darunter
befindet sich die Anzeigetafel, welche den restlichen Platz im Fenster einnimmt.

(3) Die Menütafel enthält auf der linken Seite einen Button, welcher genau so hoch ist wie die
Menütafel, aber nur ein Viertel so breit. Dieser Button ist zu Beginn mit Start beschriftet.
Zusätzlich enthält die Menütafel auf der rechten Seite zwei übereinanderliegende radio
buttons, wobei der obere mit None und der untere mit 2 seconds beschriftet ist. Weiter
gilt, dass zu jeder Zeit immer genau einer der beiden radio buttons ausgewählt ist. Zu
Beginn ist standardmäßig der obere Button aktiviert. Über den radio buttons befindet
sich die Überschrift Delay. Zwischen dem Button auf der linken Seite der Menütafel und
den radio buttons (inkl. Überschrift) auf der rechten Seite soll ein Abstand von der Hälfte
der Fensterbreite bestehen.

(4) Die Anzeigetafel hat als Hintergrundfarbe gelb. Zu einem späterem Zeitpunkt wird auf
dieser Anzeigetafel das Siegel (s.o.) in Größe 150 × 150 Pixel gemalt werden. Mit malen
meinen wir (auch in zukünftigen Aufgaben) in der Tat Methoden, die das Wort paint
enthalten, wie zum Beispiel paint bzw. repaint oder auch paintComponent.

(5) Eine für das Siegel zulässige Stelle ist eine Stelle auf der Anzeigetafel, so dass das Siegel
vollkommen zu sehen ist. Es darf also zu keiner Zeit ganz oder teilweise über den Rand der
Anzeigetafel hinausragen. Beachten Sie, dass das Siegel erst nach dem ersten Betätigen
des Buttons auf der Anzeigetafel zu sehen ist.

(6) Versehen Sie den Button aus der Menütafel mit den folgenden Eigenschaften:

11
(a) Der Button kann zwei Zustände annehmen: den Start- und den Stop-Zustand. Befin-
det er sich im Start-Zustand, so ist er mit Start beschriftet, befindet er sich im Stop-
Zustand, so ist er mit Stop beschriftet. Initial, also bei Aufruf des Programms und
damit beim ersten Öffnen des Fensters, befindet sich der Button im Start-Zustand.
(b) Wird der Button im Start-Zustand betätigt, dann geht er in den Stop-Zustand über.
Wird er im Stop-Zustand betätigt, dann geht er in den Start-Zustand über. Der
Button kann beliebig oft und zu jeder Zeit betätigt werden.
(c) Ist der Button im Start-Zustand, dann sind die radio buttons aktiv, so dass sie
verstellt werden können. Ist der Button im Stop-Zustand, dann sind die radio buttons
ausgegraut, sodass diese nicht mehr verstellt werden können. Die im Start-Zustand
getroffene Wahl bleibt erhalten und erkennbar.
(d) Wechselt der Button vom Start-Zustand in den Stop-Zustand, indem er betätigt
wird, erscheint an einer zufälligen und zulässigen Stelle auf der Anzeigetafel das
Siegel. Wechselt der Button vom Stop-Zustand in den Start-Zustand, hat das keine
Auswirkung auf die Position des Siegels.
(e) Ist der oben beschriebene Button im Stop-Zustand und es wird direkt auf das Siegel
auf der Anzeigetafel geklickt, dann verschwindet dieses und taucht in Abhängigkeit
des angewählten radio buttons entweder sofort wieder auf (der radio button mit
Beschriftung None ist ausgewählt) oder nach einer Verzögerung von 2 Sekunden
(der radio button mit Beschriftung 2 seconds ist ausgewählt). In beiden Fällen wird
das Siegel beim Erscheinen an einer neuen zufälligen und zulässigen Stelle gemalt.
Dieser Vorgang muss beliebig oft wiederholt werden können.
(f) Ist der Button im Start-Zustand und wird das Siegel angezeigt (war der Button
also zuvor im Stop-Zustand), ändert das Klicken auf das Siegel nichts am aktuellen
Zustand des Programms.

(7) Implementieren Sie Ihre Benutzeroberfläche responsiv. Das bedeutet zum Beispiel, dass
das Siegel, wenn es sich in der Mitte der Anzeigetafel befindet, auch weiterhin in der
(relativen) Mitte der Anzeigetafel zu finden ist, auch, wenn sich die Fenstergröße verän-
dert. In anderen Worten: Sie sollen die Position von einzelnen Elementen nicht hart in
den Code einprogrammieren (sollten Sie ohnehin nicht...), sondern beispielsweise einen
LayoutManager für das entsprechende Panel verwenden. Beachten Sie, dass sich die Grö-
ße des Siegels selbst nicht verändern muss - nur seine relative Position im Verhältnis zu
den anderen Elementen des Fensters. Sorgen Sie weiterhin dafür, dass die Beschriftungen
stets lesbar und vollständig sind.

(8) Wird die main-Methode ausgeführt, wird das Fenster vollständig angezeigt.

12
Hinweis(e):

(1) Ausgaben auf die Konsole (zwecks Selbstkontrolle): Sind in dieser Aufgabe erlaubt,
werden von uns nicht bewertet oder berücksichtigt. Wir bewerten Ihre Benutzeroberfläche
bzw. Ihren Code.

(2) Wir empfehlen dringend, LayoutManager (auch) für das gesamte Frame zu verwenden.
Wir empfehlen weiterhin, die Elemente des Fensters in Panel, die ggf. von JPanel erben,
aufzuteilen. Am Sinnvollsten erscheint uns eine Lösung mit zwei bis vier Panels, je nach
Geschmack und Gliederung Ihres Programms.

(3) Implementieren Sie das Siegel nicht als Button. Es muss mit paint oder paintComponent
gemalt werden.

(4) Wir stellen es Ihnen frei, was passiert, wenn der Button betätigt wird, während das Siegel
gerade für 2 Sekunden nicht angezeigt wird. Tatsächlich werden wir bei der Bewertung
gar nicht überprüfen und somit nicht bewerten, was in genau diesem Fall dann passiert.

(5) Bewertung der GUI-Aufgabe: Wir korrigieren die GUI-Aufgabe händisch (weshalb die
Ergebnisse zu dieser Aufgabe auch erst später veröffentlicht werden können). Die Unter-
punkte der Aufgabe dürfen Sie hierbei nicht als eigene Teilaufgaben sehen, die einzeln
bepunktet werden. Vielmehr wird Ihre Lösung als Ganzes in Hinblick auf die gestellten
Anforderungen geprüft und bewertet. Gezieltes Auslassen einzelner Anforderungen kann
daher zu einem hohen Punkteverlust führen.

13
Abbildung 1: GUI - Beispiel für Windows

Abbildung 2: GUI - Beispiel für MacOS

14

Das könnte Ihnen auch gefallen