-3

Stack Trace Hi i'm working on a GUI for monopoly and i've reached a stage where i need to get user input that would ask for a specific number of players and would provide a certain number of tokens (monopoly pieces) based on the number of players specified. I've currently hit a problem i feel really shouldn't be as serious as it is where if i do try to specify the number of players for the game i'm hit with a an ArrayIndexOutOfBoundsException and i can't seem to identify where or what is wrong and how to fix it. Thanks for the help in advance and any edits or tips for my code to make it more efficient are also welcome. I will attach all necessary program files.

P.s i posted the full source code as i felt it was necessary as a shortened version wouldn't make things as clear. Thanks again. P.p.s the code does work when i specify the number of players in the source code without asking for user input but stops working when i do specify user input. Monopoly Board Image

package sprint_One;

/*
 * Code written by: lagosBoys A layered pane was used to place all components on the frame at the
 * desired locations
 */

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

public class UI_Monopoly_Board extends JFrame {
  /**
   * 
   */
  private static final long serialVersionUID = 1L;
  // Array of coordinates for the position of each square on the board
  Point[] locations = {new Point(630, 643), new Point(570, 643), new Point(510, 643),
      new Point(450, 643), new Point(390, 643), new Point(330, 643), new Point(270, 643),
      new Point(210, 643), new Point(150, 643), new Point(95, 643), new Point(60, 643),
      new Point(60, 573), new Point(60, 503), new Point(60, 433), new Point(60, 383),
      new Point(60, 323), new Point(60, 273), new Point(60, 213), new Point(60, 153),
      new Point(60, 93), new Point(60, 33),

      new Point(120, 13), new Point(180, 13), new Point(230, 13), new Point(280, 13),
      new Point(340, 13), new Point(400, 13), new Point(460, 13), new Point(520, 13),
      new Point(580, 13), new Point(660, 60), new Point(660, 120), new Point(660, 160),
      new Point(660, 220), new Point(660, 280), new Point(660, 340), new Point(660, 400),
      new Point(660, 460), new Point(660, 520), new Point(660, 580), new Point(660, 640)};
  // The default position or starting point which is go
  Point defaultPosition = new Point(600, 603);

  private int players;
  private Token[] token;

  private static JPanel infoPanel;
  private static JPanel commandPanel;

  // creates a fixed length for the text field used by the command field
  final static int field_Width = 20;
  private static JTextField commandField = new JTextField(field_Width);
  private static JLabel commandLabel = new JLabel("Enter Command: ");

  private Border blackLineBorder;
  private final int ROWS = 35;
  private final int COLUMNS = 40;
  private JTextArea textArea = new JTextArea(ROWS, COLUMNS);
  private static JLabel echoed_Text_Label = new JLabel();
  private JLayeredPane layeredPane = getLayeredPane(); // The use of a JLayeredPane allows easier
                                                       // and more flexible specification of
                                                       // component positions

  private static JLabel monopolyImageLabel;

