Commit 15e8ec91 authored by Christopher Schölzel's avatar Christopher Schölzel 🐃
Browse files

adds two exercises for inheritance and one for enums

parent 0502ca9a
......@@ -73,3 +73,148 @@ include::{sourcedir}\Medium.java[]
----
include::postDetails.adoc[]
== Typen im Sammelkartenspiel
Sie wollen ein Sammelkartenspiel wie https://playhearthstone.com/de-de/[Heartstone] oder https://www.playgwent.com/en[Gwent] implementieren.
Für Ihr Spiel haben Sie die folgenden Designentscheidungen getroffen:
* Alle Karten haben eine Seltenheit (`COMMON`, `RARE` oder `LEGENDARY`) und einen Namen.
* Es gibt Zauberkarten und Einheitenkarten.
* Einheitenkarten haben zusätzlich eine Stärke zwischen 1 und 100.
* Zauberkarten unterscheiden sich zusätzlich dadurch, ob sie auf freundliche Einheiten, feindliche Einheiten, keine (für globale Effekte) oder beide angewendet werden können.
Erstellen Sie die Klassen `SpellCard` und `UnitCard` für Zauber- und Einheitenkarten, sowie eine gemeinsame Oberklasse `Card`, so dass alle oben genannten Eigenschaften mit geeigneten Datentypen abgebildet werden.
include::preDetailsSolution.adoc[]
----
enum Rarity { COMMON, RARE, LEGENDARY }
abstract class Card {
private String name;
private Rarity rarity;
public Card(String name, Rarity rarity) {
this.name = name;
this.rarity = rarity;
}
public String getName() { return name; }
public Rarity getRarity() { return rarity; }
}
class UnitCard extends Card {
private int strength;
public UnitCard(String name, Rarity rarity, int strength) {
super(name, rarity);
this.strength = strength;
}
public int getStrength() {
return strength;
}
}
class SpellCard extends Card {
private boolean targetsEnemies;
private boolean targetsFriends;
public SpellCard(String name, Rarity rarity, boolean targetsEnemies, boolean targetsFriends) {
super(name, rarity);
this.targetsEnemies = targetsEnemies;
this.targetsFriends = targetsFriends;
}
public boolean targetsFriends() {
return targetsFriends;
return targetsEnemies;
}
}
----
include::postDetails.adoc[]
== SVG Generator
Das https://en.wikipedia.org/wiki/Scalable_Vector_Graphics[Scalable Vector Graphics]-Format beschreibt Vektorgrafiken als XML-basierte Textdatei, wie in dem folgenden Beispiel:
----
<svg width="120" height="120" viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg">
<circle cx="60" cy="60" r="50.5" style="fill:yellow"/>
<line x1="20" y1="100" x2="100" y2="20" style="stroke-width: 2; stroke:black"/>
</svg>
----
Schreiben Sie die Klassen `SVGDocument`, `SVGLine` und `SVGCircle`, so dass das oben gezeigte Dokument (bzw. ein äquivalentes Dokument) mit dem folgenden Code erzeugt werden kann.
Implementieren Sie dazu auch eine gemeinsame Überklasse für `SVGLine` und `SVGCircle` mit dem Namen `SVGElement`.
----
SVGDocument doc = new SVGDocument(120, 120,
new SVGCircle(60,60,50.5f, "fill:yellow"),
new SVGLine(20,100,100,20, "stroke-width: 2; stroke:black")
);
System.out.println(doc);
----
include::preDetailsSolution.adoc[]
----
class SVGDocument {
private float w,h;
private SVGElement[] content;
public SVGDocument(float w, float h, SVGElement ... content) {
this.w = w;
this.h = h;
this.content = content;
}
public String toString() {
String msg = "<svg width=\"%1$.2f\" height=\"%2$.2f\" viewBox=\"0 0 %1$.2f %2$.2f\" "
+ "xmlns=\"http://www.w3.org/2000/svg\">\n%3$s\n</svg>";
String contentString = Arrays.stream(content)
.map(x -> x.toString()).collect(Collectors.joining("\n"));
return String.format(Locale.US, msg, w, h, contentString); // <1>
}
}
abstract class SVGElement {
private String name;
private String style;
public SVGElement(String name, String style) {
this.name = name;
this.style = style;
}
public String toString() {
String attr = additionalAttributes();
return String.format("<%1$s %3$s style=\"%2$s\"/>", name, style, attr);
}
protected abstract String additionalAttributes();
}
class SVGLine extends SVGElement {
private float x1,y1,x2,y2;
public SVGLine(float x1, float y1, float x2, float y2, String style) {
super("line", style);
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
@Override
protected String additionalAttributes() {
String tmpl = "x1=\"%.2f\" y1=\"%.2f\" x2=\"%.2f\" y2=\"%.2f\"";
return String.format(Locale.US, tmpl, x1, y1, x2, y2); // <1>
}
}
class SVGCircle extends SVGElement {
private float cx,cy,r;
public SVGCircle(float cx, float cy, float r, String style) {
super("circle", style);
this.cx = cx;
this.cy = cy;
this.r = r;
}
@Override
protected String additionalAttributes() {
String tmpl = "cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\"";
return String.format(Locale.US, tmpl, cx, cy, r); // <1>
}
}
----
<1> Die `Locale` ist hier wichtig, da das SVG-Format vorschreibt, dass Fließkommazahlen in englischer Schreibweise (mit "." statt ",") formatiert werden müssen.
include::postDetails.adoc[]
......@@ -567,6 +567,8 @@ table.CodeRay td.code>pre{padding:0}
<ul class="sectlevel1">
<li><a href="#_equals">Equals</a></li>
<li><a href="#_mediaplayer">Mediaplayer</a></li>
<li><a href="#_typen_im_sammelkartenspiel">Typen im Sammelkartenspiel</a></li>
<li><a href="#_svg_generator">SVG Generator</a></li>
</ul>
</div>
</div>
......@@ -816,10 +818,188 @@ false</pre>
</details>
</div>
</div>
<div class="sect1">
<h2 id="_typen_im_sammelkartenspiel">Typen im Sammelkartenspiel</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Sie wollen ein Sammelkartenspiel wie <a href="https://playhearthstone.com/de-de/">Heartstone</a> oder <a href="https://www.playgwent.com/en">Gwent</a> implementieren.
Für Ihr Spiel haben Sie die folgenden Designentscheidungen getroffen:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Alle Karten haben eine Seltenheit (<code>COMMON</code>, <code>RARE</code> oder <code>LEGENDARY</code>) und einen Namen.</p>
</li>
<li>
<p>Es gibt Zauberkarten und Einheitenkarten.</p>
</li>
<li>
<p>Einheitenkarten haben zusätzlich eine Stärke zwischen 1 und 100.</p>
</li>
<li>
<p>Zauberkarten unterscheiden sich zusätzlich dadurch, ob sie auf freundliche Einheiten, feindliche Einheiten, keine (für globale Effekte) oder beide angewendet werden können.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Erstellen Sie die Klassen <code>SpellCard</code> und <code>UnitCard</code> für Zauber- und Einheitenkarten, sowie eine gemeinsame Oberklasse <code>Card</code>, so dass alle oben genannten Eigenschaften mit geeigneten Datentypen abgebildet werden.</p>
</div>
<details>
<summary>Lösung</summary>
<div class="listingblock">
<div class="content">
<pre>enum Rarity { COMMON, RARE, LEGENDARY }
abstract class Card {
private String name;
private Rarity rarity;
public Card(String name, Rarity rarity) {
this.name = name;
this.rarity = rarity;
}
public String getName() { return name; }
public Rarity getRarity() { return rarity; }
}
class UnitCard extends Card {
private int strength;
public UnitCard(String name, Rarity rarity, int strength) {
super(name, rarity);
this.strength = strength;
}
public int getStrength() {
return strength;
}
}
class SpellCard extends Card {
private boolean targetsEnemies;
private boolean targetsFriends;
public SpellCard(String name, Rarity rarity, boolean targetsEnemies, boolean targetsFriends) {
super(name, rarity);
this.targetsEnemies = targetsEnemies;
this.targetsFriends = targetsFriends;
}
public boolean targetsFriends() {
return targetsFriends;
return targetsEnemies;
}
}</pre>
</div>
</div>
</details>
</div>
</div>
<div class="sect1">
<h2 id="_svg_generator">SVG Generator</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Das <a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics">Scalable Vector Graphics</a>-Format beschreibt Vektorgrafiken als XML-basierte Textdatei, wie in dem folgenden Beispiel:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>&lt;svg width="120" height="120" viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;circle cx="60" cy="60" r="50.5" style="fill:yellow"/&gt;
&lt;line x1="20" y1="100" x2="100" y2="20" style="stroke-width: 2; stroke:black"/&gt;
&lt;/svg&gt;</pre>
</div>
</div>
<div class="paragraph">
<p>Schreiben Sie die Klassen <code>SVGDocument</code>, <code>SVGLine</code> und <code>SVGCircle</code>, so dass das oben gezeigte Dokument (bzw. ein äquivalentes Dokument) mit dem folgenden Code erzeugt werden kann.
Implementieren Sie dazu auch eine gemeinsame Überklasse für <code>SVGLine</code> und <code>SVGCircle</code> mit dem Namen <code>SVGElement</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>SVGDocument doc = new SVGDocument(120, 120,
new SVGCircle(60,60,50.5f, "fill:yellow"),
new SVGLine(20,100,100,20, "stroke-width: 2; stroke:black")
);
System.out.println(doc);</pre>
</div>
</div>
<details>
<summary>Lösung</summary>
<div class="listingblock">
<div class="content">
<pre>class SVGDocument {
private float w,h;
private SVGElement[] content;
public SVGDocument(float w, float h, SVGElement ... content) {
this.w = w;
this.h = h;
this.content = content;
}
public String toString() {
String msg = "&lt;svg width=\"%1$.2f\" height=\"%2$.2f\" viewBox=\"0 0 %1$.2f %2$.2f\" "
+ "xmlns=\"http://www.w3.org/2000/svg\"&gt;\n%3$s\n&lt;/svg&gt;";
String contentString = Arrays.stream(content)
.map(x -&gt; x.toString()).collect(Collectors.joining("\n"));
return String.format(Locale.US, msg, w, h, contentString); <i class="conum" data-value="1"></i><b>(1)</b>
}
}
abstract class SVGElement {
private String name;
private String style;
public SVGElement(String name, String style) {
this.name = name;
this.style = style;
}
public String toString() {
String attr = additionalAttributes();
return String.format("&lt;%1$s %3$s style=\"%2$s\"/&gt;", name, style, attr);
}
protected abstract String additionalAttributes();
}
class SVGLine extends SVGElement {
private float x1,y1,x2,y2;
public SVGLine(float x1, float y1, float x2, float y2, String style) {
super("line", style);
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
@Override
protected String additionalAttributes() {
String tmpl = "x1=\"%.2f\" y1=\"%.2f\" x2=\"%.2f\" y2=\"%.2f\"";
return String.format(Locale.US, tmpl, x1, y1, x2, y2); <i class="conum" data-value="1"></i><b>(1)</b>
}
}
class SVGCircle extends SVGElement {
private float cx,cy,r;
public SVGCircle(float cx, float cy, float r, String style) {
super("circle", style);
this.cx = cx;
this.cy = cy;
this.r = r;
}
@Override
protected String additionalAttributes() {
String tmpl = "cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\"";
return String.format(Locale.US, tmpl, cx, cy, r); <i class="conum" data-value="1"></i><b>(1)</b>
}
}</pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Die <code>Locale</code> ist hier wichtig, da das SVG-Format vorschreibt, dass Fließkommazahlen in englischer Schreibweise (mit "." statt ",") formatiert werden müssen.</td>
</tr>
</table>
</div>
</details>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-11-10 14:43:57 Mitteleuropõische Zeit
Last updated 2017-11-14 18:04:58 Mitteleuropõische Zeit
</div>
</div>
</body>
......
......@@ -42,3 +42,44 @@ Ein Unterschied besteht jedoch darin, dass ein Objekt vom Typ `UserInt` prinzipi
Gerade für einen solchen Fall, in dem die Sicherheit des Codes relevant ist, wären also Enumerationstypen zu bevorzugen.
include::postDetails.adoc[]
== Organische Enums
Sie wollen ein Programm für eine Anwendung in der organischen Chemie schreiben. Um die chemischen Elemente möglichst platzsparend zu speichern entscheiden Sie sich, diese als `enum` zu implementieren.
Für ihre Anwendung reicht es, wenn sie die folgenden Elemente darstellen und Name, Symbol und Ordnungszahl auslesen können.
[options="header"]
|====================================
|Name | Symbol | Ordnungszahl
|Wasserstoff | H | 1
|Kohlenstoff | C | 6
|Stickstoff | N | 7
|Sauerstoff | O | 8
|Phosphor | P | 15
|Schwefel | S | 16
|====================================
Implementieren Sie den Datentyp `Element` als `enum`, so dass das Symbol als Bezeichner der Enum-Werte dient. Die natürliche Ordnung von `Element`-Objekten, soll durch die Ordnungszahl bestimmt sein.
(D.h. eine Sortierung z.B. mit `Arrays.sort` muss nach aufsteigender Ordnungszahl erfolgen.)
include::preDetailsSolution.adoc[]
----
public enum Element {
H("Wasserstoff", 1), C("Kohlenstoff", 6), N("Stickstoff", 7),
O("Sauerstoff", 8), P("Phosphor", 15), S("Schwefel", 16);
private final int ord;
private final String name;
Element(String name, int ord) {
this.ord = ord;
this.name = name;
}
public int getOrd() {
return ord;
}
public String getName() {
return name;
}
}
----
include::postDetails.adoc[]
......@@ -566,6 +566,7 @@ table.CodeRay td.code>pre{padding:0}
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_rechteverwaltung">Rechteverwaltung</a></li>
<li><a href="#_organische_enums">Organische Enums</a></li>
</ul>
</div>
</div>
......@@ -638,7 +639,6 @@ summary:after {
<details>
<summary>Lösung</summary>
<div class="listingblock">
<div class="title">Lösung</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="type">enum</span> AccessLevel {
GUEST, DEVELOPER, ADMIN;
......@@ -694,10 +694,94 @@ summary:after {
</details>
</div>
</div>
<div class="sect1">
<h2 id="_organische_enums">Organische Enums</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Sie wollen ein Programm für eine Anwendung in der organischen Chemie schreiben. Um die chemischen Elemente möglichst platzsparend zu speichern entscheiden Sie sich, diese als <code>enum</code> zu implementieren.</p>
</div>
<div class="paragraph">
<p>Für ihre Anwendung reicht es, wenn sie die folgenden Elemente darstellen und Name, Symbol und Ordnungszahl auslesen können.</p>
</div>
<table class="tableblock frame-all grid-all spread">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Symbol</th>
<th class="tableblock halign-left valign-top">Ordnungszahl</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Wasserstoff</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">H</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Kohlenstoff</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">C</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Stickstoff</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Sauerstoff</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">O</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Phosphor</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">P</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">15</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Schwefel</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">S</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Implementieren Sie den Datentyp <code>Element</code> als <code>enum</code>, so dass das Symbol als Bezeichner der Enum-Werte dient. Die natürliche Ordnung von <code>Element</code>-Objekten, soll durch die Ordnungszahl bestimmt sein.
(D.h. eine Sortierung z.B. mit <code>Arrays.sort</code> muss nach aufsteigender Ordnungszahl erfolgen.)</p>
</div>
<details>
<summary>Lösung</summary>
<div class="listingblock">
<div class="content">
<pre>public enum Element {
H("Wasserstoff", 1), C("Kohlenstoff", 6), N("Stickstoff", 7),
O("Sauerstoff", 8), P("Phosphor", 15), S("Schwefel", 16);
private final int ord;
private final String name;
Element(String name, int ord) {
this.ord = ord;
this.name = name;
}
public int getOrd() {
return ord;
}
public String getName() {
return name;
}
}</pre>
</div>
</div>
</details>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-11-10 15:00:34 Mitteleuropõische Zeit
Last updated 2017-11-14 17:59:58 Mitteleuropõische Zeit
</div>
</div>
</body>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment