Erste Schritte Scanner eingabe wird übersprungen

xant95

Mitglied
Hallo ich mache momentan den Kurs der Jetbrains Academy und mache ein TicTacToe Spiel..
-> Beispiel

Ich habe das Problem dass ich bei Zeile 11 nichts eingeben kann, er überspringt die eingabe aus irgendeinem Grund und macht mit der Schleife weiter.


Java:
public static void nextMove() {
    Scanner scanner = new Scanner(System.in);
    int row = 0;
    int col = 0;

    do {    // ENTER ROW
        try {   // CHECK INPUT TYPE
            System.out.println("Enter the coordinates: ");
            row = scanner.nextInt();
            col = scanner.nextInt();

            // INPUT OUT OF BOARD
            if (row > 3 || row < 1 || col > 3 || col < 1) {
                System.out.println("Coordinates should be from 1 to 3!");

                // CELL IS OCCUPIED
            } else if (board[row][col] == 'X' || board[row][col] == 'O') {
                System.out.println("This cell is occupied! Choose another one!");

            } else {
                return;
            }
        }catch (NoSuchElementException e) {
            System.err.println("You should enter numbers!");
        }
    } while (true);
}
 
Zuletzt bearbeitet:
Ich habe das Problem dass ich bei Zeile 11 nichts eingeben kann, er überspringt die eingabe aus irgendeinem Grund und macht mit der Schleife weiter.
Probiere es so ..
Java:
import java.awt.Point;
import java.util.Scanner;

public class InputCoordinates {
    private static Scanner input = new Scanner(System.in);

    public static void main(String[] args) {
        System.out.print(inputCoordinates(1, 3));
    }

    public static Point inputCoordinates(int min, int max) {
        Point pos = new Point();
        System.out.println("Enter the coordinates: ");
        pos.y = inputInt("Zeile", min, max);
        pos.x = inputInt("Spalte", min, max);
        return pos;
    }

    public static int inputInt(String label, int min, int max) {
        boolean ok = false;
        int value = 0;
        do {
            try {
                System.out.print(label + " >");
                value = Integer.parseInt(input.next());
                if (value < min || value > max)
                    System.out.println("Bitte nur Werte im Bereich von (" + min + "-" + max + ") eingeben!");
                else
                    ok = true;
            } catch (NumberFormatException e) {
                System.out.println("Bitte nur ganze Zahlen eingeben!");
            }
        } while (!ok);
        return value;
    }
}
 
Das Problem ist beim Scanner oft, dass verschiedene Eingabemöglichkeiten gemischt werden. Denn Scanner hat zwei Arten von Eingaben:

a) Tokenbasierte Eingaben
Bei Tokenbasierte Eingaben wird geschaut, ob es ein Token gibt, das abgefragt wird. Dazu werden erst alle Trennzeichen (per Default sind dann sogenannte Whitespace Zeichen, also Leerzeichen, Tab, Zeilenumbruch, ...) übersprungen. Und dann werden die Zeichen bis zu dem nächsten Trennzeichen betrachtet. Passen diese zu dem angefragten Token, dann werden die Daten bis einschließlich des Token entfernt und das erste nächste Zeichen wäre dann das nächste Trennzeichen.
Beispiele sind next, nextInt, ....

b) Zeilenbasierte Eingabe
Bei nextLine wird alles, was noch da ist, bis zum nächsten Zeilenwechsel genommen und dann incl. dem Zeilenwechsel aus dem Eingabestrom entfernt.

Was passiert jetzt wenn Du Eingaben machst? Die Enter/Return Taste gebe ich mit \n an:

nextInt() wird aufgerufen: Du gibst eine Zahl ein und drückst Enter: 3\n (Eingabestrom war leer nehmen wir an):
Eingabestrom hat "3\n", Trennzeichen gibt es nicht, dann kommt 3 ... \n ist das nächste Trennzeichen.
-> 3 wird zurück gegeben und Eingabestrom hat noch "\n" (Das bleibt!)

nextInt() wird erneut aufgerufen: Du gibst eine Zahl ein und drückst Enter: 4\n:
Eingabestrom hat nun "\n4\n", Trennzeichen wird übersprungen, dann kommt 4 ... \n ist das nächste Trennzeichen.
-> 4 wird zurück gegeben und Eingabestrom hat noch "\n" (Das bleibt!)

nextLine() wird aufgerufen. Es wird geschaut: Habe ich schon einen Zeilenumbruch? Und ja - der Eingabestrom hat den noch. Also wird alles vor dem \n zurück gegeben (Da ist nichts, also leerer String) und der Eingabestrom ist nun leer.

Lösungen:
1) Nur eine Variante nutzen. Also entweder Tokenbasiert oder Zeilenbasiert!
2) Nach der Tokenbasierten Eingabe den Zeilenumbruch entfernen. (Einfach ein nextLine aufrufen)
3) Das funktioniert hier aber ist keine gute Lösung. Bitte nicht machen! : Der Scanner hat auch einen internen Puffer. Aus dem Eingabestream wird also immer mehr gelesen (halt die ganze Zeile, ggf. sogar noch mehr). Somit könnte man immer einen neuen Scanner erzeugen.
 
Nimm BufferedReader
Oder einfach diese Klasse:

Java:
import java.util.Scanner;

public class Eingabemoeglichkeiten {
    private final Scanner scan = new Scanner(System.in);

    public String readNextLine() {
        return scan.nextLine();
    }

    public char readNextChar() throws NullPointerException {
        return readNextLine().charAt(0);
    }

    public int readNextInt() throws NumberFormatException {
        return Integer.parseInt(readNextLine());
    }

    public static void main(String[] args) {
        Eingabemoeglichkeiten eingabe = new Eingabemoeglichkeiten();
        System.out.println("Gib etwas ein:");
        System.out.println(eingabe.readNextLine());
        while (true) {
            try {
                System.out.println("Gib Zahl 1 ein:");
                System.out.println(eingabe.readNextInt());
                break;
            } catch (NumberFormatException ignore) {}
        }
        // Maximal 5 Versuche:
        for (int i = 0; i < 5; i++) {
            try {
                System.out.println("Gib Zahl 2 ein:");
                System.out.println(eingabe.readNextInt());
                break;
            } catch (NumberFormatException ignore) {}
        }
        System.out.println("Gib etwas ein:");
        System.out.println(eingabe.readNextLine());
    }
}
 

Neue Themen


Zurück
Oben