  public UI_Monopoly_Board() {
    String playerNumber = JOptionPane.showInputDialog("Please enter the number of players");

//    int tokenNumber = Integer.parseInt(playerNumber);

//    players = 6;

    players = Integer.parseInt(playerNumber);

    int offset = 10;

    // Initialise tokens depending on number of players and spaces them out with offset

    if(players >= 2 || players <= 6)
    {

      token = new Token[players];
      switch (players) {
        case 2:
          token[0] = new Token();
          token[0].setBounds(10, 10, 700, 700);

          token[0].setPosition(600, 603);

          token[1] = new Token(Color.red, null);

          token[1].setBounds(10, 10, 700, 700);

          token[1].setPosition(600 + offset, 603 + offset);

          break;

        case 3:
          token[0] = new Token();

          token[0].setBounds(10, 10, 700, 700);

          token[0].setPosition(600, 603);

          token[1] = new Token(Color.red, null);

          token[1].setBounds(10, 10, 700, 700);

          token[1].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[2] = new Token(Color.blue, null);

          token[2].setBounds(10, 10, 700, 700);

          token[2].setPosition(600 + offset, 603 + offset);

          break;

        case 4:
          token[0] = new Token();

          token[0].setBounds(10, 10, 700, 700);

          token[0].setPosition(600, 603);

          token[1] = new Token(Color.red, null);

          token[1].setBounds(10, 10, 700, 700);

          token[1].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[2] = new Token(Color.blue, null);

          token[2].setBounds(10, 10, 700, 700);

          token[2].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[3] = new Token(Color.green, null);

          token[3].setBounds(10, 10, 700, 700);

          token[3].setPosition(600 + offset, 603 + offset);
          break;

        case 5:
          token[0] = new Token();

          token[0].setBounds(10, 10, 700, 700);

          token[0].setPosition(600, 603);

          token[1] = new Token(Color.red, null);

          token[1].setBounds(10, 10, 700, 700);

          token[1].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[2] = new Token(Color.blue, null);

          token[2].setBounds(10, 10, 700, 700);

          token[2].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[3] = new Token(Color.green, null);

          token[3].setBounds(10, 10, 700, 700);

          token[3].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[4] = new Token(Color.yellow, null);

          token[4].setBounds(10, 10, 700, 700);

          token[4].setPosition(600 + offset, 603 + offset);

          break;

        case 6:
          token[0] = new Token();

          token[0].setBounds(10, 10, 700, 700);

          token[0].setPosition(600, 603);

          token[1] = new Token(Color.red, null);

          token[1].setBounds(10, 10, 700, 700);

          token[1].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[2] = new Token(Color.blue, null);

          token[2].setBounds(10, 10, 700, 700);

          token[2].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[3] = new Token(Color.green, null);

          token[3].setBounds(10, 10, 700, 700);

          token[3].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[4] = new Token(Color.yellow, null);

          token[4].setBounds(10, 10, 700, 700);

          token[4].setPosition(600 + offset, 603 + offset);

          offset = offset + 10;

          token[5] = new Token(Color.cyan, null);

          token[5].setBounds(10, 10, 700, 700);

          token[5].setPosition(600 + offset, 603 + offset);

          break;

        default:
          System.out.println("Invalid number of players");
      }
    }

    // The location of the image should be specified here
    monopolyImageLabel =
        new JLabel(new ImageIcon(this.getClass().getResource("Monopoly_board.jpg")));
    monopolyImageLabel.setBounds(-50, -30, 800, 750);
    // The image and the tokens are added to the pane at different levels allowing them to overlap
    layeredPane.add(monopolyImageLabel);
    layeredPane.add(token[0], new Integer(1));
    layeredPane.add(token[1], new Integer(2));
    layeredPane.add(token[2], new Integer(3));
    layeredPane.add(token[3], new Integer(4));
    layeredPane.add(token[4], new Integer(5));
    layeredPane.add(token[5], new Integer(6));


    setSize(1500, 750);
    setExtendedState(JFrame.MAXIMIZED_BOTH); // Sets the default window for the JFrame as a
                                             // maximised
    this.setResizable(false);
    setTitle("Welcome to Monopoly");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Ensures the JFrame operation ends completely
                                                    // upon exiting the window
    setVisible(true);
  }

  // This method displays the information panel and adds it to the pane
  public void information_Panel() {
    infoPanel = new JPanel();

    JScrollPane scrollPane = new JScrollPane(textArea);
    blackLineBorder = BorderFactory.createLineBorder(Color.BLACK);
    TitledBorder title = BorderFactory.createTitledBorder(blackLineBorder, "Information Panel");

    infoPanel.setBorder(title);
    infoPanel.add(echoed_Text_Label, BorderLayout.NORTH);

    // prevents any information from being added or deleted from the information panel.
    textArea.setEditable(false);
    infoPanel.add(scrollPane);
    infoPanel.setBounds(750, 0, 600, 600); // specifies the desired coordinates of the panel being
                                           // added to the layered pane

    layeredPane.add(infoPanel);
  }

