Игра TicTacToe для двух игроков в Java - Как предотвратить ввод нецелых чисел - PullRequest
0 голосов
/ 18 июня 2020

Так что моя игра TicTacToe кажется практически идеальной, если не считать того факта, что я не знаю, как предотвратить ввод нецелых чисел (символов или строк). Я хочу сделать так: «Это не число, попробуйте еще раз». всякий раз, когда через сканер вводится буква или символ. Вместо этого всякий раз, когда я пытаюсь это сделать, я просто получаю

Exception in thread "main" java.util.InputMismatchException
    at java.base/java.util.Scanner.throwFor(Scanner.java:939)
    at java.base/java.util.Scanner.next(Scanner.java:1594)
    at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
    at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
    at TicTactoe3.main(TicTactoe3.java:23)

. Также кажется, что java .util.InputMismatchException; никогда не используется, поэтому к блоку каким-то образом нельзя получить доступ. У меня есть это в инструкции try catch через некоторое время l oop, которая кажется практически недоступной, и я знаю, что это из-за того, что playerPos () отличается от playerPos, но я все еще не могу найти решение. Помещение try catch в основной метод тоже не работает, возвраты не могут использоваться в операторах void, а без него он просто ничего не делает.

Это весь мой код для справки. Я действительно не знаю, как исправить эту проблему, и любые ответы / советы будут оценены, хотя я бы предпочел не переписывать весь свой код.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.List;
// import java.util.Random;
import java.util.Scanner;

public class TicTactoe3 {
    
    static Scanner move = new Scanner(System.in);
    static ArrayList<Integer> playerPositions = new ArrayList<Integer>();
    static ArrayList<Integer> playerPositions2 = new ArrayList<Integer>();

    public static void main(String[] args) {
        
        char[][] gameBoard = {{' ', '|', ' ', '|', ' '}, 
                              {'-', '+', '-', '+', '-'}, 
                              {' ', '|', ' ', '|', ' '}, 
                              {'-', '+', '-', '+', '-'}, 
                              {' ', '|', ' ', '|', ' '}};
        
        printGameBoard(gameBoard);  
        int playerPos = move.nextInt();
        
        while(true) {
            

            System.out.println("Enter your move (1-9) player one ");
            while(playerPositions.contains(playerPos) || playerPositions2.contains(playerPos)) {
                System.out.println("Position taken");
                playerPos = move.nextInt();
            }

            while(playerPos >= 10 || playerPos <= 0) {
                System.out.println("Incorrect Input");
                playerPos = move.nextInt();
            }
            

            placePiece(gameBoard, playerPos, "player 1");
            printGameBoard(gameBoard);

            String result = checkWinner();
            if(result.length() > 0) {
                System.out.println(result);
                break;
            }
            
            if (Character.isLetter(playerPos)) {
                System.out.println("Invalid Input. Numbers 1-9 only!");
            }

            System.out.println("Enter your move (1-9) player two ");
            int playerPos2 = move.nextInt();
            while(playerPositions.contains(playerPos2) || playerPositions2.contains(playerPos2)) {
                System.out.println("Position taken");
                playerPos2 = move.nextInt();
            }

            while(playerPos2 >= 10 || playerPos2 <= 0) {
                System.out.println("Incorrect Input");
                playerPos2 = move.nextInt();
            }

            placePiece(gameBoard, playerPos2, "player 2");  
            printGameBoard(gameBoard);

            result = checkWinner();
            if(result.length() > 0) {
                System.out.println(result);
                break;
            }
        }   
    }
    
    
    public static int playerPos() { // This is where I try to prevent non-integer input but it doesn't do anything
                                    // That and it seems to regard playerPos() as different from playerPos but
                                    // simply using playerPos leads to other issues
        while (true) {
            try {
                return move.nextInt();
            }
            catch (InputMismatchException a) {
                move.next();
                System.out.println("That is not a number please try again.");
            }
        }
    } 
    
    public static void printGameBoard(char[][] gameBoard) {
        for(char[] row : gameBoard) {
            for(char c : row) {
                System.out.print(c);
            }
            System.out.println();
        }
    }
    
