0

I am doing a TicTacToe program and right now I am working on using a menu to change the size of the board(anywhere from 3x3 to 9x9) I need to remove the current buttons in use before adding the new ones. While looping through trying to remove them i get this error:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3
    at TicTacToe$menuItem.actionPerformed(TicTacToe.java:84)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
    at java.awt.Component.processMouseEvent(Component.java:6535)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6300)
    at java.awt.Container.processEvent(Container.java:2236)
    at java.awt.Component.dispatchEventImpl(Component.java:4891)
    at java.awt.Container.dispatchEventImpl(Container.java:2294)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
    at java.awt.Container.dispatchEventImpl(Container.java:2280)
    at java.awt.Window.dispatchEventImpl(Window.java:2750)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Process finished with exit code 0

Here is the code(everything that needs to be imported has been i just didnt paste it in)

public class TicTacToe extends JFrame{

public enum Space{EMPTY, X_SPACE, O_SPACE}
public enum Winner{PLAYER, COMPUTER, NEITHER}

int size;
Button button[][];
Space board[][];
int weight[][];
menuItem item[];

ImageIcon X = new ImageIcon(this.getClass().getResource("X.png"));
ImageIcon O = new ImageIcon(this.getClass().getResource("O.png"));
JPanel panel = new JPanel();


public TicTacToe(int s) {
    // Initialize window properties
    super("Tic Tac Toe");
    boardSize(s);
    item = new menuItem[7];
    clearBoard();
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(500, 500);
    setResizable(false);
    setLocationRelativeTo(null);
    panel.setLayout(new GridLayout(s, s));

    JMenuBar menubar = new JMenuBar();
    this.setJMenuBar(menubar);

    JMenu menu = new JMenu("Set Size");
    menubar.add(menu);

    for(int i=0; i<item.length; i++){
        item[i] = new menuItem(this, i+3, menu);
    }

    add(panel);
    setVisible(true);
    initWeight(); // Adds priority initialized in initWeight
}

public class Button extends JButton implements ActionListener {
    int row, col;
    TicTacToe ttt;
    public Button(TicTacToe t, int r, int c){
        ttt = t;
        row = r;
        col = c;
        this.addActionListener(this); // Adds the action listener to the buttons(this)
    }
    public void actionPerformed(ActionEvent e){
        // Displays move after event is found
        ttt.enterMove(row, col);
        displayWinner();
    }
}

public class menuItem extends JMenuItem implements ActionListener{
    int size;
    TicTacToe ttt;
    public menuItem(TicTacToe t,int s, JMenu menu){
        ttt = t;
        size = s;
        setText(s+"x"+s);
        menu.add(this);
        this.addActionListener(this);
    }
    public void actionPerformed(ActionEvent e){
        int s = size;
        for(int i=0; i < s; i++){
            for(int j=0; j < s; j++){
                ttt.panel.remove(button[i][j]);
            }
        }
        ttt.boardSize(size);
    }
}

public void addButtons(int s){
    s = size;
    for(int i = 0; i < s; i++)
    {
        for(int j = 0; j < s; j++)
        {
            board[i][j] = Space.EMPTY;
            button[i][j] = new Button(this, i, j);
            panel.add(button[i][j]);
        }
    }
}

public void displayWinner() {
    Space winner = getWinner();
    String msg;
    if(winner == Space.X_SPACE)
        msg = "Congratulations. You beat a bot smartass.\n Would you like to play again?";
    else if(winner == Space.O_SPACE)
        msg = "Wow... You just lost against a random number generator... You suck.\n Do you want redemption?";
    else
        return;

    int playAgain = JOptionPane.showConfirmDialog(this, msg, "Play Again", JOptionPane.YES_NO_OPTION); // Creates the window asking to play again

    if(playAgain == JOptionPane.YES_OPTION)
        clearBoard();
    else
        System.exit(0);
}

public void newGame(){
    for(int i = 0; i < size; i++){
        for(int j=0; j < size; j++) {
            board[i][j] = Space.EMPTY;
        }
    }
}

public boolean enterMove(int i, int j) {
    boolean goodMove = false;
    if(board[i][j] == Space.EMPTY){
        board[i][j] = Space.X_SPACE;
        goodMove = true;
    }else{
        JOptionPane.showMessageDialog(this, "Invalid Move", "Error", JOptionPane.ERROR_MESSAGE);
    }
    if(goodMove)
        updateBoard();

    if(getWinner() == Space.EMPTY && goodMove){
        computerMove();
        updateBoard();
    }
    return goodMove;
}

public void boardSize(int s) {
    size = s;
    button = new Button[size][size];
    board = new Space[size][size];
    weight = new int[size][size];
    addButtons(s);
    clearBoard();
    newGame();
}

public void initWeight(){
    //Corners
    weight[0][0] = 2;
    weight[0][size -1] = 2;
    weight[size-1][0] = 2;
    weight[size-1][size-1] = 2;

    //Edges
    for(int i = 1; i < size-1; i++) {
        weight[i][0] = 1;
        weight[0][i] = 1;
        weight[size - 1][i] = 1;
        weight[i][size - 1] = 1;
    }

    //Center(s)
    for(int i=1; i < size-1; i++){
        for(int j=1; j < size-1; j++){
            if(weight[i][j] == 0)
                weight[i][j] = 3;
            else if(weight[j][i] == 0)
                weight[j][i] = 3;
        }
    }

}

public boolean computerMove() {
    int mi = size, mj = size;
    int w = 0;

    for(int i=0; i < size; i++){
        for(int j=0; j <size; j++){
            if(board[i][j] == Space.EMPTY){
                if(weight[i][j] > w){
                    w = weight[i][j];
                    mi = i;
                    mj = j;
                }
            }
        }
    }
    if(mi < size && mj < size){
        board[mi][mj] = Space.O_SPACE;
        return true;
    }
    return false;
}

public void clearBoard(){
    for(int i=0; i < size; i++){
        for(int j=0; j < size; j++) {
            board[i][j] = Space.EMPTY;
            button[i][j].setIcon(null);
        }
    }
}

public Space getWinner(){
    Space w = Space.EMPTY;

    // Check for winner horizontally and vertically
    boolean dwii=true, dwij=true;
    for(int i=0; i < size; i++){
        boolean hw=true, vw=true;
        for(int j=1; j < size; j++){
            if(board[i][0] != board[i][j])
                hw = false;
            if(board[0][i] != board[j][i])
                vw = false;
        }
        if(hw && board[i][0] != Space.EMPTY)
            w = board[i][0];
        if(vw && board[0][i] != Space.EMPTY)
            w = board[0][i];

        if(board[0][0] != board[i][i])
            dwii = false;
        if(board[0][size-1] != board[i][size-i-1])
            dwij = false;
    }
    if(dwii && board[0][0] != Space.EMPTY)
        w = board[0][0];
    if(dwij && board[0][size-1] != Space.EMPTY)
        w = board[0][size-1];

    return w;
}

public void updateBoard() {
    for (int i = 0; i < size; i++) {
        for(int j=0; j < size; j++) {
            if (board[i][j] == Space.O_SPACE)
                button[i][j].setIcon(O);
            else if (board[i][j] == Space.X_SPACE)
                button[i][j].setIcon(X);
        }
    }
}

public static void main(String[] args) { // all this does is run the window
    new TicTacToe(3);
}
}

