Skip to main content

Java Übung 26 – Das erste kleine Java Spiel

In dieser Java Übung geht es darum ein kleines Java-Spiel zu erstellen.
Und zwar Zahlen raten.

Was kannst du dir darunter vorstellen?
Du gibst einen bestimmten Wertebereich an.
Zum Beispiel 0 bis 100.

Und das Java Programm erstellt eine Zufallszahl in diesem Bereich.
Dann fordert dich das Programm auf, die Zahl zu raten.

Du gibst deine Rateversuche in die Konsole ein.
Und nach jedem Versuch sagt das Programm, ob die Zahl richtig oder falsch ist.

Außerdem soll dir das Programm eine Hilfe geben.
Es sagt dir, ob die zu erratende Zahl größer oder kleiner, als dein Rateversuch ist.

Am Ende, wenn du die Zahl erraten hast, bekommst du die Anzahl deiner Versuche mitgeteilt.

Na Interesse, an so einem Spiel?
Na dann…

  • Erstelle eine Klasse „ZahlenRaten“.
  • Lege in dieser Klasse eine statische Methode „rateZahl“ an.
    Diese Methode bekommt beim Aufruf eine ganze Zahl übergeben.
    Und diese ganze Zahl ist der Wertebereich für die Zufallszahl.
  • Und dann fordert dich die Methode auf Zahlen zu raten.
  • Nach jedem Versuch bekommst du Hilfe.
    Wenn dein Versuch größer ist, als die Zufallszahl dann erfolgt die Bildschirmausgabe:
    „Du liegst falsch! Die zu erratende Zahl ist kleiner“
    Ansonsten
    „Du liegst falsch! Die zu erratende Zahl ist größer“
  • Nachdem du irgendwann die richtige Zahl erraten hast, erfolgt die Konsolenausgabe:
    „Richtig! Du hast „+zaehler+“ Durchgänge benötigt.“
  • Und der „zaehler“ ist die Variable, welche deine Rateversuche zählt.
  • Die Methode wird in der main-Methode der Klasse „ZahlenRaten“ aufgerufen.
    Aus Kontrollzwecken übergebe der Methode das Argument 100. (Wertebereich für Zufallszahl)

Also dann – leg los.
Ich wünsche dir ganz viel Spaß bei der Lösung dieser Java Übung.


Die Lösung dieser Java Übung vollziehe ich in drei Schritten.

Am besten ist….
Du löst diese Übung schrittweise.

Dazu suchst du dir die einzelnen Probleme heraus und beginnst diese nach und nach zu lösen.
Zu jeder Lösung eines Problems lässt du dir, eine Bildschirmausgabe zur Überprüfung zurückgeben.

Das wären die drei Probleme.

  • Problem 1:
    Die Klasse, die Methoden, die Variablen und Zufallszahl müssen erstellt werden.
    Die Zufallszahl soll ganzzahlig sein.
    Mittels einer Konsolenausgabe soll die Zufallszahl überprüft werden.
  • Problem 2:
    Es muss eine Struktur geschaffen werden, welche den Nutzer auffordert, Zahlen einzugeben.
    Diese Zahlen sollen mit der Zufallszahl verglichen werden.
    Die Anzahl der Rateversuche soll gezählt werden.
    Auch das soll als Konsolenausgabe zurückgegeben werden.
  • Problem 3:
    Die Hilfestellung „Die Zahl ist größer oder kleiner“ soll implementiert werden.

So und jetzt beginnen wir die Probleme zu lösen.

So kannst du eine ganzzahlige Zufallszahl anlegen.

Was benötigst du?
Als erstes brauchst du die Klasse.

Dann benötigst du eine statische Methode „rateZahl“, welche einen Parameter vom Datentyp Integer erwartet.

Weiterhin brauchst du eine lokale Variable, welche die ganzzahlige Zufallszahl speichert.
Die Zufallszahl soll in einem gewissen Wertebereich liegen.
Dazu musst du also den Methodenparameter mit der Zufallszahl verrechnen.