  // This method displays the command panel and adds it to the pane
  public void command_Panel() {
    commandPanel = new JPanel();

    blackLineBorder = BorderFactory.createLineBorder(Color.BLACK);

    JButton button = new JButton("Enter");

    /*
     * implements the actionlistener interface on the button to help execute a command when the
     * button is clicked
     */
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        if (commandField.getText().isEmpty()) {
          String command = null;
          textArea.append(command);
        }

        else {
          String command = commandField.getText();
          textArea.append(command + "\n");
          commandField.setText("");
        }
      }
    });

    // This invokes the actionListeners interface for actionPerformed (quick way to implement a key
    // listener on the keyboards Enter button)
    getRootPane().setDefaultButton(button);

    commandPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
    button.setPreferredSize(new Dimension(65, 20));
    commandPanel.add(commandLabel);
    commandPanel.add(commandField);
    commandPanel.add(button);
    commandPanel.setBounds(800, 630, 500, 50); // specifies the desired coordinates of the panel
                                               // being added to the layered pane

    layeredPane.add(commandPanel);
  }

  // Method which moves the tokens round the board one at a time
  public void moveTokens() throws InterruptedException {

    int i, j, offset;
    offset = 0;

    for (i = 0; i < token.length; i++) {
      for (j = 0; j < locations.length; j++) {
        token[i].setPosition(locations[j].x, locations[j].y);
        repaint();
        // controls the movement speed of the tokens across the board allowing for easy detection of
        // their movement
        Thread.sleep(300);
      }

      token[i].setPosition(defaultPosition.x + offset, defaultPosition.y + offset);
      offset = offset + 15;
    }
  }



  public static void main(String[] args) throws InterruptedException {
    // TODO Auto-generated method stub
    UI_Monopoly_Board obj = new UI_Monopoly_Board();
    obj.information_Panel();
    obj.command_Panel();
    obj.moveTokens();
[enter image description here][1]
  }

}


package sprint_One;

import java.awt.*;
import javax.swing.JComponent;

/*
 * Each token has variables for location, dimension and shape, there's a constructor that allows the
 * user to specify the colour of the shape the necessary accessor and mutator functions are provided
 */
public class Token extends JComponent {
  /**
   * 
   */
  private static final long serialVersionUID = 1L;
  private int length;
  private int breadth;
  private int x;
  private int y;
  private Shape shape;
  private Color color;
  private String name;
  private int balance;

  public Token() {
    super();
    setVisible(true);
    this.length = 15;
    this.breadth = 15;
    this.x = 5;
    this.y = 5;
    this.shape = new Rectangle(this.x, this.y, this.length, this.breadth);
    this.color = Color.BLACK;
    this.name = "";
    this.balance = 20;
  }

  public Token(Color color, String name) {
    this();
    this.color = color;
    this.name = name;
  }

  public int getX() {
    return this.x;
  }

  public int getY() {
    return this.y;
  }

  // Method which specifies the x and y coordinates of the tokens
  public void setPosition(int x, int y) {
    this.x = x;
    this.y = y;
  }

  public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    super.paintComponent(g);

    g2.setColor(color);
    g2.fill(shape); // fills the shape with the colour specified

