1

In a Game Of Life project that I'm working on, I have a 2D array of bytes. The array represents a gameboard. The problem is that when I try to access the array, it returns all zeroes. But, in the function where I set a cell, changes save just fine.

Here's the class:

public class Game {
    int boardW;
    int boardH;
    Board board;
    public Game(int bW) {
        boardW = bW;
        boardH = bW;
        this.board = new Board(boardH, boardW);
    }

    private byte updateCell(int x, int y) {
        byte neighbors = 0;
        // Loop through 8 neighbors and count them
        for (byte offset_y = -1; offset_y < 2; offset_y++) {
            for (byte offset_x = -1; offset_x < 2; offset_x++) {
                // Make sure we don't check our current cell
                if (offset_x != 0 || offset_y != 0) {
                    byte newY = (byte) (y + offset_y);
                    byte newX = (byte) (x + offset_x);
                    // Roll over edge of board
                    if (y + offset_y < 0) {
                        newY = (byte) (boardH - 1);
                    }
                    else if (y + offset_y >= boardH) {
                        newY = 0;
                    }
                    if (x + offset_x < 0) {
                        newX = (byte) (boardW - 1);
                    }
                    if (x + offset_x >= boardW) {
                        newX = 0;
                    }
                    neighbors += this.board.getState(newX, newY);
                }
            }
        }
        if (neighbors < 2) {return 0;}
        if (neighbors > 3) {return 0;}
        if (neighbors == 3) {return 1;}
        return this.board.getState(x, y);
    }

    public Board gameTick() {
        Board nextTick = new Board(boardH, boardW);
        // Go through next iteration of cells
        for (int h = 0; h < boardH; h++) {
            for (int w = 0; w < boardW; w++) {
                nextTick.setState(w, h, updateCell(w, h));
            }
        }
        return nextTick;
    }

    public Board getBoard() {

        return this.board;
    }

    public void toggleCell(int x, int y, byte state) {
        this.board.setState(x, y, state);
    }
}

class Board {
    private final byte[][] board;
    final int height;
    final int width;

    public Board(int h, int w) {
        width = w;
        height = h;
        board = new byte[height][width];
    }

    public void setState(int x, int y, byte state) {
        board[y][x] = state;
    }

    public byte getState(int x, int y) {
        return board[y][x];
    }

    public byte[][] getData() {
        return board;
    }

    public void setData(byte[][] newBoard) {
        for (int x = 0; x<newBoard.length; x++) {
            for (int y = 0; y<newBoard.length; y++) {
                setState(x, y, newBoard[y][x]);
            }
        }
    }
}

What is going on here?

EDIT: Turns out it was another problem in the code that accessed the board, which I solved. Thanks for all your help guys.

Slickytail
  • 15
  • 2
  • 4
  • 2
    Post a complete minimal example reproducing the problem. We can't diagnose from the 5 lines of code you posted. – JB Nizet Sep 11 '15 at 16:22
  • 1
    @Want2bExpert - what do you mean by a "global variable"? We are in Java, not in C++! – Honza Zidek Sep 11 '15 at 16:23
  • @HonzaZidek There are such things as "global variables" in java, fyi. http://stackoverflow.com/questions/4646577/global-variables-in-java – jgabb Sep 11 '15 at 16:36
  • 1
    @jgabb: if you mean `static` variable of a class, that's exactly what the OP uses, unfortunately. You may notice that they access the `board` variable in the `static` context. And the advice to use `global variable` is here **intrinsically wrong**! – Honza Zidek Sep 11 '15 at 16:41
  • @HonzaZidek: the methods are being called in a game loop. Subsequent calls meaning that after I call that method the first time, the set method alone recognizes the variable as having changed. – Slickytail Sep 11 '15 at 16:44
  • Now when you placed here your code, tell us what you *expect* it to do and what it actually *does*. How are you observing it is broken? – Honza Zidek Sep 11 '15 at 20:13

4 Answers4

3

Change the design of your code completely. Have a wrapper class Board which encapsulates (and hides) the two-dimensional array (if it must be an array at all) inside.

public class Board {
    private final byte[][] board;

    public Board(int height, int width) {
        board = new byte[height][width];
    }

    public void setState(int x, int y, byte state) {
        board[y][x] = state;
    }

    public byte getState(int x, int y) {
        return board[y][x];
    }
}

Then create an instance of the Board class and access the state only via that one.

Thus you will have safe access to your data and your design is open for modifications in the future. You are e.g. free to start adding useful methods such as

boolean isRowEmpty(int x)
boolean isColumnEmpty(int y)
void resetRow(int x)
void resetColumn(int y)
void reset()

All of them will be nicely called on an instance of the Board class. You will not access the array directly from your business logic code, which is a nasty practice.

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118
0

This appears to be a scoping issue, so the solution is to make sure that board is defined in a scope that all your methods have access to. The cleanest way to do this is to define board as a class field (i.e. it is defined outside of any method), and then every time you want to modify or access board, you use this.board.

For example,

public class Board{

   private byte[][] board;

   public Board(int height, int width){
      this.board = new byte[height][width];
   }

   public byte[][] getBoard(){
      return this.board;
   }

   public void setCell(int x, int y, byte state){
      System.out.println(this.board[y][x]);
      this.board[y][x] = state;
   }
}
F. Stephen Q
  • 4,208
  • 1
  • 19
  • 42
  • The idea of having a setter for a single cell, but a getter for the whole array stinks. Of course it is possible, but most probably shows something suspicious in the design. It would be much better to have a wrapper class Board which would encapsulate (and HIDE) the two-dimensional array (if it must be an array at all) inside. – Honza Zidek Sep 11 '15 at 17:03
0

I would suggest that you make two different classes one main and other for calling the function, In this from main class pass the value you want , and call the method you want this will surely solve the problem.

Tom
  • 16,842
  • 17
  • 45
  • 54
Saul_goodman
  • 141
  • 12
0

Try this:

public class YourClassName {
    byte[][] board;

    // Setters
    public void setCell(int x, int y, byte state) {
        System.out.println(board[y][x]);
        board[y][x] = state;
    }

    // Getters
    public byte[][] getBoard() {
        return board;
    }
}
Tom
  • 16,842
  • 17
  • 45
  • 54
Want2bExpert
  • 527
  • 4
  • 11
  • Thank you! Will try when I get home. – Slickytail Sep 11 '15 at 16:45
  • The idea of having a setter for a single cell, but a getter for the whole array stinks. Of course it is possible, but most probably shows something suspicious in the design. It would be much better to have a wrapper class Board which would encapsulate (and HIDE) the two-dimensional array (if it must be an array at all) inside. – Honza Zidek Sep 11 '15 at 16:50