This is the part that is giving me trouble.

        public void actionPerformed(ActionEvent e){
    int s = size;
    for(int i=0; i < s; i++){
        for(int j=0; j < s; j++){
            ttt.panel.remove(button[i][j]);
        }
    }
    ttt.boardSize(size);
}
}
8
  • Please post complete stack trace. The exception tells you that you are accessing an invalid index (3). The stack trace should give you the line number where your code makes that invalid access. Probably your loop condition is wrong .. Commented Mar 12, 2016 at 0:44
  • Ok I posted the full stack trace. Commented Mar 12, 2016 at 0:54
  • I told you: that is the line number ... do you really need us to understand that you now have to figure what is going on ... on line 84? Hint: at least add that line to the question; or do you expect us to copy your code; hoping that you posted all of us; so that the line numbers are matching up?! Commented Mar 12, 2016 at 0:56
  • I already added the loop that was triggering this exception. The specific line is ttt.panel.remove(button[i][j]); Commented Mar 12, 2016 at 1:02
  • See What is a stack trace, and how can I use it to debug my application errors? Commented Mar 12, 2016 at 1:02

2 Answers 2

1

I need to remove the current buttons in use before adding the new ones.

You can use the removeAll() method on the Container class.

This of course assumes the you create a panel that only contains the buttons of your grid which is how I would design the GUI. It is always a good idea to break the components down into logical panels.

Sign up to request clarification or add additional context in comments.

2 Comments

Alright I tried doing this by nesting the gridlayout panel into the borderlayout panel of the menu. The panel containing the buttons doesn't show up though, how should I have that set up? (Sorry, I am a noob with Swing)
It looks like your original code was already adding the "panel" to the CENTER of the BorderLayout. So I'm not sure why you changed anything. The point of my answer was that if the panel only contains the buttons, then you can use removeAll().
0

It seems like you have accidentally modified the global attribute 'size' in your menuItem constructor. In this case, 'size' is > 3 after you initialized menuItems.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.