    g2.draw(this.shape);
  }

  public Shape getShape() {
    // TODO Auto-generated method stub
    return this.shape;
  }
}
Wade
  • 1
  • 2
  • 2
    Too much code. Post a [mcve] and a stack trace. – khelwood Feb 17 '17 at 12:11
  • As defination of ArrayIndexOutOfBoundsException .Thrown to indicate that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array. – Mayank Pandya Feb 17 '17 at 12:13
  • i'm new to this so i really don't know what you mean by stack trace, nor am i sure of how to specify a minimal amount of code in such a way that you'd spot the problem if you were to run the program. – Wade Feb 17 '17 at 12:14
  • 1
    @Wade http://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors – OH GOD SPIDERS Feb 17 '17 at 12:16
  • I do realise the meaning of the error but i can't seem to understand why i am getting it just cus everything looks right to me @Maynak_Pandya – Wade Feb 17 '17 at 12:17
  • @Wade The problem is probably not your switch statement, but that after your switchstatement you just try to add token[0] - token[5] to layeredPanel without any checks if token actually has that many elements. The Stacktrace would tell you the exact line where the error occurs in and is therfor quite important btw. – OH GOD SPIDERS Feb 17 '17 at 12:17
  • 1
    "i can't seem to identify *where* ..." - see the stack trace you get - "or *what* is wrong" - you try to access an item that is not there. – Axel Feb 17 '17 at 12:17
  • @Axel oh that's what a stack trace is, didn't know that's what it was called but yes i have checked the stack trace and i don't see why there is a problem at the line specified. The code does work when i don't try to get user input on the number of players – Wade Feb 17 '17 at 12:20
  • 3
    Do we get to see the stack trace? – Steve Smith Feb 17 '17 at 12:21
  • 1
    If you looked at the stack trace, then you know which line caused the error. That information needs to be in your question. – khelwood Feb 17 '17 at 12:26
  • @khelwood look you constantly talked about stack trace assuming i knew what it was. I only just found out that the console information regarding errors was called a stack trace. It would have helped if you explained what it was you were asking. I just added it to the post now. – Wade Feb 17 '17 at 12:28
  • @Wade The stacktrace confirms what i wrote 10minutes ago. Your token array has a variable length, therefor you cannot just add token[5] (for example) to your layeredPanel without checking if it actually exists. – OH GOD SPIDERS Feb 17 '17 at 12:28
  • @911DidBush yeah i get you, token[5] should only exist when i specify that i want the number of players that should require token[5], based on my understanding. If i'm not checking if it exists how else do i go about carrying out this check – Wade Feb 17 '17 at 12:34
  • @Wade ? Not getting what you are saying. The problem is that you are **not** doing any check at the line the exception occurs. – OH GOD SPIDERS Feb 17 '17 at 12:40
  • @911DidBush i presume by check you mean finding if my tokens exist, do you have a guideline or tip on how i could go about it? – Wade Feb 17 '17 at 12:41
  • @Wade An array has a attribute length that contains its size. So for example: `if(token.length >= 2) { // token[1] exists}` – OH GOD SPIDERS Feb 17 '17 at 12:45
  • @Wade Regardless of whether or not you knew what "stack trace" meant, you already looked at the error message you were getting, and found what line the problem was on; and then you **left that information out of your question**, giving 400 lines of code with no indication where the problem was. – khelwood Feb 17 '17 at 13:12
  • 1
    @khelwood i get your complaint which makes sense and honestly it didn't cross my mind to put that in. This is really btw, im not here to argue about not having a stack trace. I'm just trying to get helpful input. – Wade Feb 17 '17 at 19:17
  • @911DidBush thanks i think get what you're referring to appreciate it! – Wade Feb 17 '17 at 19:17

1 Answers1

0

Ok, you should learn how to use a debugger...

This is the line that causes your error:

layeredPane.add(token[2], new Integer(3));

And you initialise tokenlike this:

if(players >= 2 || players <= 6)
{
  token = new Token[players];

So, what if players is 2? You will get an ArrayIndexOutOfBoundsException.

Another tip:

layeredPane.add(token[0], new Integer(1));

is not as readable as

layeredPane.add(token[0], 1);
Axel
  • 13,939
  • 5
  • 50
  • 79
  • oh i also did try initialising token as token = new Token[players - 1]; to fix the problem but that didnt work either. Thanks for the tip – Wade Feb 17 '17 at 12:37
  • Of course it didn't. Regardless of the numbers of players you even do `layeredPane.add(token[5], new Integer(6));` so token would have to be initialised with 6. – Axel Feb 17 '17 at 12:59