    public static void placePiece(char[][] gameBoard, int pos, String user) {
        
        char symbol = ' ';
        
        if(user.equals("player 1")) {
            symbol = 'X';
            playerPositions.add(pos);
        } else if(user.equals("player 2")) {
            symbol = 'O';
            playerPositions2.add(pos);
        }
        
        switch(pos) {
        case 1:
            gameBoard[0][0] = symbol;
            break;  
        case 2:
            gameBoard[0][2] = symbol;
            break;  
        case 3:
            gameBoard[0][4] = symbol;
            break;
        case 4:
            gameBoard[2][0] = symbol;
            break;
        case 5:
            gameBoard[2][2] = symbol;
            break;
        case 6:
            gameBoard[2][4] = symbol;
            break;
        case 7:
            gameBoard[4][0] = symbol;
            break;
        case 8:
            gameBoard[4][2] = symbol;
            break;
        case 9:
            gameBoard[4][4] = symbol;
            break;
        default:
            break;
        }
    }
    public static String checkWinner() {
        
        List topRow = Arrays.asList(1, 2, 3);
        List midRow = Arrays.asList(4, 5, 6);
        List botRow = Arrays.asList(7, 8, 9);
        List leftCol = Arrays.asList(1, 4, 7);
        List midCol = Arrays.asList(2, 5, 8);
        List rightCol = Arrays.asList(3, 6, 9);
        List cross1 = Arrays.asList(1, 5, 9);
        List cross2 = Arrays.asList(7, 5, 3);
        
        List<List> winning = new ArrayList<List>();
        winning.add(topRow);
        winning.add(midRow);
        winning.add(botRow);
        winning.add(leftCol);
        winning.add(midCol);
        winning.add(rightCol);
        winning.add(cross1);
        winning.add(cross2);
        
        for (List l : winning) {
            if(playerPositions.containsAll(l)) {
                return "Congrats, player 1 wins!";
            }
            else if(playerPositions2.containsAll(l)) {
                return "Congrats, player 2 wins";
            }
        }
        
        for (List l : winning) {
            if(playerPositions.size() + playerPositions2.size() == 9) {
                return "NOBODY WINS";
            }
        }
        
        return "";
    }
}

Изменить: я придумал частичное решение . Сначала я сделал так, чтобы playerPos и ​​playerPos2 начинались с нуля перед любым вводом игрока.

int playerPos = 0;
int playerPos2 = 0;

Затем я написал простой оператор try and catch, но я не могу сделать его l oop, поэтому он должен перерыв. Продолжить, просто введите ошибку до тошноты.

try {
                playerPos = move.nextInt();
            } catch (InputMismatchException e) {
                System.out.println("1-9 only, please try again.");
                break;
            }

Вместо перерыва я попробовал playerPos = move.nextInt (); как и другие мои циклы while, но это просто приводит к ошибке «Исключение в основном потоке», которая останавливает программу. Вероятно, есть довольно простое решение, которое я просто не понимаю.

1 Ответ

0 голосов
/ 18 июня 2020

Типичный паттерн, который мне нравится:

public Optional<Integer> getInt(String input) {
    try {
        return Integer.parseInt(input);
    } catch (NumberFormatException ex) {
        return Optional.empty();
    }
}

Затем в вашем основном logi c:

//...
Scanner move = /* your scanner object */;
Optional<Integer> input;
while ((input = getIntLine(move.nextLine())).isEmpty()) {
    System.out.println("Invalid input, expected (number)"); 
}
int value = input.get();

Если вы хотите, чтобы ваш l oop повторился запрос ввода, это тоже достаточно просто:

//...
Scanner move = /* your scanner object */;
Optional<Integer> input;
boolean read = false;
while (!read) {
    System.out.print("Please enter a number: ");
    input = getInt(move.nextLine());
    read = !input.isEmpty();
    if (!read) {
        System.out.println("Not a number " /* ... etc */);
    }
}
int value = input.get();
...