i

Basisversion des Spiels

Grundgerüst

Wir fangen zuerst mit einer ganz einfachen Version des Spiels an und werden diese dann Stück für Stück ergänzen und verbessern. Am Ende dieser Seite wird dann eine einfache, aber für zwei Spieler spielbare Version des Spiels entstanden sein. Diese solltest Du dann z.B. anhand der Übungen noch weiter ausbauen.

Als Ausgangspunkt für die Implementierung nutzen wir folgenden Code:

class Spiel
{
    Spiel()
    {
    }

    void rateEinmal()
    {
        System.out.println("Wie viel ist " + zufallszahl(10) + " + " + zufallszahl(10) + "?");
        leseZahl();
        System.out.println("Das Ergebnis war " + (zufallszahl(10) + zufallszahl(10)) );
    }

    int zufallszahl(int n)
    {
        return new java.util.Random().nextInt(n);
    }

    int leseZahl()
    {
        return new java.util.Scanner(System.in).nextInt();
    }

}

Die Methode zufallszahl gibt eine Zufallszahl von 0 bis n-1 zurück. Da wir an mehreren Stellen Zufallszahlen erzeugen werden, ist es praktischer diese Methode zu nutzen, anstatt immer den recht länglichen Ausdruck new java.util.Random().nextInt(n) zu notieren.

Benutzereingaben sind in Java etwas kompliziert, weswegen wir hier einfach die angegebene Methode leseZahl nutzen. Du musst diese nicht verstehen. Du musst nur wissen, was die Methode bewirkt: Auf dem Bildschirm erscheint eine Eingabemöglichkeit für den Benutzer, um eine Zahl einzugeben. Die Methode hält so lange an, bis der Benutzer eine Zahl eingegeben hat und gibt diese dann zurück. Falls der Benutzer keine gültige Zahl eingibt, bricht das Programm mit einer Fehlermeldung ab.

Aufgabe 1 - Grundgerüst

  • Erstelle in BlueJ ein neues Projekt und darin die Klasse Spiel. Kopiere den obigen Quellcode hinein und übersetze/compiliere die Klasse. Teste die beiden Methoden zufallszahl und leseZahl, um deren Wirkung kennenzulernen.
  • Teste und erkläre die Wirkung von rateEinmal. Achte dabei auch auf die unterschiedliche Wirkung des +-Operators. Hinweis: System.out.println(...) gibt den Wert des übergebenen Parameters auf dem Bildschirm aus.

Lokale Variablen

Damit das Programm funktioniert, benötigen wir eine Möglichkeit mindestens die Zufallszahlen und evtl. noch weitere Daten zu speichern. Theoretisch könnte man dies in Form von Attributen der Klasse Spiel erreichen. Allerdings handelt es sich um Variablen, die wir eigentlich nur während der Ausführung der Methode rateEinmal benötigen. Es macht also viel mehr Sinn diese Variablen dort zu definieren, wo wir sie auch benötigen, nämlich als lokale Variablen in der Methode rateEinmal.

Lokale Variablen werden innerhalb der Methode (genauer: ihres Geltungsbereichs) erzeugt und am Ende wieder zerstört. Wird die Methode ein zweites mal aufgerufen, sind die Werte des ersten Aufrufs also verloren. Außerdem muss man beachten, dass lokale Variablen in Java immer initialisiert (also mit einem Wert belegt, werden müssen), während Attribute automatisch mit einem Standardwert (z.B. 0 für alle Zahlentypen) belegt werden.

Aufgabe 2 - lokale Variablen

int zahl1 = zufallszahl(10); int zahl2 = zufallszahl(10); int loesung = zahl1 + zahl2; System.out.println("Wie viel ist " + zahl1 + " + " + zahl2 + "?"); int antwort = leseZahl(); System.out.println("Das Ergebnis war " + loesung );

Ordne die Codeschnipsel, um eine funktionierende Version der Methode rateEinmal zu erhalten. Ergänze die Methode in Deinem Programm und teste sie.

Fallunterscheidungen

Bis jetzt muss man selbst überprüfen, ob man richtig gerechnet hat. Viel schöner wäre natürlich, wenn der angezeigte Text dies in einer Fallunterscheidung schon berücksichtigt.

Fallunterscheidungen lassen sich unterschiedlich darstellen. Umgangssprachlich könnte man sagen: Falls die Antwort richtig eingegeben wurde, dann gebe Super! aus, sonst gebe Leider falsch aus.

Eine Fallunterscheidung enthält also eine Bedingung, Anweisungenen, die ausgeführt werden, falls die Bedingung wahr ist, und evtl. alternative Anweisungen.

Die Abläufe lassen sich auch durch ein Struktogramm oder Flussdiagramm visualisieren:

Struktogramm zu if-Anweisungen Flussdiagramm zu if-Anweisungen

Aufgabe 3 - Fallunterscheidungen in Java

if(antwort == loesung) { System.out.println("Super! Richtig gerechnet."); } else { System.out.println("Leider falsch. Richtig war:" + loesung); }

Sortiere die Codeschnipsel und ergänze die Methode rateEinmal. Beachte den Unterschied zwischen == und dem Dir bisher bekannten =.

Zwei-Spieler-Version mit Punkten

Als nächstes sollen zwei Spieler gegeneinander spielen können und die Punkte gezählt werden.

Aufgabe 4 - rateEinmal mit Rückgabe

