我正在学习 Java 并构建一个战舰游戏作为学习练习。我创建了一个方法来从用户接收一组坐标,该坐标以两个整数形式输入,并用空格分隔。我已经验证这两个整数是否被正确读取,但是程序继续从键盘获取输入,并且永远不会脱离 while 循环。因此,该方法永远不会返回一组坐标。我已经搜索并阅读了很多有关使用 Scanner 的信息,但我没有看到我的代码有什么问题。你能告诉我我做错了什么吗?
传入的扫描仪是
Scanner(System.in)
。
public static int[] getCoordinates(Scanner input, String prompt) {
int[] coordinates = new int[2];
boolean invalid = false;
do {
System.out.println(prompt + ":");
int index = 0;
while (input.hasNext()) {
if (input.hasNextInt() && index < 2) {
coordinates[index] = input.nextInt();
index++;
} else {
input.next();
}
}
if (coordinates[0] < 0 || coordinates[0] > 4 || coordinates[1] < 0 || coordinates[1] > 4) {
System.out.println("Invalid coordinates. Choose different coordinates.");
invalid = true;
}
} while (invalid);
return coordinates;
}
我期望发生的是用户输入两个整数,然后按 Enter 键,
while(input.hasNext())
循环将退出并继续该方法的其余部分。
更新:我只需执行以下操作即可获得基本功能。我不确定这是否可靠,但现在就可以了。
int index = 0;
while (index < 2) {
if (input.hasNextInt()) {
coordinates[index] = input.nextInt();
index++;
}
}
这也很有效。感谢@k314159!
String[] answer = input.nextLine().split(" ");
if (answer.length >= 2) {
coordinates[0] = Integer.parseInt(answer[0]);
coordinates[1] = Integer.parseInt(answer[1]);
}
原始
while (input.hasNext())
循环永远不会退出的原因是它等待输入流 (System.in
) 关闭,这通常在程序终止时发生。它不会仅仅因为用户按下 Enter 键而退出。
如果您想继续使用
while (input.hasNext())
循环并仍然允许用户输入值并按 Enter 键,您可以像这样修改代码:
public static int[] getCoordinates(Scanner input, String prompt) {
int[] coordinates = new int[2];
boolean invalid = false;
do {
System.out.println(prompt + ":");
int index = 0;
while (index < 2) {
if (input.hasNextInt()) {
coordinates[index] = input.nextInt();
index++;
} else {
input.next(); // Consume the non-integer token
}
}
if (coordinates[0] < 0 || coordinates[0] > 4 || coordinates[1] < 0 || coordinates[1] > 4) {
System.out.println("Invalid coordinates. Choose different coordinates.");
invalid = true;
} else {
invalid = false;
}
} while (invalid);
return coordinates;
}
“为什么我的 while(Scanner.hasNext()) 循环永远不会退出?...”
正在等待更多输入。
在 Java 中,这有时被称为 “阻塞”。
“...我期望发生的是用户输入两个整数,然后按回车键,
循环将退出并继续该方法的其余部分。...”while(input.hasNext())
只需调用 nextInt 方法两次。
int[] coordinates;
boolean invalid;
do {
System.out.println(prompt + ":");
coordinates = new int[] { input.nextInt(), input.nextInt() };
invalid = false;
if (coordinates[0] < 0 || coordinates[0] > 4 || coordinates[1] < 0 || coordinates[1] > 4) {
System.out.println("Invalid coordinates. Choose different coordinates.");
invalid = true;
}
} while (invalid);
return coordinates;
更好的方法是将它们添加到坐标时检查值。
int[] coordinates = new int[2];
boolean invalid = true;
do {
System.out.println(prompt + ":");
switch (coordinates[0] = input.nextInt()) {
case 1, 2, 3, 4 -> {
switch (coordinates[1] = input.nextInt()) {
case 1, 2, 3, 4 -> invalid = false;
}
}
}
if (invalid) {
System.out.println("Invalid coordinates. Choose different coordinates.");
input.nextLine();
}
} while (invalid);
return coordinates;
或者最好使用 Scanner#next 或 nextLine 方法以及 Integer#parseInt 方法评估输入。
int a = 0, b = 0;
boolean exit = false;
do {
System.out.println(prompt + ":");
try {
a = Integer.parseInt(input.next());
b = Integer.parseInt(input.next());
if (Math.min(a, b) > 0 && Math.max(a, b) < 4) exit = true;
else throw new Exception();
} catch (Exception e) {
System.out.println("Invalid coordinates. Choose different coordinates.");
input.nextLine();
}
} while (!exit);
return new int[] { a, b };
或者,流。
int[] coordinates = null;
boolean exit = false;
do {
System.out.println(prompt + ":");
try {
coordinates
= input.tokens()
.limit(2)
.mapToInt(Integer::parseInt)
.peek(x -> {
if (x < 0 || x > 4)
throw new RuntimeException(); })
.toArray();
exit = true;
} catch (RuntimeException e) {
System.out.println("Invalid coordinates. Choose different coordinates.");
input.nextLine();
}
} while (!exit);
return coordinates;