You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Java Scanner的nextInt()时遇NoSuchElementException及无限循环问题

终端版战舰游戏shipLocations方法二次调用异常问题解决

问题根源

你的核心问题出在重复创建并关闭Scanner实例:

  • 每次调用shipLocations方法时,都新建Scanner input = new Scanner(System.in),并且在方法末尾调用input.close()。关闭Scanner会连带关闭底层的System.in输入流,第二次调用方法时,新建的Scanner已经无法从已关闭的System.in读取数据,导致hasNextInt()永远返回false,或者直接抛出NoSuchElementException。
  • 初始化坐标为6时,会进入无效坐标循环,但输入流已关闭后hasNextInt()一直为false,coordinate1和coordinate2始终是6,循环条件invalidCoords永远为true,触发无限循环;设为0时,第一次调用后关闭输入流,第二次调用时无法读取输入,直接抛出异常。

解决方案

  1. 复用同一个Scanner实例:在main方法中仅创建一次Scanner,作为参数传递给shipLocations方法,统一在main方法结束前关闭它,避免破坏System.in输入流。
  2. 优化输入校验逻辑:用单一循环处理所有无效输入场景,同时清理输入流中残留的换行符,避免干扰后续读取。

修改后的代码

import java.util.Scanner;

public class battleship {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in); // 仅创建一次Scanner实例
        System.out.println("Hello Mortals, Welcome to Battleship!");
        
        System.out.println("PLAYER 1, Enter your ships' coordinates.");
        int[] coordinate1 = shipLocations(1, input);
        int[] coordinate2 = shipLocations(2, input);
        // int[] coordinate3 = shipLocations(3, input);
        // int[] coordinate4 = shipLocations(4, input);
        // int[] coordinate5 = shipLocations(5, input);

        input.close(); // 统一在程序结束前关闭Scanner
    }

    public static int[] shipLocations(int shipNumber, Scanner input){
        int coordinate1;
        int coordinate2;
        int[] coordinates = new int[2];
        boolean invalidCoords;

        do {
            invalidCoords = false;
            System.out.println("Enter Ship " + shipNumber + " location: ");
            
            // 校验是否输入了两个有效整数
            if(!input.hasNextInt()){
                System.out.println("输入无效,请输入两个整数坐标!");
                input.nextLine(); // 清理当前行的无效输入
                invalidCoords = true;
                continue;
            }
            coordinate1 = input.nextInt();
            if(!input.hasNextInt()){
                System.out.println("输入无效,请输入两个整数坐标!");
                input.nextLine(); // 清理无效输入
                invalidCoords = true;
                continue;
            }
            coordinate2 = input.nextInt();
            input.nextLine(); // 清理输入后的换行符,避免干扰后续读取

            // 校验坐标范围(0-4)
            if(coordinate1 < 0 || coordinate1 > 4 || coordinate2 < 0 || coordinate2 > 4){
                System.out.println("Invalid Coordinates. Choose different Coordinates.");
                invalidCoords = true;
            } else {
                coordinates[0] = coordinate1;
                coordinates[1] = coordinate2;
            }
        } while(invalidCoords);

        return coordinates;
    }
}

关键修改点说明

  • 移除方法内的Scanner创建和关闭逻辑,改为外部传入实例,保护System.in输入流不被提前关闭。
  • 重构校验逻辑,用单一循环处理非整数输入、坐标超范围等所有无效场景,避免分支混乱。
  • 每次读取整数后调用input.nextLine()清理换行符,防止残留的空白字符影响后续输入判断。
  • 增加坐标下限校验(不能小于0),让逻辑更严谨。

内容的提问来源于stack exchange,提问作者Dylan Wangrud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 13:55:20