Fertiges Spiel
Das Spiel vervollständigen
Die Klasse Spiel ist bereits fertig implementiert.
Du kannst in BlueJ eine neue Klasse Spiel
erstellen und den folgenden Code in diese Klasse kopieren,
um das Spiel zu vervollständigen.
Um die Seite nicht zu überladen, versteckt sich der Code hinter dem folgenden Button.
Du kannst den gesamten Code kopieren, indem du oben rechts auf
Copy klickst.
import kotlin.random.Random
class Spiel {
private data class Spieler(
val spielerName: String,
val tier: Tier,
var futter: Int
)
private sealed interface Aktion {
data object Fuettern : Aktion
data object Spielen : Aktion
data object FutterSuchen : Aktion
data object Beenden : Aktion
companion object {
fun fromEingabe(x: Int): Aktion? =
when (x) {
1 -> Fuettern
2 -> Spielen
3 -> FutterSuchen
0 -> Beenden
else -> null
}
}
}
fun starten() {
konsoleLeeren()
val spieler1 = erstelleSpieler(1, startFutter = 5)
val spieler2 = erstelleSpieler(2, startFutter = 5)
konsoleLeeren()
var aktueller = spieler1
var anderer = spieler2
while (true) {
zugBildschirm(aktueller)
when (val aktion = readAktion()) {
Aktion.Beenden -> {
println()
println("Spiel beendet.")
return
}
Aktion.Fuettern -> fuettern(aktueller)
Aktion.Spielen -> spielen(aktueller)
Aktion.FutterSuchen -> futterSuchen(aktueller)
}
// Nach jeder Aktion: Konsole leeren und neuen Zustand anzeigen
konsoleLeeren()
println("=== Neuer Zustand nach der Aktion ===")
statusAusgeben(aktueller)
println()
if (aktueller.tier.istGluecklich() && !aktueller.tier.istVerhungert()) {
println()
println("🎉 ${aktueller.spielerName} gewinnt! ${aktueller.tier.name} ist glücklich.")
return
}
if (aktueller.tier.istTraurig()) {
println()
println("😢 ${aktueller.tier.name} ist sehr traurig.")
println("🏆 ${anderer.spielerName} gewinnt!")
return
}
if (aktueller.tier.energie <= 0) {
println()
println("💀 ${aktueller.tier.name} hat keine Energie mehr.")
println("🏆 ${anderer.spielerName} gewinnt!")
return
}
println()
print("ENTER für Spielerwechsel …")
readLine()
konsoleLeeren()
aktueller = anderer.also { anderer = aktueller }
}
}
private fun erstelleSpieler(nr: Int, startFutter: Int): Spieler {
println("=== Daten für Spieler $nr ===")
val spielerName =
readText("Name von Spieler $nr: ", fallback = "Spieler $nr")
val tierName =
readText("Name des Tieres von $spielerName: ", fallback = "Tier $nr")
return Spieler(
spielerName = spielerName,
tier = Tier(tierName),
futter = startFutter
)
}
private fun zugBildschirm(spieler: Spieler) {
println("===================================")
println("${spieler.spielerName}, du bist am Zug")
println("Du hast noch ${spieler.futter} Futter-Portionen")
println("===================================")
println("${spieler.tier.name}s Zustand")
println("Energie : ${spieler.tier.energie}")
println("Glückslevel : ${spieler.tier.glueckslevel}")
println()
println("Aktionen:")
println("1) ${spieler.tier.name} füttern")
println("2) Mit ${spieler.tier.name} spielen")
println("3) Futter suchen")
println("0) Spiel beenden")
println()
}
private fun statusAusgeben(spieler: Spieler) {
println("Übrige Futtermenge : ${spieler.futter}")
println()
println("${spieler.tier.name}s Zustand")
println("Energie : ${spieler.tier.energie}")
println("Glueckslevel : ${spieler.tier.glueckslevel}")
}
private fun readAktion(): Aktion {
while (true) {
val eingabe = readInt("Bitte Zahl eingeben: ")
val aktion = Aktion.fromEingabe(eingabe)
if (aktion != null) return aktion
println("Ungültige Eingabe.")
}
}
private fun fuettern(spieler: Spieler) {
if (spieler.futter <= 0) {
println("Kein Futter vorhanden!")
return
}
val menge = readIntInRange(
"Wie viel Futter soll ${spieler.tier.name} bekommen (1–${spieler.futter})? ",
1,
spieler.futter
)
spieler.futter -= menge
spieler.tier.fuettern(menge)
println("${spieler.spielerName} füttert ${spieler.tier.name} mit $menge.")
}
private fun spielen(spieler: Spieler) {
spieler.tier.spielen()
println("${spieler.spielerName} spielt mit ${spieler.tier.name}.")
}
private fun futterSuchen(spieler: Spieler) {
val gefunden = Random.nextInt(1, 10)
spieler.futter += gefunden
spieler.tier.langweilen()
println("${spieler.spielerName} sucht Futter und findet $gefunden.")
}
private fun konsoleLeeren() {
print('\u000C') // Form Feed
}
private fun readText(prompt: String, fallback: String): String {
print(prompt)
return readLine()?.trim().takeUnless { it.isNullOrBlank() } ?: fallback
}
private fun readInt(prompt: String): Int {
while (true) {
print(prompt)
val x = readLine()?.trim()?.toIntOrNull()
if (x != null) return x
println("Bitte eine ganze Zahl eingeben.")
}
}
private fun readIntInRange(prompt: String, min: Int, max: Int): Int {
while (true) {
val x = readInt(prompt)
if (x in min..max) return x
println("Bitte eine Zahl zwischen $min und $max eingeben.")
}
}
}
Aufgabe 1
Spiel entsprechend der obigen Beschreibung
und teste es, indem du ein Spiel-Objekt erstellst und die Methode
starten() aufrufst.
Zufallszahlen
Aktuell ist der Verlauf des Spiels komplett vorhersehbar,
da die Aktionen der Spieler immer die gleichen Auswirkungen haben.
Um das Spiel interessanter zu machen, können wir bei den
Methoden spielen und langweilen
Zufallszahlen verwenden, um die energie und glueckslevel
des Tiers unterschiedlich zu verändern.
Die einfachste Möglichkeit, Zufallszahlen in Kotlin zu verwenden,
ist die Funktion random() im Zusammenhang mit
einem Bereichsoperator, z.B. 2..4.
fun main() {
var zahl = 5
println(zahl)
zahl = zahl + (2..4).random()
println(zahl)
}
Wenn du in späteren Abschnitten noch einmal Zufallszahlen verwenden möchtest, und nicht mehr genau weißt, wie das funktioniert, kannst du in den Tipps zu Kotlin nachschauen, wo die Verwendung von Zufallszahlen ausführlich erklärt wird.
Wenn du genau wissen möchtest was hier passiert ...
Der Ausdruck (2..4) erzeugt ein Objekt vom Typ IntRange,
das die Zahlen 2, 3 und 4 enthält.
So wie du an einem Objekt der Klasse Tier die Methode
fuettern() aufrufen kannst, kannst du an einem Objekt der
Klasse IntRange die Methode random() aufrufen.
Die Methode random() wählt zufällig eine dieser Zahlen aus
und gibt sie zurück.
In diesem Fall könnte also entweder 2, 3 oder 4 zu der
Variable zahl addiert werden.
Aufgabe 2
- Lasse das obige Programmfragment mehrmals laufen und erläutere die Ausgabe.
-
Nutze Zufallszahlen, um die Werte der Attribute
energieundglueckslevelbei den Methodenspielenundlangweilennicht immer um den gleichen Wert zu verändern, sondern um einen zufälligen Wert.