s n h m r u

Minimallogo des digitalen Schulbuchs inf-schule.de. Schriftzug in Zustandsübergangsdiagramm eines endlichen Automaten.

s n h m r u
i

Fertiges Spiel

So wird gespielt

Zwei Spielerinnen oder Spieler spielen abwechselnd. Beide erstellen ein Tier, das zu Beginn eine bestimmte Menge an Energie und Glückslevel hat. Außerdem besitzen beide einen Vorrat an Futterportionen. In jedem Zug steht eine der folgenden Aktionen zur Auswahl:

Aktion Auswirkung
Tier füttern Die Methode fuettern(menge) wird am aktuellen Tier aufgerufen, wodurch die Energie des Tiers bis auf höchstens 10 erhöht wird. Die verfütterten Portionen werden vom Futter-Vorrat abgezogen.
Mit dem Tier spielen Die Methode spielen() wird am aktuellen Tier aufgerufen. Dabei verliert das Tier Energie, aber gewinnt Glück.
Futter suchen Der Futter-Vorrat wird um eine zufällige Anzahl von 1 bis 9 Portionen erhöht. Dabei wird die Methode langweilen() am aktuellen Tier aufgerufen, wodurch das Tier Energie und Glück verliert.

Nach jeder Aktion wird geprüft: Ein glückliches Tier, das nicht verhungert ist, gewinnt. Ein trauriges oder verhungertes Tier verliert.

Das BlueK-Projekt vervollständigen

Das Hauptprogramm mit der Spiellogik ist bereits fertig implementiert. Es enthält die main-Funktion und einige Hilfsfunktionen. Das bisherige Hauptprogramm muss deshalb vollständig durch den vorgegebenen Code ersetzt werden. Um die Seite nicht zu überladen, versteckt sich dieser hinter dem folgenden Button. Du kannst den gesamten Code kopieren, indem du oben rechts auf Copy klickst.

val namen = mutableListOf("", "")
val tiere = mutableListOf<Tier>()
val futter = mutableListOf(5, 5)

fun main() {
    neuesSpielZuruecksetzen()
    konsoleLeeren()

    for (nr in 1..2) {
        println("=== Daten für Spieler $nr ===")

        namen[nr - 1] = liesText("Name von Spieler $nr: ", "Spieler $nr")

        val tierName =
            liesText(
                "Name des Tieres von ${namen[nr - 1]}: ",
                "Tier $nr",
            )

        tiere.add(Tier(tierName))
    }

    konsoleLeeren()

    var aktuell = 0

    while (true) {
        val anderer = 1 - aktuell
        val tier = tiere[aktuell]

        zugBildschirm(aktuell)

        val aktion = liesAktion()
        val aktionsmeldung: String

        if (aktion == 0) {
            println()
            println("Spiel beendet.")
            return
        } else if (aktion == 1) {
            aktionsmeldung = fuettern(aktuell)
        } else if (aktion == 2) {
            tier.spielen()
            aktionsmeldung = "Du hast mit ${tier.name} gespielt."
        } else {
            val gefunden = (1..9).random()
            futter[aktuell] += gefunden
            tier.langweilen()

            aktionsmeldung = "Du hast ${futterportionenText(gefunden)} gefunden."
        }

        konsoleLeeren()

        println(aktionsmeldung)
        println()
        println("=== Neuer Zustand nach der Aktion ===")
        println("Übrige Futterportionen : ${futter[aktuell]}")
        println()

        zustandAusgeben(tier)
        println()

        if (tier.istGluecklich() && !tier.istVerhungert()) {
            println()
            println("🎉 ${namen[aktuell]} gewinnt! " + "${tier.name} ist glücklich.")
            return
        }

        if (tier.istTraurig()) {
            println()
            println("😢 ${tier.name} ist sehr traurig.")
            println("🏆 ${namen[anderer]} gewinnt!")
            return
        }

        if (tier.istVerhungert()) {
            println()
            println("💀 ${tier.name} hat keine Energie mehr.")
            println("🏆 ${namen[anderer]} gewinnt!")
            return
        }

        println()
        print("ENTER für Spielerwechsel ...")
        readLine()

        konsoleLeeren()
        aktuell = anderer
    }
}

