使用 Character.getNumericValue 时出现 StringIndexOutOfBoundsException

StringIndexOutOfBoundsException when using Character.getNumericValue

这是我的 tic tac toe 程序的接受函数,所以 s 只会以 String 格式存储 0,0 或 2,2 之间的数据。

我现在使用 getNumericValue 函数将数字分别存储在 pq 中,但是在运行时,我在尝试时遇到 StringIndexOutOfBounds 异常将值存储在 p 中。

The problem is happening only when choice() function to decide x or O is called before accept() else it's running fine. What is the problem with the choice() funtion?

void accept()throws IOException
{
    System.out.println("Your move:");
    String s=xy.readLine();

    int p = (Character.getNumericValue(s.charAt(0)))-1;
    int q = Character.getNumericValue(s.charAt(2))-1;
    if(ar[p][q]==0)
        ar[p][q]=1;
    else
    {
        System.out.println("You can't capture a location that has already been captured!");
        accept();
    }
}



void choice() throws IOException
    {
        System.out.println("Welcome to tictactoe");
        System.out.print("Enter your weapon X or O : ");
        chp = Character.toUpperCase((char)xy.read());

        if (chp=='X')
            chc='O';
        else 
            chc = 'X';

        System.out.println("kkbot chose: "+ chc);
    }

您的问题是:

这是我的井字游戏程序的接受函数,所以 s 只会以 0,0 或 2,2 之间的格式存储数据。

但是您的代码会:

String s=xy.readLine();
int p = (Character.getNumericValue(s.charAt(0)))-1;
int q = Character.getNumericValue(s.charAt(2))-1;

用户可以输入任何他想要的东西。 readLine() 中的任何内容都不会阻止他添加空字符串或太长的字符串!

在对该字符串执行 任何操作 之前,您已经 验证 它具有 assumed 长度;比如:

String inputFromUser = "";
do {
  System.out.println("Your move [enter a value like A1]: ");
  inputFromUser = scanner.readLine();
} while (inputFromUser.length != 2);

除此之外:请为变量使用 真实 名称。 s, xy, p, q ...告诉 reader nothing 这些变量的用途。是的,您在打字时节省了一些时间;以后阅读源代码时,你将花费 10 倍的时间;那些丑陋的 single-character 名字也大大增加了出现愚蠢拼写错误的可能性!

如果您只是想将 0,01,1 之类的值存储在两个单独的 int 变量中,那应该是一个简单的过程。不过,您应该对错误输入采取预防措施。 因此,您的 accept() 方法应该是这样的:

public void accept(){
        Scanner sc = new Scanner(System.in);
        System.out.println("Your move [Enter marking position in the form x,y]: ");
        String userInput = sc.nextLine();
        String[] userMarkedPositions = userInput.split(",");
        if(userMarkedPositions.length == 2){
            int x = Integer.parseInt(userMarkedPositions[0]);
            int y = Integer.parseInt(userMarkedPositions[1]);
            //Followed by your other operations
            //....
            //....
        }else{
            System.out.println("Invalid input!!");
            System.out.println("Input should be in the form of x,y");
            accept();
        }
        sc.close();
    }

就像@GhostCat 正确提到的那样,您应该为变量使用适当的名称。这提高了代码的可读性。

哎呀我终于找到代码中的问题了。 choice() 函数接受一个字符,但之后当字符串被接受时,机器不会让用户有机会输入字符串,而是自动将 null 作为输入字符串(在字符后按 space 时产生).

问题

This problem is produced whenever one tries to accept a string or any other data type after CHAR, for example, the input for 's' here after the input 'ch'.

解决方案

Read input as a string, and extract the first character to consume and discard the subsequent spaces and newlines I also found a way to hack this problem though. :)

import java.io.*;
class tictactoe
{
    BufferedReader xy=new BufferedReader(new InputStreamReader(System.in));
    void accept()throws IOException
    {
        System.out.println("Enter your weapon X or O : ");
        char ch = xy.readLine().charAt(0);  #Ahaaa momemt
    
        System.out.println("Your move:");
        String s=xy.readLine();              
    }
}