Search code examples
javaarraysstringindexoutofboundsexceptionstringbuilder

java.lang.StringIndexOutOfBoundsException: index x , length 0 without a loop


i'm currently adding functionality and completing a Hang-Man game my programing teacher made.

The following error message: Exception in thread "AWT-EventQueue-0" java.lang.StringIndexOutOfBoundsException: index 0, length 0 with the index changing for everyindex in a String builder. is appearing everytime i input a letter that is correctly guessed in the game.

I have tried for a while to fix it but i have yet to be able to.

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
    
}

}

Solution

  • The code is needlessly complex and that is making it hard for you to see the issue.

    Your actual issue starts on this line where you assign the entire correct word d to randomWord:

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

    You then use the entire correct word and append it to your builder string:

    //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());
    

    So now when you try to get the index of your letter for example if you guessed 'm' it will return a large index:

    //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);
    

    So when you use the next line with an index of 6 it will be out of bounds because the builderDisplay String is only 4 characters long for the word rome:

    builderDisplay.setCharAt(index, CharGuessedLetter);
    

    So what can you do to fix this? I won't give you an exact answer, but You should start by thinking about the above code, and where it goes wrong (append), and how you can return the correct character index (using the d string)

    Final hint, the following line would get a correct character index of a character, note how we use the d string, not the builder string:

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

    Edit:

    Following on from comments. You also need to fill the string builder with blanks to avoid this issue:

    //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('_');
    }
    

    Note also that you should check for duplicate characters in your word:

    //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());