private fun neuesSpielZuruecksetzen() {
    namen[0] = ""
    namen[1] = ""

    tiere.clear()

    futter[0] = 5
    futter[1] = 5
}

private fun zugBildschirm(nr: Int) {
    val tier = tiere[nr]

    println("===================================")
    println("${namen[nr]}, du bist am Zug")
    println("Du hast noch ${futterportionenText(futter[nr])}.")
    println("===================================")

    zustandAusgeben(tier)
    println()

    println("Aktionen:")
    println("1) ${tier.name} füttern")
    println("2) Mit ${tier.name} spielen")
    println("3) Futter suchen")
    println("0) Spiel beenden")
    println()
}

private fun zustandAusgeben(tier: Tier) {
    println("${tier.name}s Zustand")
    println("Energie     : ${tier.energie}")
    println("Glückslevel : ${tier.glueckslevel}")
}

private fun fuettern(nr: Int): String {
    val tier = tiere[nr]

    if (futter[nr] <= 0) {
        return "Du hast leider kein Futter mehr."
    }

    val menge =
        liesZahlImBereich(
            "Wie viele Futterportionen soll ${tier.name} bekommen " + "(1-${futter[nr]})? ",
            1,
            futter[nr],
        )

    futter[nr] -= menge
    tier.fuettern(menge)

    return "Du hast ${tier.name} mit ${futterportionenText(menge)} gefüttert."
}

private fun futterportionenText(anzahl: Int): String {
    return if (anzahl == 1) {
        "1 Futterportion"
    } else {
        "$anzahl Futterportionen"
    }
}

private fun liesAktion(): Int {
    while (true) {
        val eingabe = liesZahl("Bitte Zahl eingeben: ")

        if (eingabe in 0..3) {
            return eingabe
        }

        println("Ungültige Eingabe.")
    }
}

private fun konsoleLeeren() {
    print('\u000C')
}

private fun liesText(frage: String, standard: String): String {
    print(frage)

    val eingabe = readLine()?.trim()

    return if (eingabe.isNullOrEmpty()) {
        standard
    } else {
        eingabe
    }
}

private fun liesZahl(frage: String): Int {
    while (true) {
        print(frage)

        val zahl = readLine()?.trim()?.toIntOrNull()

        if (zahl != null) {
            return zahl
        }

        println("Bitte eine ganze Zahl eingeben.")
    }
}

private fun liesZahlImBereich(
    frage: String,
    min: Int,
    max: Int,
): Int {
    while (true) {
        val zahl = liesZahl(frage)

        if (zahl in min..max) {
            return zahl
        }

        println("Bitte eine Zahl zwischen $min und $max eingeben.")
    }
}

Aufgabe 1

Ersetze dein Hauptprogramm durch den vorgegebenen Code und spiele das Spiel, indem du per Rechtsklick main aufrufst oder den Button main starten klickst.

Zufallszahlen

Aktuell ist der Verlauf des Spiels sehr vorhersehbar, da die Methoden spielen und langweilen die Attributwerte bisher immer um feste Werte verändern. Um das Spiel interessanter zu machen, können wir bei den Methoden spielen und langweilen Zufallszahlen verwenden, um die energie und den glueckslevel des Tiers zufällig - innerhalb eines bestimmten Bereichs - zu verändern. Das folgende Code-Fragment demonstriert die Verwendung von Zufallszahlen in Kotlin.

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 Variablen zahl addiert werden.

Aufgabe 2

  • Lasse das obige Programmfragment mehrmals laufen und erläutere die Ausgabe.
  • Nutze Zufallszahlen, um die Werte der Attribute energie und glueckslevel bei den Methoden spielen und langweilen nicht immer um den gleichen Wert zu verändern, sondern um einen zufälligen Wert.

Aufgabe 3

Teste dein Spiel, also spiele es :-) Passe bei Bedarf die konkreten Zahlenwerte an, so dass das Spiel gut spielbar ist.

Suche

v
100.123.2.1.6 Fertiges Spiel
Kopieren durch Anklicken

Rückmeldung geben