【问题标题】:java.lang.StringIndexOutOfBoundsException: index x , length 0 without a loop [closed]java.lang.StringIndexOutOfBoundsException:索引 x ,长度 0 没有循环 [关闭]
【发布时间】:2021-08-07 05:29:21
【问题描述】:

我目前正在添加功能并完成我的编程老师制作的 Hang-Man 游戏。

以下错误消息:线程“AWT-EventQueue-0”java.lang.StringIndexOutOfBoundsException 中的异常:索引 0,长度 0,索引更改为字符串构建器中的每个索引。每次我输入一个在游戏中猜对的字母时都会出现。

我已经尝试了一段时间来修复它,但我还没有能够做到。

package hangManSo;


import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Arrays;
import java.util.Random;


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;



public class HangManSO extends JPanel implements             ActionListener, MouseListener {
private int error;
JButton button;
JTextField field;
JFrame frame;
JLabel rättord;

HangManSO(JButton button, JTextField field, JFrame frame, JLabel rättord) {
    this.button = button;
    this.field = field;
    this.frame = frame;
    this.rättord = rättord;
    this.addMouseListener(this);
}

static String [] ord = {"rome"}; 
static Random r = new Random();
static int randomNumber=r.nextInt(ord.length);
static String d = ord[randomNumber];

StringBuilder builder = new StringBuilder(d.length());
StringBuilder builderDisplay = new StringBuilder();

public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    
    String guessedletter = field.getText();
    
    if (source.equals(button)) {
        
         
        if (!d.contains(guessedletter)) {
            error++;
            frame.repaint();
        }
        
        
        if (d.contains(guessedletter)) {
            
            char [] randomWord = d.toCharArray();   
            char CharGuessedLetter = guessedletter.charAt(0);
            
            
            //gets the index of the guessed letter in the randomword
            builder.append(randomWord);
        
            int index = builder.indexOf(String.valueOf(CharGuessedLetter));
            
            //is supposed to set the correctly guessed letter in the correct index 
            builderDisplay.setCharAt(index, CharGuessedLetter);
                 
            rättord.setText(builderDisplay.toString());
        

        
        }
        
        
              
        field.setText("");
   
    
    }

    
    
}

public void paintComponent(Graphics g ) {
    
    super.paintComponent(g);

    if (error == 1)
        g.drawLine(10, 270, 500, 270);

    if (error == 2) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
    }
    
    if (error == 3) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
    }
    
    if (error == 4) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
    }
    
    if (error == 5) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
        g.drawLine(350, 30, 350,100);

    }
    
    if (error == 6) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
        g.drawLine(350, 30, 350,100);
        g.drawOval(330, 100, 40, 40);

    }
    
    if (error == 7) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
        g.drawLine(350, 30, 350,100);
        g.drawOval(330, 100, 40, 40);
        g.drawLine(350, 140, 350,200);

    }
    
    if (error == 8) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
        g.drawLine(350, 30, 350,100);
        g.drawOval(330, 100, 40, 40);
        g.drawLine(350, 140, 350,200);
        g.drawLine(350, 200,390, 240);

    }
    
    if (error == 9) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
        g.drawLine(350, 30, 350,100);
        g.drawOval(330, 100, 40, 40);
        g.drawLine(350, 140, 350,200);
        g.drawLine(350, 200,390, 240);
        g.drawLine(350, 200, 310, 240);

    }
    
    if (error == 9) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
        g.drawLine(350, 30, 350,100);
        g.drawOval(330, 100, 40, 40);
        g.drawLine(350, 140, 350,200);
        g.drawLine(350, 200,390, 240);
        g.drawLine(350, 200, 310, 240);

    }
    
    if (error == 10) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
        g.drawLine(350, 30, 350,100);
        g.drawOval(330, 100, 40, 40);
        g.drawLine(350, 140, 350,200);
        g.drawLine(350, 200,390, 240);
        g.drawLine(350, 200, 310, 240);
        g.drawLine(350, 170, 400, 150);

    }
    
    if (error == 11) {
        g.drawLine(10, 270, 500, 270);
        g.drawLine(200, 30, 200, 270);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(200, 30, 350, 30);
        g.drawLine(250, 30, 200, 75);
        g.drawLine(350, 30, 350,100);
        g.drawOval(330, 100, 40, 40);
        g.drawLine(350, 140, 350,200);
        g.drawLine(350, 200,390, 240);
        g.drawLine(350, 200, 310, 240);
        g.drawLine(350, 170, 400, 150);
        g.drawLine(350, 170, 300, 150);
        

        
  }        
  
    if(error > 11) {
        
        g.setFont(new Font("Calibri", Font.BOLD, 26));
        g.drawString("GAME OVER", 225, 150);
        
    }

}
    


