Java井字棋程序出现StringIndexOutOfBoundsException错误求助
Java井字棋程序StringIndexOutOfBoundsException错误修复
问题描述
编写的Java井字棋程序在输入指定内容后,抛出StringIndexOutOfBoundsException: String index out of range: 1错误,预期程序能正确更新棋盘并打印结果,但实际报错。调试发现第一行棋盘内容读取正常,第二行读取时出现问题。
输入内容
-X- -X- -O- 0 2 X
报错信息
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1 at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:47) at java.base/java.lang.String.charAt(String.java:693) at TicTacToe.readInGrid(TicTacToe.java:59) at TicTacToe.main(TicTacToe.java:76)
原程序代码
import java.util.Scanner; /** * (add a summary comment) * @author Samuel Church * @author Max Hubenko */ public class TicTacToe { /** * Prints to the console the contents of the given tic-tac-toe grid * @param grid 2D char array representing current state of tic-tac-toe game */ public static void printGrid(char[][] grid) { System.out.print(grid); } /** * Updates the tic-tac-toe grid given a move by a player (specified by row, column and mark). * @param grid current tic-tac-toe grid that will be updated * @param row The row the player would like to play in (in the range [0, 2]) * @param column The column the player would like to play in (in the range [0, 2]) * @param mark The mark the player would like to place ('X', 'O') */ public static void placeMark(char[][] grid, int row, int column, char mark) { grid[row][column] = mark; } /** * Reads user input and stores it in a 3x3 char array. This represents * the current state of the tic-tac-toe grid. Expect user input to be * three lines with three characters on each line. * @param input Scanner instance used to read user input * @return tic-tac-toe grid as a 2D char array */ public static char[][] readInGrid(Scanner input){ char ticTacToeBoard[][] = new char[3][3]; for (int i = 0; i < ticTacToeBoard.length; i++) { for (int j = 0; j < ticTacToeBoard[i].length; j++) { ticTacToeBoard[i][j] = input.next().charAt(j); } } return ticTacToeBoard; } /** * Create and show a tic-tac-toe board using the methods you'll write. * Read user input to determine updates to the board. * @param args unused */ public static void main(String[] args) { // DO NOT EDIT MAIN Scanner input = new Scanner(System.in); // Reads in the current state of the tic-tac-toe grid from the user char[][] gameGrid = readInGrid(input); // Reads in the next player's move int row = input.nextInt(); int column = input.nextInt(); char mark = input.next().charAt(0); // Update the tic-tac-toe grid given the next player's move placeMark(gameGrid, row, column, mark); // Print the updated tic-tac-toe grid printGrid(gameGrid); } }
错误原因
readInGrid方法逻辑错误:
input.next()会按空格、换行符等分隔符将输入拆分为独立token,而非读取整行内容。- 原循环中,外层循环遍历行,内层循环遍历列,每次内层循环都调用
input.next(),导致:- 第一次外层循环(i=0)时,j=0读取第一行
-X-,j=1读取第二行-X-,j=2读取第三行-O-; - 第二次外层循环(i=1)时,j=0读取移动指令的第一个token
0,j=1读取第二个token2,此时"2"长度仅为1,调用charAt(1)触发索引越界异常。
- 第一次外层循环(i=0)时,j=0读取第一行
解决方案
- 修改
readInGrid方法,使用input.nextLine()读取整行内容,再从每行提取对应位置的字符填充棋盘; - 修复
printGrid方法,原代码直接打印数组对象会输出内存地址,需遍历数组打印实际棋盘内容。
修正后的完整代码
import java.util.Scanner; /** * (add a summary comment) * @author Samuel Church * @author Max Hubenko */ public class TicTacToe { /** * Prints to the console the contents of the given tic-tac-toe grid * @param grid 2D char array representing current state of tic-tac-toe game */ public static void printGrid(char[][] grid) { for (char[] row : grid) { for (char c : row) { System.out.print(c); } System.out.println(); } } /** * Updates the tic-tac-toe grid given a move by a player (specified by row, column and mark). * @param grid current tic-tac-toe grid that will be updated * @param row The row the player would like to play in (in the range [0, 2]) * @param column The column the player would like to play in (in the range [0, 2]) * @param mark The mark the player would like to place ('X', 'O') */ public static void placeMark(char[][] grid, int row, int column, char mark) { grid[row][column] = mark; } /** * Reads user input and stores it in a 3x3 char array. This represents * the current state of the tic-tac-toe grid. Expect user input to be * three lines with three characters on each line. * @param input Scanner instance used to read user input * @return tic-tac-toe grid as a 2D char array */ public static char[][] readInGrid(Scanner input){ char ticTacToeBoard[][] = new char[3][3]; for (int i = 0; i < ticTacToeBoard.length; i++) { // 读取整行并去除首尾可能的空白字符 String line = input.nextLine().trim(); for (int j = 0; j < ticTacToeBoard[i].length; j++) { ticTacToeBoard[i][j] = line.charAt(j); } } return ticTacToeBoard; } /** * Create and show a tic-tac-toe board using the methods you'll write. * Read user input to determine updates to the board. * @param args unused */ public static void main(String[] args) { // DO NOT EDIT MAIN Scanner input = new Scanner(System.in); // Reads in the current state of the tic-tac-toe grid from the user char[][] gameGrid = readInGrid(input); // Reads in the next player's move int row = input.nextInt(); int column = input.nextInt(); char mark = input.next().charAt(0); // Update the tic-tac-toe grid given the next player's move placeMark(gameGrid, row, column, mark); // Print the updated tic-tac-toe grid printGrid(gameGrid); } }
额外说明
- 若输入中存在空行,可在
readInGrid中添加判断跳过空行,避免读取空字符串触发异常; - 可添加输入校验,确保每行长度为3,移动指令的行、列在0-2范围内,标记为'X'或'O',提升程序健壮性。
内容的提问来源于stack exchange,提问作者maxhub
相关产品推荐
相关产品推荐