Hier der Javacode dazu:
In der main-Methode wird die rateZahl-Methode mit dem Argument 100 aufgerufen.


public class ZahlenRaten {

public static void main(String[] args) {
	rateZahl(100);
}
}

Somit wurde der Wert 100 für die lokale Variable „wertebereich“ festgelegt.
Innerhalb der rateZahl-Methode wurde jetzt eine weitere lokale Variable, namens „zufallsZahl“ angelegt.


public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl;	
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Diese Variable ist vom Datentyp Integer.
Es handelt sich somit um eine ganze Zahl.

Bisher steckt in dieser Variablen aber noch kein Wert.
Da soll jetzt die Zufallszahl rein.
Und Zufallszahlen kannst du mit der Methode Math.Random() erzeugen.
Die Math.Random-Methode ist eine Klassenmethode aus der Standardklasse Math.
Diese Methode liefert dir einen zufälligen Komma-Wert zwischen 0 und 1.


public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl = Math.random();	
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Dann wird dieser Kommawert mit der Variablen „wertebereich“ multiplziert.

Beim Aufruf der Methode „rateZahl“ (in der main-Methode) haben wir für den „wertebereich“ die Zahl 100 festgelegt.
Und wenn eine Kommazahl zwischen 0 und 1 mit 100 multipliziert wird, entsteht eine Kommazahl zwischen 0 und 100.
Somit hast du eine zufällige Kommazahl zwischen 0 und 100.


public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl = ( Math.random()*wertebereich);
		
		}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Und diese Kommazahl wird in einen Integer-Wert gewandelt.
Am Ende steckt jetzt in der Variablen „zufallszahl“ eine zufällige ganzzahlige Zahl zwischen 0 und 100.


public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl = (int)( Math.random()*wertebereich);
			
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Und aus Testzwecken lasse ich mir dies, über die System.out.println()-Anweisung auf der Konsole ausgeben.


public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl = (int)( Math.random()*wertebereich);
		
		System.out.println(zufallsZahl);//Zur Überprüfung die Rückgabe der Zufallszahl	
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Probiere es an dieser Stelle ebenfalls und führe das Programm einmal aus.

Und welche Konsolenausgabe erscheint?
Eine Zahl zwischen 0 und 100, oder?

Okay…
Dann können wir uns um das Raten kümmern.

So kannst du die einzelnen Rateversuche darstellen.

Der jeweilige Rateversuch soll über eine Nutzereingabe erfolgen.

Du brauchst also ein Scanner-Objekt, um die Nutzereingabe zu speichern.
Scanner scanner = new Scanner(System.in);

Da die Zahl, welche du eingibst ebenfalls ganzzahlig ist, musst du diese in einer Integer-Variablen speichern.
Dazu rufst du die Methode nextInt() am Scanner-Objekt auf.
int eingabe = scanner.nextInt();

Und du benötigst eine Aufforderung zur Eingabe deines Rateversuches.
System.out.println("Gib eine Zahl zwischen 0 und "+wertebereich+" ein!");

Also bis hierher sieht der Code so aus:


import java.util.Scanner;//Importanweisung für den Scanner

public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl = (int)( Math.random()*wertebereich); //Zufallszahl
		
		System.out.println(zufallsZahl); //Aus Kontrollzwecken
		Scanner scanner = new Scanner(System.in); //Scanner-Objekt
		
		System.out.println("Gib eine Zahl zwischen 0 und "+wertebereich+" ein!");
		int eingabe = scanner.nextInt();//Eingabe wird gespeichert
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Bis hierher hast du die Grundstruktur dafür gelegt, eine Zufallzahl zu erzeugen und einen Rateversuch zu speichern.
Mehr nicht.

