String wird nicht erkannt, cannot find symbol

Hallöchen,
Ich bin relativ neu in der Welt von Java und habe einProblem in einem Progrämmchen, das mich eine zufällige Zahl erraten lässt und mir nach jedem Versuch sagt ob die tatsächliche Zahl höher oder niedriger ist als mein Vorschlag. Ich versuche es mithilfe einer while-do Schleife. Jetzt erkennt mein Compiler aber in Zeile 27 den String c nicht als solchen sondern sagt mir stattdessen “error: cannot find symbol”

	
	public static void main(String[] args) throws IOException{
		
		int z;
		
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		
		System.out.println("Hi-Lo Game");
		System.out.println();
		System.out.println();
	
		System.out.println("Ich denke mir eine Zahl zwischen 1 und 100");
		System.out.println("Errate sie!");
		
		z = (int)(Math.random()*100+1);

		do {
			String geraten = br.readLine();
			int c = Integer.parseInt(geraten);
			if ( c < z ) {
				System.out.println("hoeher");
			} else if ( c > z ) {
				System.out.println("niedriger");
			}
		} while( c != z );
		
		System.out.println("Richtig! Du hast gewonnen!!!");
	
	}

}

unten bei dem while( c != z );

Schon mal danke :).

Ach so hab ich vergessen ich hab natürlich java.io.* importiert, daran liegts schonmal nicht :smiley:

int c ist im do-Block deklariert und nur dort sichtbar. das musst du vor dem do-Block machen. Am besten oben bei int z mit dazuschreiben. Also int c, z; Und dann unten in der do-Schleife nur:
c = Integer.parseInt(geraten);

also etwa so:

import java.io.IOException;
import java.io.InputStreamReader;

