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

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(),导致:
    1. 第一次外层循环(i=0)时,j=0读取第一行-X-,j=1读取第二行-X-,j=2读取第三行-O-;
    2. 第二次外层循环(i=1)时,j=0读取移动指令的第一个token0,j=1读取第二个token2,此时"2"长度仅为1,调用charAt(1)触发索引越界异常。

解决方案

  1. 修改readInGrid方法,使用input.nextLine()读取整行内容,再从每行提取对应位置的字符填充棋盘;
  2. 修复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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:10:24