繁体   English   中英

如何在Java中制作动态2D数组?

[英]How to make dynamic 2d array in Java?

我一直在环顾四周,但找不到任何解决我的问题的方法。

我有这种方法可以为游戏创建棋盘:

public void createBoard(Canvas canvas) {
    ROWS_NUM = (int) canvas.getHeight() / rectangleSize;
    COLS_NUM = (int) canvas.getWidth() / rectangleSize;
    grid = new Cell[COLS_NUM][ROWS_NUM];

    for (int x = 0; x < COLS_NUM; x++) {
        for (int y = 0; y < ROWS_NUM; y++) {
            grid[x][y] = new Cell();
            grid[x][y].setAndUpdateState(false);
        }
    }
}

问题是,每当我添加一个大于ROWS_NUMCOLS_NUM的值时,我都会像ROWS_NUM那样超出数组索引。 我想使数组动态化,我想知道我该怎么做。 我必须将数组转换为ArrayList还是将HashMap更好? 如果我希望行和列都是动态的,该怎么办?

这不是那么容易。

您当然可以将您的网格表示为List<List<Cell>>

 public Cell getCell(int x, int y) {
       return grid.get(x).get(y);
 }

但是,这并不能让您免费分配任何旧号码:

  List<String> list = new ArrayList<>();
  list.set(5,"Hello");

...也会抛出IndexOutOfBounds异常。

您可以list.add(string)多次,并且每次列表都会增长。 但是您不能set()超出其当前大小。

但是,如果您知道每个网格位置都需要一个像元对象,并且知道它每次增长,它就会增长一个,那么就编写算法使用add()而不是set() ,这样的结构就可以很好地工作。


或者,按照您的建议, HashMap<Coordinates, Cell> 可能适合您的需求。

您将需要一个合适的Coordinates类,并具有有效的hashCode()equals()实现。 然后,您可以执行以下操作:

   Map<Coordinates, Cell> grid = new HashMap<>();
   grid.put(new Coordinates(80, 100), new Cell());

如果您想要一个“人烟稀少”但实际上不受限制的“网格”,这将特别有用。

还有许多其他方法-包括实现自己的数组重新分配算法(毕竟,这就是ArrayList内的内容-如果您好奇的话,请查找并研究其源代码)。


您可能还应该退后一步,问一问为什么以及何时需要在初始化网格后更改网格的大小。 固定大小数组的固定大小数组是一种简单的解决方案,如果大多数情况下都可以使用,则值得坚持。 如果大小只是偶尔变化,那么最好创建一个新的网格并将旧值复制到其中,这会更好。

  public void setCell(int x, int y, Cell cell) {
     if(x >= this.grid.length || y >= this.grid[0].length) {
          Cell[][] newGrid = createEmptyGrid(x,y);
          copyCells(this.grid,newGrid);
          this.grid = newGrid;
     }
     this.grid[x][y] = cell;
  }

createEmptyGrid()在此需要确定新大小-刚好足以容纳[x][y]吗? 还是更大的案例? 正确的做法取决于您的广泛要求。

更好的选择是使用Java 列表来实现所需的逻辑:

List<List<Cell>> grid = new ArrayList<>();

for (int x = 0; x < COLS_NUM; x++) {
    List<Cell> cells = new ArrayList<>();
    for (int y = 0; y < ROWS_NUM; y++) {
        cells.add(new Cell());
    }
    grid.add(cells);
}

public boolean isAlive(int x, int y) {
    List<Cell> cells = grid.get(x);
    Cell cell = cells.get(y);        
    return cell != null && cell.getState();
}

使用ArayList(ArrayList可以动态更改其大小)

ArrayList<ArrayList<Integer>> grid= new ArrayList<ArrayList<Integer>>();

您可以使用ArrayList ,但是要插入任何索引而不必担心越界,您希望将嵌套Map与一种特殊的插入或检索方法一起使用。

Map<Integer, Map<Integer, Cell>> grid = new HashMap<Integer, Map<Integer, Cell>>();

for (int x = 0; x <= COLS_NUM; x++) {
    Map inner = new HashMap<Integer, Cell>();
    for (int y = 0; y < ROWS_NUM; y++) {
        inner.put(y, new Cell());
    }
    grid.put(x, inner);
}

现在,您可以创建一个方法,使用以下任何索引将单元格设置到网格中:

 public void setCell(Map<Integer, Map<Integer, Cell>> grid, Cell newCell, int x, int y) {
    if (grid.containsKey(x)) {
        grid.get(x).put(y, newCell);
    } else {
        grid.put(x, (new HashMap<Integer, Cell>().put(y, newCell)));
    }
}

以及一种检索单元格的方法:

     public Cell getCell(Map<Integer, Map<Integer, Cell>> grid, int x, int y) {
     try {
         Cell found = grid.get(x).get(y);
         return found;
     } catch (NullPointerException npe) {
         return null;
     }
 }

为了使此功能有用,您需要创建一个自定义类,该类为您管理这些映射和插入/检索方法,以及对应用程序有用的其他功能。

这是使用列表的更简单选项。 如上所述,这无法避免您获得IndexOutOfBoundsException的可能性。

int ROWS_NUM = (int) canvas.getHeight() / rectangleSize;
int COLS_NUM = (int) canvas.getWidth() / rectangleSize;

List<List<Cell>> array = new ArrayList<List<Cell>>();

for (int x = 0; x < COLS_NUM; x++) {
    List inner = new ArrayList<Cell>();
    for (int y = 0; y < ROWS_NUM; y++) {
        inner.add(new Cell());
    }
    array.add(inner);
}

您仍然可以通过以下方式访问特定单元格(相当于数组中的array [x] [y]:

// Find equivalent of arr[2][3]
Cell found = array.get(2).get(3);

但是,由于您指定希望能够使用任何索引访问单元而不会出现超出范围的异常,因此可以选择使用Maps来实现它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM