10. Übungsblatt - Technische Universität Braunschweig

Technische Universität Braunschweig
Institut für Programmierung und Reaktive Systeme
Dr. Werner Struckmann
8. Mai 2015
Programmieren II
10. Übungsblatt
Hinweis: Auf diesem und den folgenden Übungsblättern finden Sie jeweils eine Pflichtaufgabe. Insgesamt werden in diesem Semester fünf Pflichtaufgaben gestellt. Ihre Lösung
der Pflichtaufgabe dieses Übungsblatts müssen Sie bis spätestens zum 17. Mai 2015 auf
der Web-Seite
http://ips.rz.tu-bs.de/programmieren-abgabe
abgeben. Beachten Sie, dass Sie Ihre Lösung auch Ihrem Tutor erläutern müssen.
Halten Sie sich bei der Programmierung an die in der Vorlesung vorgestellten Richtlinien zur Formatierung von Java-Programmen. Auf der Internetseite zu dieser Veranstaltung finden Sie eine Zusammenstellung dieser Richtlinien. Kommentieren Sie Ihre Lösung
der Pflichtaufgabe. Der Kommentar muss Ihren Namen, Ihre Matrikelnummer und Ihre Übungsgruppe sowie eine Beschreibung Ihrer Lösung enthalten. Auf der Abgabeseite
finden Sie eine Möglichkeit, die Formatierung Ihrer Lösung zu checken.
Aufgabe 54: (Wiederholung: Rekursion) Die durch die Ausdrücke
f (0) = 0, f (1) = 1, f (2n) = f (n), f (2n + 1) = f (n) + f (n + 1)
für n ∈ N rekursiv definierte Funktion f : N → N heißt
Verkannte Schwester der Fibonacci-Folge.
Die Tabelle
1
1
1
1
1
1
2
3
4
5
6
2
3
4
5
3
5
7
9
2 5
3 8
4 11
3 4
5 7
7 10
2 7
3 11
5 8
8 13
3 7
5 12
4
7
5
9
....
enthält die Funktionswerte f (1) = 1, f (2) = 1, f (3) = 2, ... , f (47) = 9. Die Summen
der Zeilen sind 30 = 1, 31 = 3, 32 = 9, 33 = 27, 34 = 81, . . .. Außerdem sind die Spalten
arithmetische Folgen, d. h., die Differenzen zwischen zwei Werten in einer Spalte sind stets
gleich. Schreiben Sie ein Programm, dass die Anfänger der ersten Spalten zeilenmäßig
ausgibt. Ihre Ausgabe könnte also wie folgt aussehen:
1
2
2
3
2
1
3
3
5
3
1
4
4
7
4
1 1 1 1 1 1
5 6 7 8 9 10
5 6 7 8 9 10
9 11 13 15 17 19
5 6 7 8 9 10
1
11
11
21
11
1
12
12
23
12
1
13
13
25
13
1
14
14
27
14
1
15
15
29
15
1
16
16
31
16
1
17
17
33
17
....
....
....
....
....
Diese Folge wurde von Moritz Stern und Achille Brocot definiert.
Aufgabe 55: Als einführendes Beispiel in die Programmierung dynamischer Datentypen
wurde in der Vorlesung die Schnittstelle
interface List {
boolean isEmpty();
boolean isInList(Element x);
Element firstElement();
int length();
List insert(Element x);
List append(Element x);
List delete(Element x);
List delete();
}
durch verkettete Listen implementiert. Der Implementierung lag die folgende Strukturinvariante zu Grunde:
L:
x1
x2
...
xn
Das erste Element L der Liste ist ein „Zeiger“ auf die Liste, d. h., das erste Item-Feld
wird nicht genutzt. Der letzte Zeiger ist „null“. Die Schnittstelle List wird jetzt um die
folgenden Methoden erweitert:
interface List {
...
List add(Element x, int n);
List remove(int n);
Element get(int n);
int firstIndexOf(Element x);
int lastIndexOf(Element x);
}
Die Methode add(Element x, int n) soll das Element x an Position n in die aktuelle
Liste einfügen. Die Methode remove(int n) soll das Element an Position n der aktuellen
Liste löschen. Die Methode get(int n) soll das Element an Position n der aktuellen Liste
liefern. Die Methoden firstIndexOf(Element x) und lastIndexOf(Element x) sollen
den ersten bzw. letzten Index des Elements x der aktuellen Liste liefern. Vergleichen Sie
hierbei Elemente durch die Methode equals.
–2–
Implementieren Sie die erweiterte Schnittstelle List durch eine verkettete Liste. Die
Strukturinvariante Ihrer Implementierung soll analog zur obigen Strukturinvariante sein,
aber das erste Item-Feld nutzen. Achten Sie darauf, dass beim Aufruf jeder Methode die
Strukturinvariante erhalten bleibt.
Es sind fehlerhafte Aufrufe möglich. Die Methode add(Element x, int n) könnte
beispielsweise mit dem Wert 10 für den Parameter n aufgerufen werden, obwohl die Liste
nur 2 Elemente enthält. In diesen Fällen soll eine IllegalArgumentException ausgelöst
werden.
Kommentieren Sie Ihre Lösung und erzeugen Sie die Dokumentation mit dem Programm javadoc.
Aufgabe 56:
In der Vorlesung wurde die Schnittstelle
interface List {
boolean isEmpty();
boolean isInList(Element x);
Element firstElement();
int length();
List insert(Element x);
List append(Element x);
List delete(Element x);
List delete();
}
durch verkettete Listen und durch Felder implementiert. Diese Schnittstelle wird jetzt um
die folgenden Methoden erweitert:
interface List {
...
List insert(Element x, int n);
List swap(int m, int n);
List deleteAll(Element x);
List deleteLast();
Element maximum();
}
Die Methode insert(Element x, int n) soll das Element x an Position n in die aktuelle Liste einfügen. Die Methode swap(int m, int n) soll das m-te mit dem n-ten
Element der aktuellen Liste durch Änderung der Verkettung vertauschen. Die Methode
deleteAll(Element x) soll alle Elemente der aktuellen Liste entfernen, die den gleichen
Inhalt wie der Parameter x besitzen. Die Methode deleteLast() soll das letzte Element
der aktuellen Liste löschen. Die Methode maximum() soll das größte Element der aktuellen
Liste liefern.
–3–
Implementieren Sie die erweiterte Schnittstelle List. Verwenden Sie dabei statt einer
einzelnen Klasse LinkedList die beiden folgenden Klassen Node und LinkedList:
public class LinkedList implements List {
protected Node node;
...
}
public class Node {
protected Element item;
protected LinkedList next;
...
}
Lösen Sie die Aufgabe, indem Sie sich zuerst die Strukturinvariante der Implementierung
klar machen.
Testen Sie Ihr Programm mit Beispielen der Klasse Element. Vervollständigen Sie dazu
die Methoden equals, compareTo und toString:
public class Element implements Comparable<Element> {
private int i;
public Element(int i) { this.i = i; }
public boolean equals(Object x) { ... }
public int compareTo(Element e) { ... }
public String toString() { ... }
}
Aufgabe 57:
Arrays.
Implementieren Sie die erweiterte Schnittstelle List aus Aufgabe 56 durch
Informationen zu den Pflichtaufgaben im Sommersemester 2015
Die Abgaben der Programme erfolgt über das alte Abgabetool unter der Adresse
http://ips.rz.tu-bs.de/programmieren-abgabe.
Falls Sie hierfür noch kein Benutzerkonto besitzen, so erstellen Sie sich bitte eins und
tragen Sie sich in ihre Übungsgruppe ein. Falls sich Ihre Übungsgruppennummer geändert
hat, so ändern Sie diese bitte im Abgabetool.
Vergewissern Sie sich im Stud.IP, dass Sie Ihre Zusatzangaben mit Studiengang usw.
vollständig und korrekt ausgefüllt haben. Sollten Sie bis zum Ende des Semesters diese nicht
ausfüllen, kann im Falle des Bestehens der Studienleistung dies nicht an das zuständige
Prüfungsamt übermittelt werden.
Das Bewertungssystem für die Hausaufgaben hat sich in diesem Semester geändert. Für
Hausaufgaben sind folgende Benotungen möglich: +1, 0, -1 und keine Punkte. Zum bestehen der Studienleistung muss die Summe der Punkte am Ende des Semesters positiv sein
und 5 Benotungen aufweisen. Am Ende des Semesters wird es eine Zusatzaufgabe als Joker
geben. Es kann maximal ein Eintrag mit keine Punkte durch bestehen der Joker-Aufgabe
–4–
ausgeglichen werden. Desweiteren ist es mit der Joker-Aufgabe möglich, das schlechteste Ergebnis in eine +1 umzuwandeln. Jedoch kann mit der Joker-Aufgabe entweder das
schlechteste Ergebnis oder keine Punkte ausgeglichen werden, aber nicht beides gleichzeitig.
Sollten Sie einmal aus triftigen Gründen nicht in der Lage sein ihre Programme abzugeben
oder vorzustellen, setzten Sie sich bitte rechtzeitig mit ihrem Tutor in Verbindung.
Für das WiSe 15/16 ist der Einsatz einen neuen, auf Stud.IP basierenden Abgabesystems geplant. Sollten Sie Interesse haben an einem internen Beta-Test teilzunehmen,
können Sie sich auf
http://studip25.bognari.me/
ein Benutzerkonto erstellen. Sollten Sie keine Bestätigungsmail erhalten, wenden Sie sich
bitte an Stephan Mielke <[email protected]>. In der Veranstaltung Programmieren II
ist das Abgabetool Leeroy aktiviert, über welches Sie testweise ihre Programme abgeben
können. Bitte Beachten Sie, dass die trotzdem über das alte Tool ihre Programme abgeben.
Pflichtaufgabe 58: (Listen) In dieser und den folgenden Hausaufgaben sollen Sie nach
und nach ein bestehendes textbasiertes Rollenspiel erweitern. Die Grundlage für das Rollenspiel entnehmen Sie bitte dem bereitgestellten Archiv. Alternativ können Sie nach Rücksprache mit Ihrem Tutor auch ihre Lösungen aus Programmieren I verwenden.
In dieser Aufgabe sollen Sie ein Inventar auf Basis der in der Vorlesung vorgestellten
LinkedList programmieren. Hierfür wird Ihnen ein List Interface zur Verfügung gestellt.
a) Item: Für ein funktionierendes Inventar werden zu aller erst „Dinge“ benötigt. Hierfür sollen Sie die Klasse Item erstellen, welche als Attribute einen Namen, ein Gewicht
und einen Verkaufswert besitzt. Für ein Item soll es mindestens die zwei Konstruktoren, Item() und Item(String name, int value, int weight) geben. Der StandardKonstruktor soll hierbei ein Item mit einem zufälligen Namen, Gewicht und Wert
erzeugen. Überlegen Sie sich geeignete Überladungen für die equals(Object obj) und
toString() Methoden.
Beachten Sie bei der Implementierung das in der Vorlesung1 vorgestellte Prinzip der
Kapselung.
b) Comparable: Damit das Inventar nicht aus einem unsortierten Haufen von Items
besteht, müssten Items nach ihrem Namen sortierbar sein. Zu diesem Zweck soll
die Klasse Item das Comparable Interface implementieren und eine geeignete Implementierung der compareTo(Object o) Methode bereitstellen. Sollten zwei Items den
gleichen Namen besitzen, so entscheidet absteigend zuerst der Wert und dann das
Gewicht über die Reihenfolge.
Beachten Sie, dass die compareTo(Object o) auch Objekte entgegen nehmen kann,
die nicht vom Typ Item sind. Das Interface Comparable ist nicht mit dem Interface
Comparable<T> zu verwechseln.
1
Programmieren I, Folie 4-8
–5–
c) Liste: Schreiben Sie die Klasse Inventar welche das vorgegebene Interface List implementiert. Überlegen Sie sich für das Inventar zuerst eine geeignete Strukturinvariante2 und fangen Sie erst dann mit der Implementierung an. Die Erläuterungen zu
den einzelnen Methoden entnehmen Sie bitte direkt den Javadoc Kommentaren des
Interfaces.
Auch wenn nicht alle Methoden des Interfaces für die weiteren Teilaufgaben dieses
Blattes benötigt werden, müssen Sie diese trotzdem implementieren und auf Funktionalität testen, da diese in nachfolgenden Aufgabenblättern verwendet werden.
Sie dürfen für diese Aufgabe keine Klassen oder Methoden des JCF (Java Collections
Framework) verwenden. Desweiteren dürfen Sie das vorgegebene List Interface nicht
verändern.
d) Spielerweiterung: Nach dem Implementieren des Inventars und der dazugehörigen
Items. Sollen diese in das bestehende Spiel integriert werden. Erweitern Sie hierzu
die bestehenden Klassen des Spiels so, dass der Spieler mit einem leeren Inventar
und einem Gold Betrag von 0 startet. Die Monster hingegen sollen mit einem zufällig gefülltem Inventar sowie einem zufälligen positiven Gold Betrag starten. Beide Klassen sollen die Methoden List getInventar() und int getGold() als einfache
Getter-Methoden bereitstellen.
Erweitern Sie ihr Kampfsystem so, das beim Besiegen eines Monsters die Beute also
dessen Inventar und Gold Betrag dem Spieler gutgeschrieben wird.
Momentan können Sie zwischen den Zügen auf der Karte nur die Richtung angeben,
in welche sich der Spieler bewegen soll. Erweitern Sie die Abfrage nach der nächsten
Aktion bzw. Richtung so, das statt der Eingabe einer Richtung auch ein Befehl
für das Darstellen des Inventars akzeptiert und ausgeführt wird. Die Darstellung
des Inventars soll die Position des jeweiligen Items im Inventar und die einzelnen
Attribute beinhalten.
2
Programmieren II, Folie 9-9
–6–