0

I am currently trying to set up a Mini version of the Game of Life, but I'm struggling to get it visualised in a frame, using an array to produce a grid.

This is my first time using interfaces, so I've decided to protray the grid and array through a modified bar graph. However, I keep getting an error with the JComponent when I try and place the graph/grid into the frame, with a method called paintComponent being called. I haven't created Graphic g earlier, although I did import JFrame, JComponent and Graphic into the main body.

Main Body

 JFrame frame = new JFrame();
 frame.setSize(400,200);
 frame.setTitle("Mini Game of Life");
 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 for (int t = 0; t < 30; t++)
 {
      grid = LifeSweeper(grid, x, y);   //Line 104
      grid = next;  
      // Line below main Error
      JComponent component = paintComponent(Graphics g; x; y; int grid[][]);
      frame.add(component);

      frame.setVisible(true);
 }

paintComponent Method

public void paintComponent(Graphics g, int x, int y, int grid[][])
{
  for (int i = 0; i < x; i++) 
    {
        for (int j = 0; j < y; j++) 
        {

            if (grid[i][j] == 1) 
            {
                g.fillRect(x, y, 10, 10);
            }
        }
    }  
}

The plan was for the game of life to run inside a for loop which would update the frame graphic, with grid being the current version of the game array, x and y being the grid size and next being the returned array from the LifeSweeper Method. paintComponent would then generate the graphic and place it within the frame, updating within the for loop. However, the JComponent keeps returning an error, stating that the line isn't a statement and how there are missing semi colons. I imagine there is an easier way around this, but I can't find it in the javadoc or other pages.

EDIT: I have tried to run the program as it is, here is the current error/exception message:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at lifegame.LifeGame.LifeSweeper(LifeGame.java:129)
at lifegame.LifeGame.main(LifeGame.java:104)

EDIT 2: The LifeSweeper Method added as requested. Notes have not been added yet, but it runs two series of nested for loops, the first to check and count the neighbouring cells, the second to change the cells according to the rules of life.

public static int[][] LifeSweeper(int[][] next, int a, int b)
{
    int cellFate[][] = new int[a][b];
    int cellsStatus[][] = new int [a][b];
    for (int x = 1; x < next.length-1; x++)
    {
        for (int y = 1; y < next[0].length-1; y++)
        {
            int cellCounter = 0;
            int cellStatus = 0;
            for (int i = -1; i <= 1; i++)   
            {
                for (int j = -1; j <= 1; i++)
                {
                    if (next[i][j] == 1) // Line 129
                    {
                        cellCounter++;
                    }
                    else if (next[0][0] == 1)
                    {
                        cellStatus = 1;
                    }
                }
            }
            cellFate[x][y] = cellCounter - 1;
            cellsStatus[x][y] = cellStatus;
        }
    }
    for (int x = 1; x < next.length-1; x++)
    {
      for (int y = 1; y < next[0].length-1; y++)
      {
          if (cellsStatus[x][y] == 0)
          {
              if (cellFate[x][y] == 0)
              {
                  next[x][y] = 0;
              }
              if (cellFate[x][y] == 3)
              {
                  next[x][y] = 1;
              }
          }
          if (cellsStatus[x][y] == 1)
          {
              if (cellFate[x][y] < 2)
              {
                  next[x][y] = 0;
              }
              if (cellFate[x][y] == 2 || cellFate[x][y] == 3)
              {
                  next[x][y] = 1;
              }
              if (cellFate[x][y] > 3)
              {
                  next[x][y] = 0;
              }
          }
      }
    } 
    return next;
}
c0der
  • 18,467
  • 6
  • 33
  • 65
SIHB007
  • 69
  • 1
  • 10
  • Could you please show us LifeSweeper, marking where line 129 is? The exception says your problem is occurring there. – Brandon McKenzie Feb 06 '19 at 21:21
  • Just added LifeSweeper, line 129 is marked alongside line 104 in the main body, although the JComponent still has the main error in the editor. – SIHB007 Feb 06 '19 at 21:33
  • `JComponent component = paintComponent(Graphics g; x; y; int grid[][]);` this can not compile because `paintComponent` returns void. – c0der Feb 07 '19 at 05:20
  • `JComponent component = paintComponent(Graphics g; x; y; int grid[][]);` this can not compile because `paintComponent` returns void. Also frame content uses `Borderlayout` by default, so by invoking `frame.add(component);` over and over again, you only overwrite the last component placed in `Borderlayout.CENTER` location. There is no need to run `frame.setVisible(true);` more than once. For more help post [mcve] – c0der Feb 07 '19 at 05:33

1 Answers1

0

The exception is saying "hey, you tried to access an element beyond the bounds of your array, which is greater than 0 and less than the size of your array". The immediate problem lies here:

for (int i = -1; i <= 1; i++)   // i starts at -1 
        {
            for (int j = -1; j <= 1; i++) // jstarts at -1  Note that you are incrementing i, which is unrelated to the exception, but still probably not what you want.
            {
                if (next[i][j] == 1) // Line 129  - next[-1][-1] accessed, which is prior to the beginning of the array.  Exception thrown.

In the game of life, you need to consider cases where cells are at the edge of the grid. Before line 129, check to make sure that you do not attempt point to locations outside of the grid.

Another point about line 129, you mention you intend to check the cells neighbors at that location, but from my reading it seems you only ever check the neighbors of cell 0,0. Did you intend to check x+i and y+j? That would accomplish checking the surroundings of cell x and y.

paintComponent seemed okay, but the following snippet from your code also has a few problems that you might consider:

grid = LifeSweeper(grid, x, y); // LifeSweeper looks like a constructor for a class.  Being a function, you should call it lifeSweeper.  Before you posted line 129, I was very confused about why you were trying to construct a LifeSweeper named grid using itself.
grid = next;  //I remain confused about what next is in this context, as your grid already updated, presumably.
JComponent component = paintComponent(Graphics g; x; y; int grid[][]); //This won't compile, and even if it did, it looks like you're calling with a null g and an empty grid.  Probably not what you want.

You are well along the right path, but you ran into the classic edge case everyone who ever did a Game of Life simulation ran into first, myself included when I was learning to code.

As for your paintComponent, there are several problems with the code as written, not the least of which being that you should not actually call paintComponent directly; the windowing system will do it whenever it's needed (which you can signal by calling methods like revalidate() and repaint()). I would have a look at How does paintComponent work, which will put you on the right path.

Brandon McKenzie
  • 1,655
  • 11
  • 26
  • The originial idea was that i and j would be incremented like x and y, moving from cell to cell in the for loops. I'll give that a fresh look. As for the edge issue, the original for loops were able to avoid it, so I'll rewrite the -1 sections to resemble the originals to skip the edges. As for compiling paint component, any suggestions on how let it compile? – SIHB007 Feb 06 '19 at 22:08
  • c0der pointed out that it returns a void, so assigning it is bad. You separated your parameters with semicolons, and type information isn't needed in the actual call. However, the real underlying problem is that you are trying to call it at all; the java windowing system will call it for you as needed. I modified my answer with further information. – Brandon McKenzie Feb 07 '19 at 14:17