public static void main(String[] args) {
    JFrame.setDefaultLookAndFeelDecorated(true);
    JFrame frame = new JFrame("HangMan");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    JLabel rubrikOrd = new JLabel("rätt gissade ord");
    rubrikOrd.setOpaque(false);
    rubrikOrd.setBackground(Color.GREEN);
    rubrikOrd.setBounds(10, 10, 100, 20);

    JLabel rättord = new JLabel();
    rättord.setOpaque(true);
    rättord.setBackground(Color.GREEN);
    rättord.setBounds(10, 35, 100, 20);
    
    
    
    
    JTextField field = new JTextField();
    field.setVisible(true);

    JButton b = new JButton("ok");
    b.setBounds(370, 300, 100, 30);
    frame.add(b);
    field.setSize(300, 30);
    field.setLocation(60, 300);
    field.setVisible(true);
    frame.add(field);
    frame.add(rättord);
    frame.add(rubrikOrd);

    frame.setBackground(Color.white);
    frame.setSize(600, 400);

    HangManSO object = new HangManSO(b, field, frame, rättord);
    b.addActionListener(object);
    field.addActionListener(object);
    frame.add(object);
    frame.setVisible(true);

}


@Override
public void mouseClicked(MouseEvent e) {
    System.out.println(e.getX() + " " + e.getY());
}


@Override
public void mousePressed(MouseEvent e) {
    // TODO Auto-generated method stub
    
}


@Override
public void mouseReleased(MouseEvent e) {
    // TODO Auto-generated method stub
    
}


@Override
public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub
    
}


@Override
public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub
    
}

}

【问题讨论】:

  • 你能从异常堆栈跟踪中添加更多吗?可能有实际引发异常的指令
  • builderDisplay 以空(长度 == 0)启动。您可以使用一个字符串初始化它,其所有空格字符的长度 == answer.length。
  • 但是,您不需要字符串生成器。一个简单的数组或数组列表就足够了。
  • 修复代码的另一个想法,在调用setCharAt之前,您可以检查当前builderDisplay的长度。如果索引 >= builderDisplay.length,则追加而不是 setCharAt

标签: java arrays string indexoutofboundsexception stringbuilder


【解决方案1】:

代码过于复杂,让您很难发现问题。

您的实际问题从您将整个正确单词 d 分配给 randomWord 的这一行开始:

char [] randomWord = d.toCharArray();
//randomWord now equals `{r,o,m,e}`

然后您使用整个正确的单词并将其附加到您的 builder 字符串中:

//builder equals a blank string of 4 characters "    "
builder.append(randomWord);
//builder now equals a string with 4 blank characters followed by some "    rome"
System.out.print(builder.toString());

因此,现在当您尝试获取字母的索引时,例如,如果您猜到“m”,它将返回一个大索引:

//the builder string now "    rome"
int index = builder.indexOf(String.valueOf(CharGuessedLetter));
//So `m` will be found at the 6th index of "    rome"
System.out.print("index = " + index);

因此,当您使用索引为 6 的下一行时,它将超出范围,因为 builderDisplay 字符串对于单词 rome 而言只有 4 个字符长:

builderDisplay.setCharAt(index, CharGuessedLetter);

那么你能做些什么来解决这个问题呢?我不会给你一个确切的答案,但你应该首先考虑上面的代码,它哪里出错了(append),以及如何返回正确的字符索引(使用d字符串)

最后提示,以下行将获得一个字符的正确字符索引,注意我们如何使用d 字符串,而不是builder 字符串:

int index = d.indexOf(String.valueOf(CharGuessedLetter));

编辑:

从 cmets 开始。您还需要用空格填充字符串生成器以避免此问题:

//Create the hangman object
HangManSO object = new HangManSO(b, field, frame, rättord);
//Now populate the string builder with empty characters "_" or you could use a space " "
for (int i = 0; i < object.d.length(); i++) {
    object.builderDisplay.append('_');
}

还要注意,您应该检查单词中的重复字符:

//check against every letter of the word to make sure that it gets duplicate characters
for (int i = 0; i < d.length(); i++) {
    if (d.charAt(i) == charGuessedLetter){
        builderDisplay.setCharAt(i, charGuessedLetter);
        System.out.println("Match found");
    }
}
rättord.setText(builderDisplay.toString());

【讨论】:

  • 我在声明 Stringbuilders 时删除了 (d.length),根据我对您所说的理解,应该删除代码中的额外空格,因此“索引”应该具有正确的 int当“randomWord”附加到“builder”时,放置字母并删除问题。我还使用了您获取索引的方法。但是我继续遇到同样的错误。
  • 你会注意到错误改变了位置,你现在的问题是builderDisplay被初始化为长度为0,StringBuilder builderDisplay = new StringBuilder();但你应该使用d.length()这样StringBuilder builderDisplay = new StringBuilder(d.length());给它是正确的长度,以便这条线正常工作builderDisplay.setCharAt(index, CharGuessedLetter);
  • 我应用了它,但是正如您所说,错误已更改为:线程“AWT-EventQueue-0”中的异常 java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:0。
  • 我现在修好了。谢谢你的帮助!
  • @Koshan 太棒了。我在上一条评论中给了您错误的信息,您仍然需要填写 builderDisplay 字符串生成器,例如使用循环将其全部设置为空白 builderDisplay.setCharAt(i, "_");。请参阅上面我的答案中的编辑信息,以及处理重复字符的提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 2017-08-26
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
  • 1970-01-01
  • 2013-04-06
相关资源
最近更新 更多