public class HiLoGame {        
	public static void main(String[] args) throws IOException{
		int z;                
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		System.out.println("Hi-Lo Game");
		System.out.println();
		System.out.println();
		System.out.println("Ich denke mir eine Zahl zwischen 1 und 100");
		System.out.println("Errate sie!");
		z = (int)(Math.random()*100+1);
		int c=0;
		do {
			String geraten = br.readLine();
		    c = Integer.parseInt(geraten);
			if ( c < z ) {
				System.out.println("hoeher");
				} else if ( c > z ) {
					System.out.println("niedriger");
					}
			} while( c != z );
		System.out.println("Richtig! Du hast gewonnen!!!");
		}
	}```

Yes sir!

[QUOTE=pappawinni]also etwa so:[/QUOTE]Das sieht schon sehr gut aus.

aber…
Hier sind noch ein paar Vorschläge, worauf ich beim Programmieren achte:

Variablen sollen mit der kleinst möglichen Sichtbarkeit deklariert und möglichst auch sofort initialisiert werden.
In Deinem Fall bedeutet das, die Variable z erst in Zeile 15 zu deklarieren und zwar so:int z = (int)(Math.random()*100+1);
Außerdem soll man bei den Namen kreativ sein (solange man keine gängigen Abkürzungen verwendet)
Die Variablen sollten also nicht c und z sondern zuRaten und eingabe heißen.
Das Problem, dass es jetzt 2 Variablen mit dem selben Namen (eingabe) gibt umgehst Du, indem Du das Anfordern der geratenen Zahl und deren Umwandlung in einen int in eine eigenen Methode auslagerst:```public class HiLoGame {
public static void main(String[] args) throws IOException {
System.out.println(“Hi-Lo Game”);
System.out.println();
System.out.println();
System.out.println(“Ich denke mir eine Zahl zwischen 1 und 100”);
System.out.println(“Errate sie!”);
int zuRaten = (int) (Math.random() * 100 + 1);
int eingabe = 0;
do {
eingabe = benutzerRaet();
if (eingabe < zuRaten) {
System.out.println(“hoeher”);
} else if (eingabe > zuRaten) {
System.out.println(“niedriger”);
}
} while (eingabe != zuRaten);
System.out.println(“Richtig! Du hast gewonnen!!!”);
}

private static int benutzerRaet() throws IOException {
	InputStreamReader isr = new InputStreamReader(System.in);
	BufferedReader br = new BufferedReader(isr);
	String geraten = br.readLine();
	return Integer.parseInt(geraten);
}

}Ich würde jetzt noch versuchen die fußgesteuerte Schleife los zu werden. Dazu muss man aber wissen, dass man in Java auch Zuweisungen ein "Ergebnis" haben, dass man sofort weiter verarbeiten kann. Man kann also beispielsweise den Rückgabewert einer Methode einer Variablen zuweisen und ihn gleichzeitig mit einem anderen Wert vergleichen. Dann würde das `while` so aussehen: // Vorsicht: ohne extra Klammern kompiliert das while auch, dann ist aber die Reihenfolge wichtig!!!
while (zuRaten != (eingabe = benutzerRaet())) {
if (eingabe < zuRaten) {
System.out.println(“hoeher”);
} else if (eingabe > zuRaten) {
System.out.println(“niedriger”);
}
}
System.out.println(“Richtig! Du hast gewonnen!!!”);Der nächste Schritt wäre dann die Zeilen 3 bis 7 sowie die Zeilen 12 bis 16 in je eine eigene Methode mit einem passenden Namen auszulagen. Wegen dem **Single Abstraction Layer**-Prinzip würde ich dann auch noch die einzelne Zeile 8 (die dann Zeile 4 wäre) in eine eigenen Methode auslagern, aber da könnte man argumentieren, dass sich dass hier mit dem **KISS**-Prinzip beißt, welchen im Zweifel immer gewinnt. Jedenfalls sähe das dann so aus:public class HiLoGame {
public static void main(String[] args) throws IOException {
anleitungAusgeben();
int zuRaten = ratezahlBerechnen();
benutzerRatenLassen(zuRaten);
}

private static void anleitungAusgeben() {
	System.out.println("Hi-Lo Game");
	System.out.println();
	System.out.println();
	System.out.println("Ich denke mir eine Zahl zwischen 1 und 100");
	System.out.println("Errate sie!");
}

private static int ratezahlBerechnen() {
	return (int) (Math.random() * 100 + 1);
}

private static void benutzerRatenLassen(int zuRaten) throws IOException {
	int eingabe = 0;
	while (zuRaten != (eingabe = benutzerRaet())) {
		hinweisAusgeben(zuRaten, eingabe);
	}
	System.out.println("Richtig! Du hast gewonnen!!!");
}

private static int benutzerRaet() throws IOException {
	InputStreamReader isr = new InputStreamReader(System.in);
	BufferedReader br = new BufferedReader(isr);
	String geraten = br.readLine();
	return Integer.parseInt(geraten);
}

private static void hinweisAusgeben(int zuRaten, int eingabe) {
	if (eingabe < zuRaten) {
		System.out.println("hoeher");
	} else if (eingabe > zuRaten) {
		System.out.println("niedriger");
	}
}

}```Auf den ersten Blick mag diese Umsetzung im Vergleich zu Deiner Lösung lang und “zerrissen” aussehen, aber es gibt einige entscheidende Vorteile:[ol]
[li]In der main-Methode steht eine Prosa-Beschreibung was gemacht wird ohne einen Kommentar zu benötigen.
[/li][li]In jeder Methode gibt es nur wenige Anweisungen die nur eine Aufgabe erfüllen und die sehr genau durch den Methodennamen beschrieben ist.
[/li][li]Da die einzelnen Methoden nur wenige Anweisungen haben kann man sie sehr leicht analysieren.
[/li][li]Da die einzelnen Methoden nur wenige Anweisungen haben können auch nur wenige Fehler darin sein.
[/li][/ol]

bye
TT

Da würde ich aber einiges anders machen:

import java.util.InputMismatchException;
import java.util.Random;
import java.util.Scanner;

public class HiLoGame {

    private static final Scanner scanner = new Scanner(System.in);

    private final int zuRaten = new Random().nextInt(100) + 1;
    private boolean gefunden = false;

    public HiLoGame() {
        System.out.println("Hi-Lo Game

Ich denke mir eine Zahl zwischen 1 und 100
Errate sie!");
    }

    public boolean wurdeGefunden() {
        return gefunden;
    }

    private void lassRaten() {
        int eingabe = benutzerRaet();
        hinweisAusgeben(eingabe);
        if (eingabe == zuRaten) {
            gefunden = true;
        }
    }

    private static int benutzerRaet() {
        while(true) {
          try {
             return scanner.nextInt();
          } catch (InputMismatchException ex) {
              System.out.println("Bitte geben sie eine Zahl ein!");
              scanner.next(); //falsche Eingabe aus Scanner entfernen
          }
        }
    }

    private void hinweisAusgeben(int eingabe) {
        if (eingabe != zuRaten)
        System.out.println(eingabe < zuRaten ? "hoeher" : "niedriger");
    }

    public static void main(String[] args) {
        HiLoGame game = new HiLoGame();
        while(! game.wurdeGefunden()) {
            game.lassRaten();
        }
        System.out.println("Richtig! Du hast gewonnen!!!");
    }
}

Gibt es einen konkreten Grund, weshalb lassRaten() nicht direkt einen boolean zurückgibt?
Dann wäre die wurdeGefunden()-Methode überflüssig.

Edit: erklärt sich eigentlich von selbst - das verschlechtert die Lesbarkeit des Codes. Denn den Rückgabewert würde man bei dem Methodennamen nicht erwarten.

Stimmt, könnte man so machen. Die while-Schleife in main sähe dann zwar etwas degeneriert aus, aber das wäre sicher vertretbar. Oder ist dann vielleicht for besser?

import java.util.InputMismatchException;
import java.util.Random;
import java.util.Scanner;

public class HiLoGame {

    private static final Scanner scanner = new Scanner(System.in);

    private final int zuRaten = new Random().nextInt(100) + 1;

    public HiLoGame() {
        System.out.println("Hi-Lo Game

Ich denke mir eine Zahl zwischen 1 und 100
Errate sie!");
    }

    private boolean hatRichtigGeraten() {
        int eingabe = benutzerRaet();
        hinweisAusgeben(eingabe);
        return eingabe == zuRaten;
    }

    private static int benutzerRaet() {
        while(true) {
          try {
             return scanner.nextInt();
          } catch (InputMismatchException ex) {
              System.out.println("Bitte geben sie eine Zahl ein!");
              scanner.next(); //falsche Eingabe aus Scanner entfernen
          }
        }
    }

    private void hinweisAusgeben(int eingabe) {
        if (eingabe != zuRaten)
        System.out.println(eingabe < zuRaten ? "hoeher" : "niedriger");
    }

    public static void main(String[] args) {
        for(HiLoGame game = new HiLoGame(); ! game.hatRichtigGeraten(); )
            ;
        System.out.println("Richtig! Du hast gewonnen!!!");
    }
}

Übrigens habe ich mit für leere Schleifenkörper das eingerückte Semikolon auf der nächsten Zeile angewöhnt, das so ziemlich deutlich ausdrückt, dass das “so gewollt” ist. Das while(true) kann man auch als for(;;) schreiben. Ich nenne das “Vampir-for” (betrachtet die Klammern mal als Smiley)