Um überhaupt Punkte zählen zu können, soll die Methode rateEinmal zurückgeben, ob der Spieler richtig gerechnet hat, oder nicht. Ändere die Methode so ab, dass zusätzlich zur Ausgabe true zurückgegeben wird, falls der Spieler richtig gerechnet hat, ansonsten false. Die Signatur der Methode muss so geändert werden, dass ein Wahrheitswert zurückgegeben werden kann. Am Endes des if-Zweiges muss true zurückgegeben werden, am Ende des else-Zweiges muss false zurückgegeben werden.

Aufgabe 5 - eineRundeSpielen

Füge eine neue Methode eineRundeSpielen ein gemäß den folgenden Anforderungen:

  • Die Zahl der gespielten Runden soll gezählt werden. Dazu wird ein Attribut runden benötigt, das innerhalb der Methode eineRundeSpielen erhöht wird.
  • Es soll zwei mal die Methode rateEinmal aufgerufen werden, um für die beiden Spieler je eine Aufgabe zu stellen.
  • Wenn der erste Spieler richtig geraten hat, soll dessen Punktestand um eins erhöht werden. Dazu muss ein neues Attribut punkte1 eingeführt werden. Für den zweiten Spieler gilt dies analog.
  • Der Punktestand der beiden Spieler soll ausgegeben werden.

Oben im Quelltext der Klasse müssen drei Attribute eingefügt werden mit int punkte1;, int punkte2; und int runden;. Die Methode eineRundeSpielen besteht aus den (sortierbaren) Zeilen:

  • void eineRundeSpielen()
  • {
  • runden = runden + 1;
  • boolean richtigGeraten1 = rateEinmal();
  • boolean richtigGeraten2 = rateEinmal();
  • if(richtigGeraten1)
  • {
  • punkte1 = punkte1 + 1;
  • }
  • if(richtigGeraten2)
  • {
  • punkte2 = punkte2 + 1;
  • }
  • System.out.println("Spieler 1 hat " + punkte1 + " Punkt(e)");
  • System.out.println("Spieler 2 hat " + punkte2 + " Punkt(e)");
  • System.out.println(); // Für etwas Abstand zur nächsten Runde
  • }

Automatischer Spielablauf

Bis jetzt musst Du die Methode eineRundeSpielen so oft aufrufen wie Du spielen möchtest. Statt dessen soll nun eine Spielelogik dafür sorgen, dass automatisch fünf Runden gespielt und dann der Gewinner ausgegeben wird.

Aufgabe 6 - spielSteuern

Schreibe dazu eine neue Methode spielSteuern. Diese ruft die Methode eineRundeSpielen auf, solange die Rundenzahl kleiner als fünf ist. Danach wird überprüft wer gewonnen hat und eine entsprechende Meldung ausgegeben. Hinweis: Besteht ein if- oder else-Zweig nur aus einer einzelnen Anweisung können die geschweiften Klammern auch weggelassen werden. Das kann den Code manchmal übersichtlicher machen.

Als Struktogramm lässt sich das folgendermaßen darstellen:

Struktogramm zur Methode spielSteuern

Wie man Wiederholungen programmiert, wirst Du im nächsten Projekt ausführlich lernen. Du wirst aber bestimmt keine Probleme haben, das vorgegebene Fragment zu verstehen und gemäß dem Struktogramm zu ergänzen:

void spielSteuern()
{
    while(runden < 5) {
        eineRundeSpielen();
    }
    // Hier musst Du noch überprüfen wer gewonnen hat...
}

Logische Operatoren

Die Gewinnregel soll nun etwas angepasst werden: Der Spieler, der zuerst fünf Punkte hat, gewinnt. Es sollen aber höchstens zehn Runden gespielt werden.

Wir benötigen dazu die Möglichkeit einzelne Wahrheitswerte zu verknüpfen oder zu negieren, also deren Wert umzukehren. In Java benutzt man den Operator &&, um eine logisches "Und" auszudrücken. Der Operator || drückt ein logisches "Oder" aus. Der Operator ! stellt ein logisches "Nicht" dar, kehrt also einen Wahrheitswert um.

Aufgabe 7 - Spielende

Welche der dargestellten Ausdrücke passen, um die bisherige Bedingung runden < 5 in der Methode spielSteuern gemäß der oben formulierten Gewinnregel zu ersetzen?

runden < 10 && !(punkte1 >= 5 && punkte2 >= 5)
(runden < 10 && !(punkte1 >= 5)) && (runden < 10 && !(punkte2 >= 5))
(runden < 10 && !(punkte1 >= 5)) || (runden < 10 && !(punkte2 >= 5))
runden < 10 && !(punkte1 >= 5 || punkte2 >= 5)
runden < 10 && punkte1 < 5 && punkte2 < 5

Passe Dein Programm entsprechend an und teste das Spiel.

Aufgabe 8 - Erste Anpassungen

Das Spiel ist nun in der ersten Version fertig und spielbar. Ändere erste Details, indem Du z.B. die Ausgabe Deinen Wünschen anpasst oder den Zahlenbereich der Aufgaben änderst.

Optional: Überlege, welche Elemente public oder private sein sollten und ändere den Code entsprechend ab.

Suche

v
7.1.2.1.1
inf-schule.de/oop/java/implementierung/superbrain/implementierung
inf-schule.de/7.1.2.1.1
inf-schule.de/@/page/2O7Gm6uoITQZYyHP

Rückmeldung geben