Compare commits
8 Commits
4be67cbf33
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3210503b64 | |||
| 3dace33759 | |||
| 05f883fdf1 | |||
| 14702200e9 | |||
| ff3b4c2963 | |||
| e576b37e16 | |||
| 2369958a2e | |||
| 9ec4ee6c5b |
@@ -1 +1,5 @@
|
||||
# OOP Klausuren der vergangenen Jahre
|
||||
# OOP Klausuren der vergangenen Jahre
|
||||
- 2025 ST
|
||||
- 2025 FT
|
||||
- 2024 ST
|
||||
- 2024 FT
|
||||
241
src/j2024/FT/AriadneIterator.java
Normal file
241
src/j2024/FT/AriadneIterator.java
Normal file
@@ -0,0 +1,241 @@
|
||||
package j2024.FT;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
public class AriadneIterator implements Iterator<Room> {
|
||||
|
||||
private final Room entry;
|
||||
private Stack<Room> ariadnesThread;
|
||||
private Set<Room> visited;
|
||||
private State currentState;
|
||||
|
||||
public AriadneIterator(Room entry) {
|
||||
this.entry = entry;
|
||||
this.ariadnesThread = new Stack<>();
|
||||
this.visited = new HashSet<>();
|
||||
this.currentState = new Starting();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Iterator interface
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentState.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Laut Spezifikation: ruft zuerst step() auf,
|
||||
* gibt dann die aktuelle Position (letzter Eintrag in ariadnesThread) zurück.
|
||||
*/
|
||||
@Override
|
||||
public Room next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
step();
|
||||
return ariadnesThread.peek();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Private Hilfsmethoden (werden von den Zuständen genutzt)
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Delegiert step() an den aktuellen Zustand.
|
||||
*/
|
||||
private void step() {
|
||||
currentState.step();
|
||||
}
|
||||
|
||||
/**
|
||||
* Theseus betritt das Labyrinth am Eingang:
|
||||
* Eingang auf den Faden legen und als besucht markieren.
|
||||
* Achtung: currentState wird hier NICHT verändert – das obliegt dem Starting-Zustand.
|
||||
*/
|
||||
private void init() {
|
||||
ariadnesThread.push(entry);
|
||||
visited.add(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert true, wenn Theseus den Raum mit dem Minotaurus erreicht hat.
|
||||
*/
|
||||
private boolean foundMinotaur() {
|
||||
return ariadnesThread.peek().hasMinotaur();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tiefensuche (depth-first): Betritt den ersten noch nicht besuchten Nachbarn.
|
||||
* Gibt es keinen solchen Nachbarn (Sackgasse), wird per Backtracking ein Schritt
|
||||
* zurückgegangen (pop), ohne einen neuen Raum zu betreten.
|
||||
*
|
||||
* Hinweis: next() gibt anschließend ariadnesThread.peek() zurück,
|
||||
* also entweder den neu betretenen Raum oder den Raum nach dem Backtrack.
|
||||
*/
|
||||
private void seekingStep() {
|
||||
Room current = ariadnesThread.peek();
|
||||
for (Room neighbor : current.getReachable()) {
|
||||
if (!visited.contains(neighbor)) {
|
||||
// Unbesuchten Nachbarn betreten
|
||||
ariadnesThread.push(neighbor);
|
||||
visited.add(neighbor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Sackgasse → Backtracking: einen Schritt zurück
|
||||
retreatingStep();
|
||||
}
|
||||
|
||||
/**
|
||||
* Theseus geht entlang des Ariadnefadens einen Schritt zurück.
|
||||
*/
|
||||
private void retreatingStep() {
|
||||
ariadnesThread.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert den nächsten noch nicht besuchten Nachbarn des aktuellen Raums,
|
||||
* oder null wenn keiner existiert.
|
||||
*/
|
||||
private Room nextForward() {
|
||||
Room current = ariadnesThread.peek();
|
||||
for (Room neighbor : current.getReachable()) {
|
||||
if (!visited.contains(neighbor)) {
|
||||
return neighbor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// State Pattern – Interface
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Das Interface wird von AriadneIterator intern definiert.
|
||||
* (Laut Aufgabe muss der Code für das Interface nicht hingeschrieben werden –
|
||||
* hier dennoch vollständig angegeben.)
|
||||
*/
|
||||
private interface State {
|
||||
void step();
|
||||
boolean hasNext();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Konkreter Zustand: Starting
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Startzustand: Theseus hat das Labyrinth noch nicht betreten.
|
||||
* Beim ersten step()-Aufruf wird init() aufgerufen und in den
|
||||
* nächsten Zustand gewechselt.
|
||||
*/
|
||||
private class Starting implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
init(); // Eingang betreten, Faden anbinden
|
||||
if (foundMinotaur()) {
|
||||
// Minotaurus steht direkt am Eingang
|
||||
currentState = new MissionAccomplished();
|
||||
} else {
|
||||
currentState = new SeekingMinotaur();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Die Iteration hat noch nicht begonnen → es gibt noch Elemente.
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Konkreter Zustand: SeekingMinotaur
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Suchzustand: Theseus durchsucht das Labyrinth per Tiefensuche.
|
||||
* Dieser Zustand muss laut Aufgabe NICHT vollständig realisiert werden,
|
||||
* wird hier aber der Vollständigkeit halber angegeben.
|
||||
*/
|
||||
private class SeekingMinotaur implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
seekingStep();
|
||||
// Nach dem Schritt prüfen, ob Minotaurus gefunden wurde
|
||||
if (!ariadnesThread.empty() && foundMinotaur()) {
|
||||
currentState = new MissionAccomplished();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Solange Theseus sucht, gibt es immer noch weitere Elemente
|
||||
* (das Labyrinth hat garantiert einen Weg zum Minotaurus).
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Konkreter Zustand: MissionAccomplished
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Rückweg-Zustand: Der Minotaurus wurde besiegt; Theseus folgt dem
|
||||
* Ariadnefaden zurück zum Eingang.
|
||||
*
|
||||
* Übergang zu Finished: Sobald step() den Ariadnefaden auf den alleinigen
|
||||
* Eingangsraum reduziert hat, wechselt der Zustand auf Finished –
|
||||
* next() gibt dann noch den Eingang zurück (peek), danach ist
|
||||
* hasNext() == false.
|
||||
*/
|
||||
private class MissionAccomplished implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
retreatingStep();
|
||||
// Sind wir wieder am Eingang angekommen?
|
||||
if (ariadnesThread.size() == 1 && ariadnesThread.peek() == entry) {
|
||||
currentState = new Finished();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true; // Es gibt noch mindestens den Eingang zurückzugeben
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Konkreter Zustand: Finished
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Endzustand: Theseus ist wieder am Eingang, die Iteration ist abgeschlossen.
|
||||
* hasNext() liefert false; step() ist eine No-Op.
|
||||
*/
|
||||
private class Finished implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
// Iteration beendet – nichts zu tun
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/j2024/FT/AriadneIteratorTest.java
Normal file
24
src/j2024/FT/AriadneIteratorTest.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package j2024.FT;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class AriadneIteratorTest {
|
||||
|
||||
@Test
|
||||
public void testSmallMaze() {
|
||||
Room entry = SampleMaze.createSmallMaze();
|
||||
|
||||
AriadneIterator iter = new AriadneIterator(entry);
|
||||
|
||||
assertEquals("a2", iter.next().getName());
|
||||
assertEquals("b2", iter.next().getName());
|
||||
assertEquals("b1", iter.next().getName());
|
||||
assertEquals("b2", iter.next().getName());
|
||||
assertEquals("a2", iter.next().getName());
|
||||
|
||||
assertFalse(iter.hasNext());
|
||||
}
|
||||
}
|
||||
BIN
src/j2024/FT/KlausurOOP_FT24.pdf
Normal file
BIN
src/j2024/FT/KlausurOOP_FT24.pdf
Normal file
Binary file not shown.
38
src/j2024/FT/Room.java
Normal file
38
src/j2024/FT/Room.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package j2024.FT;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Room {
|
||||
private final String name;
|
||||
private boolean minotaur;
|
||||
|
||||
private Set<Room> reachable;
|
||||
|
||||
public Room(String name) {
|
||||
this.name = name;
|
||||
minotaur = false;
|
||||
reachable = new HashSet<>();
|
||||
}
|
||||
|
||||
public void setMinotaur(boolean v) {
|
||||
minotaur = v;
|
||||
}
|
||||
|
||||
public void addReachable(Room room) {
|
||||
reachable.add(room);
|
||||
room.getReachable().add(this);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean hasMinotaur() {
|
||||
return minotaur;
|
||||
}
|
||||
|
||||
public Set<Room> getReachable() {
|
||||
return reachable;
|
||||
}
|
||||
}
|
||||
19
src/j2024/FT/SampleMaze.java
Normal file
19
src/j2024/FT/SampleMaze.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package j2024.FT;
|
||||
|
||||
public class SampleMaze {
|
||||
|
||||
public static Room createSmallMaze() {
|
||||
Room a1 = new Room("a1");
|
||||
Room b1 = new Room("b1");
|
||||
Room a2 = new Room("a2");
|
||||
Room b2 = new Room("b2");
|
||||
|
||||
b1.setMinotaur(true);
|
||||
|
||||
a2.addReachable(b2);
|
||||
b2.addReachable(b1);
|
||||
b1.addReachable(a1);
|
||||
|
||||
return a2;
|
||||
}
|
||||
}
|
||||
6
src/j2024/FT/State.java
Normal file
6
src/j2024/FT/State.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package j2024.FT;
|
||||
|
||||
public interface State {
|
||||
public void step();
|
||||
public boolean hasNext();
|
||||
}
|
||||
153
src/j2024/ST/AriadneIterator.java
Normal file
153
src/j2024/ST/AriadneIterator.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package j2024.ST;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
public class AriadneIterator implements Iterator<Node> {
|
||||
|
||||
private final Node entry;
|
||||
private Stack<Node> ariadnesThread;
|
||||
private Set<Node> visited;
|
||||
private State currentState;
|
||||
|
||||
public AriadneIterator(Node entry) {
|
||||
this.entry = entry;
|
||||
this.ariadnesThread = new Stack<>();
|
||||
this.visited = new HashSet<>();
|
||||
this.currentState = new Starting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentState.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
step();
|
||||
|
||||
if (ariadnesThread.empty()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
return ariadnesThread.peek();
|
||||
}
|
||||
|
||||
private void step() {
|
||||
currentState.step();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
ariadnesThread.push(entry);
|
||||
visited.add(entry);
|
||||
}
|
||||
|
||||
private boolean foundMiraculix() {
|
||||
return ariadnesThread.peek().hasMiraculix();
|
||||
}
|
||||
|
||||
private Node nextForward() {
|
||||
Node current = ariadnesThread.peek();
|
||||
|
||||
for (Node next : current.getReachable()) {
|
||||
if (!visited.contains(next)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void seekingStep() {
|
||||
Node next = nextForward();
|
||||
|
||||
if (next != null) {
|
||||
ariadnesThread.push(next);
|
||||
visited.add(next);
|
||||
} else {
|
||||
retreatingStep();
|
||||
}
|
||||
}
|
||||
|
||||
private void retreatingStep() {
|
||||
ariadnesThread.pop();
|
||||
}
|
||||
|
||||
private interface State {
|
||||
void step();
|
||||
|
||||
boolean hasNext();
|
||||
}
|
||||
|
||||
private class Starting implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
init();
|
||||
|
||||
if (foundMiraculix()) {
|
||||
currentState = new MissionAccomplished();
|
||||
} else {
|
||||
currentState = new SeekingMiraculix();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class SeekingMiraculix implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
seekingStep();
|
||||
|
||||
if (!ariadnesThread.empty() && foundMiraculix()) {
|
||||
currentState = new MissionAccomplished();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class MissionAccomplished implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
retreatingStep();
|
||||
|
||||
if (ariadnesThread.size() == 1 && ariadnesThread.peek() == entry) {
|
||||
currentState = new Finished();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return ariadnesThread.size() > 1;
|
||||
}
|
||||
}
|
||||
|
||||
private class Finished implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/j2024/ST/AriadneIteratorTest.java
Normal file
24
src/j2024/ST/AriadneIteratorTest.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package j2024.ST;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class AriadneIteratorTest {
|
||||
|
||||
@Test
|
||||
public void testSmallVillage() {
|
||||
Node entry = SampleVillage.createSmallVillage();
|
||||
|
||||
AriadneIterator iter = new AriadneIterator(entry);
|
||||
|
||||
assertEquals(1, iter.next().getNumber());
|
||||
assertEquals(2, iter.next().getNumber());
|
||||
assertEquals(3, iter.next().getNumber());
|
||||
assertEquals(2, iter.next().getNumber());
|
||||
assertEquals(1, iter.next().getNumber());
|
||||
|
||||
assertFalse(iter.hasNext());
|
||||
}
|
||||
}
|
||||
BIN
src/j2024/ST/KlausurOOP_ST24.pdf
Normal file
BIN
src/j2024/ST/KlausurOOP_ST24.pdf
Normal file
Binary file not shown.
38
src/j2024/ST/Node.java
Normal file
38
src/j2024/ST/Node.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package j2024.ST;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Node {
|
||||
|
||||
private final int number;
|
||||
private boolean miraculix;
|
||||
private Set<Node> reachable;
|
||||
|
||||
public Node(int number) {
|
||||
this.number = number;
|
||||
this.miraculix = false;
|
||||
this.reachable = new HashSet<>();
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public boolean hasMiraculix() {
|
||||
return miraculix;
|
||||
}
|
||||
|
||||
public void setMiraculix(boolean miraculix) {
|
||||
this.miraculix = miraculix;
|
||||
}
|
||||
|
||||
public Set<Node> getReachable() {
|
||||
return reachable;
|
||||
}
|
||||
|
||||
public void addReachable(Node node) {
|
||||
reachable.add(node);
|
||||
node.reachable.add(this);
|
||||
}
|
||||
}
|
||||
19
src/j2024/ST/SampleVillage.java
Normal file
19
src/j2024/ST/SampleVillage.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package j2024.ST;
|
||||
|
||||
public class SampleVillage {
|
||||
|
||||
public static Node createSmallVillage() {
|
||||
Node n1 = new Node(1);
|
||||
Node n2 = new Node(2);
|
||||
Node n3 = new Node(3);
|
||||
Node n4 = new Node(4);
|
||||
|
||||
n3.setMiraculix(true);
|
||||
|
||||
n1.addReachable(n2);
|
||||
n2.addReachable(n3);
|
||||
n3.addReachable(n4);
|
||||
|
||||
return n1;
|
||||
}
|
||||
}
|
||||
9
src/j2025/FT/Die.java
Normal file
9
src/j2025/FT/Die.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package j2025.FT;
|
||||
|
||||
public enum Die {
|
||||
ONE, TWO, THREE, FOUR, FIVE, SIX;
|
||||
|
||||
public static Die random() {
|
||||
return values()[(int) (Math.random() * 6)];
|
||||
}
|
||||
}
|
||||
141
src/j2025/FT/Game.java
Normal file
141
src/j2025/FT/Game.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package j2025.FT;
|
||||
|
||||
public class Game {
|
||||
|
||||
private final PlayerHandler playerHandler;
|
||||
private PairOfDice dice;
|
||||
private PairOfDice announcement;
|
||||
|
||||
public Game(PlayerHandler playerHandler) {
|
||||
this.playerHandler = playerHandler;
|
||||
}
|
||||
|
||||
public void checkValue() {
|
||||
state.checkValue();
|
||||
}
|
||||
|
||||
public void rollTheDice() {
|
||||
state.rollTheDice();
|
||||
}
|
||||
|
||||
public void announce(PairOfDice pairOfDice) {
|
||||
state.announce(pairOfDice);
|
||||
}
|
||||
|
||||
public void callLiar() {
|
||||
state.callLiar();
|
||||
}
|
||||
|
||||
public PairOfDice getDice() {
|
||||
return dice;
|
||||
}
|
||||
|
||||
public PairOfDice getAnnouncement() {
|
||||
return announcement;
|
||||
}
|
||||
|
||||
public PlayerHandler getPlayerHandler() {
|
||||
return playerHandler;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private State startRound = new State() {
|
||||
|
||||
@Override
|
||||
void checkValue() {
|
||||
System.out.println("Aktueller Spieler sieht:" + getDice().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
void rollTheDice() {
|
||||
dice = PairOfDice.random();
|
||||
state = initialValue;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private State initialValue = new State() {
|
||||
|
||||
@Override
|
||||
void checkValue() {
|
||||
System.out.println("Aktueller Spieler sieht:" + getDice().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
void announce(PairOfDice value) {
|
||||
announcement = value;
|
||||
playerHandler.nextTurn();
|
||||
state = choice;
|
||||
}
|
||||
};
|
||||
|
||||
private State choice = new State() {
|
||||
|
||||
@Override
|
||||
void announce(PairOfDice value) {
|
||||
if (value.compareTo(getAnnouncement()) > 0) {
|
||||
announcement = value;
|
||||
playerHandler.nextTurn();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void checkValue() {
|
||||
System.out.println("Aktueller Spieler sieht:" + getDice().toString());
|
||||
state = increaseValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
void callLiar() {
|
||||
if (getAnnouncement().compareTo(dice) > 0) {
|
||||
playerHandler.currentPlayerWinsRound();
|
||||
} else {
|
||||
playerHandler.previusPlayerWinsRound();
|
||||
}
|
||||
|
||||
if (playerHandler.remaining() > 1) {
|
||||
state = startRound;
|
||||
} else {
|
||||
state = gameOver;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private State increaseValue = new State() {
|
||||
|
||||
@Override
|
||||
void checkValue() {
|
||||
System.out.println("Aktueller Spieler sieht:" + getDice().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
void announce(PairOfDice value) {
|
||||
if (value.compareTo(announcement) > 0) {
|
||||
announcement = value;
|
||||
playerHandler.nextTurn();
|
||||
state = choice;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private State gameOver = new State() {
|
||||
|
||||
// Konstruktor von anonymen Klassen
|
||||
{
|
||||
entry();
|
||||
}
|
||||
|
||||
private void entry() {
|
||||
System.out.println("Spiel vorbei!");
|
||||
System.out.println("Spieler " + playerHandler.getCurrentPlayer().getName() + " gewinnt!");
|
||||
for (Player player : playerHandler.getRanking()) {
|
||||
System.out.println("Platz " + (playerHandler.getRanking().indexOf(player) + 2) + ": " + player.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private State state = startRound;
|
||||
}
|
||||
7
src/j2025/FT/InvalidAction.java
Normal file
7
src/j2025/FT/InvalidAction.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package j2025.FT;
|
||||
|
||||
public class InvalidAction extends RuntimeException{
|
||||
public InvalidAction(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
BIN
src/j2025/FT/KlausurOOP_FT25.pdf
Normal file
BIN
src/j2025/FT/KlausurOOP_FT25.pdf
Normal file
Binary file not shown.
40
src/j2025/FT/PairOfDice.java
Normal file
40
src/j2025/FT/PairOfDice.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package j2025.FT;
|
||||
|
||||
public class PairOfDice implements Comparable<PairOfDice> {
|
||||
|
||||
private final Die die1;
|
||||
private final Die die2;
|
||||
|
||||
public PairOfDice(Die die1, Die die2) {
|
||||
this.die1 = die1;
|
||||
this.die2 = die2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(PairOfDice other) {
|
||||
return Integer.compare(this.getValue(), other.getValue());
|
||||
}
|
||||
|
||||
private int getValue() {
|
||||
int high = Math.max(die1.ordinal(), die2.ordinal());
|
||||
int low = Math.min(die1.ordinal(), die2.ordinal());
|
||||
|
||||
// Mäxchen (2,1) → höchster Wert
|
||||
if (high == 2 && low == 1) return Integer.MAX_VALUE;
|
||||
|
||||
// Pasch → 100 + Augenzahl (11..66 → 101..106)
|
||||
if (high == low) return 100 + high;
|
||||
|
||||
// Normale Würfe → zweistellige Zahl (z.B. 6,5 → 65)
|
||||
return high * 10 + low;
|
||||
}
|
||||
|
||||
public static PairOfDice random() {
|
||||
return new PairOfDice(Die.random(), Die.random());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return die1.ordinal() + 1 + " " + (die2.ordinal() + 1);
|
||||
}
|
||||
}
|
||||
27
src/j2025/FT/PairOfDiceTest.java
Normal file
27
src/j2025/FT/PairOfDiceTest.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package j2025.FT;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class PairOfDiceTest {
|
||||
private final PairOfDice p33 = new PairOfDice(Die.THREE, Die.THREE);
|
||||
private final PairOfDice p41 = new PairOfDice(Die.FOUR, Die.ONE);
|
||||
|
||||
|
||||
@Test
|
||||
public void testCompareTo() {
|
||||
// p33 ist Pasch → Wert 102, p41 → Wert 41: p33 > p41
|
||||
assertTrue(p33.compareTo(p41) > 0);
|
||||
assertTrue(p41.compareTo(p33) < 0);
|
||||
assertEquals(0, p33.compareTo(p33));
|
||||
assertEquals(0, p41.compareTo(p41));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
assertEquals("3 3", p33.toString());
|
||||
assertEquals("4 1", p41.toString());
|
||||
}
|
||||
}
|
||||
24
src/j2025/FT/Player.java
Normal file
24
src/j2025/FT/Player.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package j2025.FT;
|
||||
|
||||
public class Player {
|
||||
|
||||
private final String name;
|
||||
private int points = 10;
|
||||
|
||||
public Player(String name, int points) {
|
||||
this.name = name;
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
public int getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void losesPoint() {
|
||||
points--;
|
||||
}
|
||||
}
|
||||
55
src/j2025/FT/PlayerHandler.java
Normal file
55
src/j2025/FT/PlayerHandler.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package j2025.FT;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlayerHandler {
|
||||
|
||||
private List<Player> players = new LinkedList<>();
|
||||
private List<Player> ranking = new ArrayList<>();
|
||||
|
||||
public void addPlayer(Player player) {
|
||||
players.add(player);
|
||||
}
|
||||
|
||||
public Player getCurrentPlayer() {
|
||||
return players.getFirst();
|
||||
}
|
||||
|
||||
public void nextTurn() {
|
||||
players.add(players.removeFirst());
|
||||
}
|
||||
|
||||
public int remaining() {
|
||||
return players.size();
|
||||
}
|
||||
|
||||
public void currentPlayerWinsRound() {
|
||||
Player lastPlayer = players.getLast();
|
||||
lastPlayer.losesPoint();
|
||||
removePlayer(lastPlayer);
|
||||
}
|
||||
|
||||
public void previusPlayerWinsRound() {
|
||||
Player currentPlayer = getCurrentPlayer();
|
||||
Player lastPlayer = players.getLast();
|
||||
currentPlayer.losesPoint();
|
||||
removePlayer(currentPlayer);
|
||||
|
||||
while (players.getFirst() != lastPlayer) {
|
||||
nextTurn();
|
||||
}
|
||||
}
|
||||
|
||||
private void removePlayer(Player player) {
|
||||
if (player.getPoints() == 0) {
|
||||
ranking.add(player);
|
||||
players.remove(player);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Player> getRanking() {
|
||||
return ranking;
|
||||
}
|
||||
}
|
||||
17
src/j2025/FT/State.java
Normal file
17
src/j2025/FT/State.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package j2025.FT;
|
||||
|
||||
abstract class State {
|
||||
void checkValue() {}
|
||||
|
||||
void rollTheDice() {
|
||||
throw new InvalidAction("You must not roll the dice in state " + this);
|
||||
}
|
||||
|
||||
void announce(PairOfDice value) {
|
||||
throw new InvalidAction("You must not announce a value in state " + this);
|
||||
}
|
||||
|
||||
void callLiar() {
|
||||
throw new InvalidAction("You must not call liar in state " + this);
|
||||
}
|
||||
}
|
||||
BIN
src/j2025/ST/KlausurOOP_ST25.pdf
Normal file
BIN
src/j2025/ST/KlausurOOP_ST25.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user