[英]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_NUM
和COLS_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.