Kommen wir zum Raten.
Du sollst solange aufgefordert werden weiter zu raten, bis die Zahl in der Variable „eingabe“ mit der Zahl in der Variable „zufallszahl“ übereinstimmt.
Da du nicht weißt, wie oft du raten musst – ist die for-Schleife hier unpraktisch.

Viel besser ist für dieses Beispiel eine while-Schleife.
Und die Schleifenbedingung lautet:

„Rate solange bis der Wert in der Variablen „eingabe“ gleich ist dem Wert in der Variablen „zufallszahl“.

Oder anders gesagt:

„Solange sich beide Werte unterscheiden – rate weiter.

Somit lautet die Schleifenbedingung:
(zufallsZahl != eingabe)

Immer dann, wenn die Eingabe nicht mit der Zufallszahl übereinstimmt- geht es in die Schleife.

Und was passiert in der Schleife:
Erst einmal erfolgt eine Info, dass die Eingabe falsch war.
System.out.println("Du liegst falsch!");

Dann muss eine neue Eingabe erfolgen.
eingabe = scanner.nextInt();

Also würde das Ganze bis hierhin so aussehen:


import java.util.Scanner;//Importanweisung für die Scanner-Klasse

public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl = (int)( Math.random()*wertebereich);//Zufallszahl
		
		System.out.println(zufallsZahl); //Aus Kontrollzwecken
		Scanner scanner = new Scanner(System.in);//neues Scanner Objekt
		
		System.out.println("Gib eine Zahl zwischen 0 und "+wertebereich+" ein!");
		int eingabe = scanner.nextInt();//Eingabe wird gespeichert
		
		while (zufallsZahl != eingabe){
			System.out.println("Du liegst falsch!");//Rückinfo
			eingabe = scanner.nextInt();//neue Eingabe
			
		}//Schleifenende
		System.out.println("Richtig!");//Falls Eingabe richtig
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

An dieser Stelle macht es Sinn, das Ganze auszuprobieren.
Führe das Programm deshalb einmal aus.
Gib einmal die richtige Zahl ein und schau was passiert.

Und im zweiten Versuch nimmst du eine falsche Zahl.

Und? Läuft’s?
Also dann weiter..

Bis jetzt fehlt noch die Eingabe welche die Anzahl der Versuche speichert.

  • Also ein Zähler.
  • Der Zähler startet bei eins.
    Denn der Erste Rateversuch zählt schon mit.

Also wenn der erste Versuch komplett richtig ist- das Programm nicht in die Schleife springt – bleibt es bei einem Versuch.
int zaehler=1;

Und bei jedem Schleifendurchlauf wird der Zähler dann um eins erhöht.
zaehler++;

Bevor wir als letzten Schritt die Hilfestellung implementieren.
Hier der komplette Code.


import java.util.Scanner;

public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl = (int)( Math.random()*wertebereich);
		
		System.out.println(zufallsZahl);
		Scanner scanner = new Scanner(System.in);
		
		System.out.println("Gib eine Zahl zwischen 0 und "+wertebereich+" ein!");
		int eingabe = scanner.nextInt();
		int zaehler=1;//Zähler startet bei eins
		
		while (zufallsZahl != eingabe){
			System.out.println("Du liegst falsch!");
			eingabe = scanner.nextInt();
			zaehler++;//Zähler wird bei jedem Durchlauf um eins erhöht
			
		}
		System.out.println("Richtig! Du hast "+zaehler+" Durchgänge benötigt.");//Anzahl der Durchgänge
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Probiere es wieder aus.
Gib verschiedene Zahlen ein und lass den Zähler zählen.

Jetzt kommt die Hilfestellung.

So kannst du die Hilfestellung implementieren.

Für die Hilfestellung musst du Werte abfangen.

Und Werte fängst du mit if und else Blöcken ab.
Somit könnte die Anweisung im if Block lauten:

„Wenn die Zufallszahl kleiner als die Eingabe ist- Dann erscheint die Konsolenausgabe:
Du liegst falsch! Die zu erratende Zahl ist kleiner“

Die Bedingung für den if-Block würde somit lauten:
(zufallsZahl < eingabe)

Und im Falle, dass die Eingabe kleiner ist - muss lediglich die Bildschirmanweisung angepasst werden.

Der komplette Code zu dieser Java Übung:


import java.util.Scanner;//Importanweisung für die Scanner Klasse

public class ZahlenRaten {

	static void rateZahl(int wertebereich){		
		int zufallsZahl = (int)( Math.random()*wertebereich);//Zufallszahl wird gespeichert
		
		System.out.println(zufallsZahl); //Aus Kontrollzwecken - kann jetzt gelöscht werden
		Scanner scanner = new Scanner(System.in);//neues Scanner-Objekt
		
		System.out.println("Gib eine Zahl zwischen 0 und "+wertebereich+" ein!");
		int eingabe = scanner.nextInt();//Speicherung des ersten Rateversuchs
		int zaehler=1;//Zählvariable um die Rateversuche zu zählen
		
		while (zufallsZahl != eingabe){
			if (zufallsZahl<eingabe){
			System.out.println("Du liegst falsch! Die zu erratende Zahl ist kleiner");
			}
			else {
				System.out.println("Du liegst falsch! Die zu erratende Zahl ist größer");
			}
			eingabe = scanner.nextInt();//neuer Rateversuch
			zaehler++;//Rateversuch wird um eins erhöht
			
		}
		System.out.println("Richtig! Du hast "+zaehler+" Durchgänge benötigt.");
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Das Programm wäre fertig.
Die Anweisung zur Konsolenausgabe der Zufallszahl kannst du einfach löschen.
Dann funktioniert das Spiel auch ohne Vorsagen. 🙂

Ein kleines, vielleicht mittelgroßes Problem bleibt.
Und zwar doppelter Code.
Schau dir diese Bild dazu einmal an.

Java Übung doppelter Code

Die Anweisung für die nächste Bildschirmeingabe findest du in der Schleife.
int eingabe = scanner.nextInt();
Aber genau die gleiche Anweisung befindet sich auch außerhalb der Schleife.

Wenn du später in diesem Programm Dinge ändern willst, musst du es an zwei Stellen machen.
Ein Grundsatz der Programmierung lautet:

"Vermeide doppelten Code!"

Denn doppelter Code führt später zu doppelter Nachbesserung.
Und wenn du an zwei oder mehr Stellen nachbessern musst- führt dies zu Fehlern.
Bzw. das Risiko, dass du an einer Stelle Codeanteile änderst - an der anderen nicht - steigt.

Also dann…
Das Problem bei diesem Programm ist, dass du immer mindestens einen Rateversuch benötigst.

Egal was kommt - Mindestens einmal musst du raten.
Deshalb musste auch der Schleifenzähler bei eins starten und nicht bei null.

Wenn du mindestens einen Rateversuch benötigst, ist eine do-while Schleife besser.

Und zwar beginnt so eine do-while-Schleife mit dem Keyword do.

Dann kommt ein Codeblock.
Und in diesen Codeblock kommen dann die Schleifenanweisungen, wie

  • If und else Blöcke
  • Die Infos
  • Das Hochzählen des Schleifenzählers
  • Die neue Eingabe

Also all das, was du bereits in der while-Schleife im Rumpf hast.
Der Do-Block ist somit der Rumpf.

Im Do-Block musst du dann allerdings alle drei Bedingungen festlegen:

  1. Zufallszahl < Eingabe
  2. Zufallszahl > Eingabe
  3. Und Zufallszahl = Eingabe

do {
			if (zufallsZahl == eingabe) {
				System.out.println("Richtig! Du hast " + zaehler + " Durchgänge benötigt.");
			} else if (zufallsZahl < eingabe) {
				System.out.println("Du liegst falsch! Die zu erratende Zahl ist kleiner");
			} else {
				System.out.println("Du liegst falsch! Die zu erratende Zahl ist größer");
			}
}

Was bringt es?
Der Unterschied besteht darin, dass die Schleifenbedingung nicht im Kopf steht.
Stattdessen steht diese im Rumpf.

Das wiederum führt dazu, dass die Schleife immer mindestens einmal durchlaufen wird.
Somit kann auch der Schleifenzähler bei null starten.

So würde die Lösung dieser Java Übung mit do while Schleife aussehen:


import java.util.Scanner;

public class ZahlenRaten {

	static void rateZahl(int wertebereich) {
		int zufallsZahl = (int) (Math.random() * wertebereich);

		System.out.println(zufallsZahl); // Aus Kontrollzwecken
		Scanner scanner = new Scanner(System.in);

		//System.out.println("Gib eine Zahl zwischen 0 und "+wertebereich+" ein!");
		int eingabe = 0;//Eingabe startet jetzt bei Null
		int zaehler = 0;// Startet bei Null

		do {
			System.out.println("Gib eine Zahl zwischen 0 und " + wertebereich + " ein!");
			eingabe = scanner.nextInt();
			zaehler++;
			if (zufallsZahl == eingabe) {
				System.out.println("Richtig! Du hast " + zaehler + " Durchgänge benötigt.");
			} else if (zufallsZahl < eingabe) {
				System.out.println("Du liegst falsch! Die zu erratende Zahl ist kleiner");
			} else {
				System.out.println("Du liegst falsch! Die zu erratende Zahl ist größer");
			}
		} 
               while (zufallsZahl != eingabe);//Schleifenbedingung im Fuß
	}

	public static void main(String[] args) {
		rateZahl(100);
	}
}

Die fett markierten Anteile sind jetzt alle neu.
Der Schleifenzähler kann bei Null starten, da ja mindestens ein Schleifendurchlauf stattfindet.

Die Aufforderung zur Eingabe einer Zahl kann raus.
Diese habe ich in diesem Beispiel auskommentiert.

Die Eingabe findet jetzt auch nicht mehr außerhalb der Schleife statt.
Da die Variable dennoch eine lokale ist, muss diese einen Wert (0) haben.

So das war es.

Also immer wenn du feststellst:

"Ich muss im Rumpf der Schleife Code schreiben, welchen ich außerhalb der Schleife schon einmal geschrieben habe".

Dann solltest du überlegen:

"Ist es notwendig, dass die Schleife mindestens einmal durchlaufen werden muss?"

Wenn du diese Frage mit Ja beantwortest - dann wähle statt der while Schleife eine do while Schleife.


Ähnliche Beiträge

So kannst du mit dem StringTokenizer Java Strings zerlegen oder splitten

Java StringTokenizer Java Strings teilen zerlegen splitten

Java StringTokenizer – was ist das? Bevor ich diese Frage kläre, schiebe ich eine zweite Frage hinterher. Denn im Wort Tokenizer steckt das Wort Token. Also was ist ein Token? Hier die Definition zum Token: Ein Token ist eine bestimmte Aneinanderreihung von Zeichen. Man kann auch sagen, eine lexikalische Einheit. Das kann zum Beispiel eine […]

So verwendest du den Java Oder Operator

Java Oder Operator

Kennst du das auch aus deiner Schulzeit? Du schreibst eine Klassenarbeit in irgendeinem Fach. Nehmen wir einfach mal an – Mathe. Jetzt bist gerade fertig mit deiner Arbeit. Und zu Hause wirst du gefragt: „Und wie lief es?“ Du antwortet:“ Ganz gut. Es wird bestimmt eine Eins oder eine Zwei.“ Drei oder vier Tage später […]

So richtest du einen Schreibschutz für deine Java Variablen ein

Stell dir vor: Du hast erfolgreich dein erstes Programm für die Personalabteilung aufgesetzt. Du hast deine ersten 1000 Datensätze schön sauber angelegt. Und nun kommt dein Kollege und überschreibt die Vornamen der ersten 100 Mitarbeitern. Na schöne Sch…. 🙂 Wie kann das passieren? Wie kann man das verhindern? Du brauchst eigentlich nur deine Java Variablen […]

So kannst du in Java Und Verknüpfung anlegen und auswerten

Java Und

In Java stehen dir eine Menge Operatoren zur Verfügung. Einer dieser Operatoren ist der Und-Operator. Dies ist ein logischer Operator, da dieser sogenannte Wahrheitswerte mit einander verknüpft. Also…. Was erwartet dich in diesem Beitrag? Zuerst möchte ich dir die Aussagenlogik hinter dem Und-Operator zeigen. Also wann sind Aussagen wahr und wann sind diese falsch. Dann […]

Der Aufbau von Java Klassen

Java Klassen Aufbau

Jedes Java Programm besteht aus Java Klassen. Doch wie sind diese aufgebaut? Wie setzt sich die Struktur zusammen? Wo befinden sich Klassen hierarchisch? Was kommt in die Klassen rein und wie wird es integriert? Das sind die Fragen, welche ich in diesem Artikel beantworten werde. Doch bevor wir bei den Klassen ansetzen, müssen wir eine […]

So kannst du dein Java Programm mit der main Methode ausführen

Auf zum ersten Java Programm. Vielleicht fragst du dich jetzt gerade: Na, was haben wir denn bisher gemacht? War das etwa kein Java Programm? Wir haben bisher nur eine Klasse „Human“ für ein zuküntfiges Mensch-Objekt erstellt. Diesem Objekt haben wir eine Instanzvariable, namens size (Größe) zugeordnet. Und wir haben eine Instanzmethode, namens grow (wachsen) geschrieben. […]

Java Polymorphie – besserer Code und mehr Möglichkeiten

Java Polymorphie Vorteile

Polymorphie ist das Herzstück jeder objektorientierten Sprache. Nicht nur in Java – auch in Python, Javascript und in anderen Sprachen. Aber was bedeutet Polymorphie eigentlich? Polymorphie oder auch Polymorphismus genannt, kommt aus dem Griechischen. Es bedeutet Vielgestaltigkeit. Etwas freier übersetzt, kannst du es auch als Facettenreichtum bezeichnen. Im Grunde genommen zielt die ganze Java Vererbung […]

Du bekommst was du vereinbarst – Die Rückgabewerte von Java Methoden

Java Methoden Rückgabetypen

Was du vereinbarst, das bekommst du zurück. Ach wäre es schön, wenn alles im Leben so funktionieren würde. Aber zum Glück funktioniert dieses Prinzip bei deinen Java Methoden. Denn du kannst den Rückgabetypen im Methodenkopf vereinbaren. Doch bevor ich dir zeige, wie du den Rückgabetypen anlegen kannst…. Lass mich dir zeigen, wofür du den Kram […]

So nutzt du Methoden aus der Java String Klasse

Java Strings Methoden

In einen der letzten Beiträge haben wir darüber gesprochen, dass Java Strings – Objekte sind. Dass Strings in allen Programmen äußerst häufig vorkommen Und dass sich deshalb Referenzvariablen String-Objekte im String Pool teilen. Das Konzept hinter dem String-Pool ist die Teilung der Ressourcen. Und das bedeutet: Weniger Objekte – mehr Speicher Mehr Speicher – bessere […]

Nutze das Java Switch Case Statement für komplexe Verzweigungen

Java Switch case

Java switch case statement – was ist das? Wozu brauchst du das? Lass mich anders beginnen… 🙂 In einen meiner früheren Beiträge habe ich schon einmal über bedingte Anweisungen oder Zuweisungen geschrieben. Diese if und else Konstrukte funktionieren eigentlich ganz gut. Aber was ist, wenn du mehrere Parameter abfangen möchtest. Okay ein Beispiel…