[英]Store 2d array positions in ArrayList
我想在ArrayList中存儲幾個2d數組位置,並按如下所示進行設置:
ArrayList<Integer> playedValues = new ArrayList<Integer>();
playedValues.add(dataArray[0][1]);
playedValues.add(dataArray[0][2]); //example of adding 2d array positions
int size = playedValues.size(); //get size of ArrayList
int gridIndex = playedValues.get(size - 1); //trying to set gridIndex to dataArray[0][2]
cell.setCell(0, gridIndex); //this is where the error occurs
//trying to pass gridIndex to here
public void setCell(int value, int gridIndex) {
gridIndex = value;
}
我的問題是,當我嘗試將gridIndex
作為參數傳遞給setCell
,得到了NullPointerException 。
我將其傳遞給的方法在我的測試中似乎可以正常工作,因此我認為gridIndex is not being set properly
。 如何使playedValues
本身存儲dataArray[][]
而不是dataArray[][]
持有的信息?
在與您聊天后,我們確定您正在制作Sudoku游戲,並且您想要存儲移動並能夠撤消這些移動。
您將板存儲為sudokuGrid
,它是一個2d int數組。 您需要能夠對某些單元格(行,列)進行更改。 您還需要能夠存儲移動(行,列)和順序。 然后,您可以同時使用這兩個功能,並允許用戶撤消其移動。
讓我們專注於首先更改單元格。
我們可以編寫一個方法,該方法接受一行和一列,然后將(行,列)單元格的值改回0。(撤消移動)。
我們應該可以像這樣調用此方法:
int testRow = 4, testColumn = 1;
undoMove(testRow, testColumn, sudokuGrid);
當然,稍后我們將使用先前動作中的行和列,但是我們現在需要能夠進行測試。 undoMove
方法的編寫方式如下:
public void undoMove(int row, int column, int[][] board) {
board[row][column] = 0;
}
這是非常重要的,我們在傳遞sudokuGrid
到undoMove
。 否則, undoMove
將無法對游戲板進行永久更改。 您可以閱讀下面我提供的鏈接,以獲取有關為何能夠對sudokuGrid
進行更改的更多信息。
現在,我們需要集中精力存儲動作。
我們有一些可用的選項,但是我認為最簡單的方法是創建一個ArrayList並將其中的Move
存儲在其中。 當然,Java尚未為我們定義Move
。 我們將必須創建自己的類來定義Move
。
這是我們的Move
類的樣子:
class Move {
int row, column;
public Move(int row, int column) {
this.row = row;
this.column = column;
}
}
public void undoMove(int row, int column, int[][] board) {
board[row][column] = 0;
}
這只是說每個Move
將有一行,一列。 現在,我們可以存儲每個動作在其中的單元格的行和列。
現在,我們可以創建一個ArrayList來保存Move
:
ArrayList<Move> moves = new ArrayList<Move>();
每次用戶移動時,我們都可以創建一個Move對象,如下所示:
// You'll need to get the row and column
// before you make the Move object
Move currentMove = new Move(row, column);
現在,只要我們想撤消任何動作,我們都可以簡單地做到這一點:
Move moveToUndo = moves.get( moves.size() - 1 );
undoMove(moveToUndo.row, moveToUndo.column, sudokuGrid);
moves.remove( moves.size() - 1 );
class Move {
int row, column;
public Move(int row, int column) {
this.row = row;
this.column = column;
}
}
public void undoMove(int row, int column, int[][] board) {
board[row][column] = 0;
}
// Later on, in your game loop method
ArrayList<Move> moves = new ArrayList<Move>();
// Adding moves
// In your program, you'll get the row and column from what
// the user types in or clicks on.
int row = 1, column = 7;
moves.add( new Move(row, column) );
row = 6, column = 8;
moves.add( new Move(row, column) );
// Undo'ing moves
Move moveToUndo = moves.get( moves.size() - 1 );
undoMove(moveToUndo.row, moveToUndo.column, sudokuGrid);
moves.remove( moves.size() - 1 );
您甚至可以重寫undoMove
方法以接受Move
,而不是一行和一列,這看起來非常干凈。 您也可以編寫一個方法undoLastMove
,該方法可以自動完成某些過程。
我不太確定您打算將ArrayList playedValues
用途,因此我不得不做出一些有根據的猜測,即您想讓ArrayList保存數組,而不是單個值。
那很簡單!
您當前的聲明:
ArrayList<Integer> playedValues = ArrayList<Integer>();
設置playedValues
以容納Integer
或int
值。 要改為設置playedValues
以容納int
的數組,請執行以下操作:
ArrayList<Integer[]> playedValues = ArrayList<Integer[]>();
然后playedValues
將存儲Integer
或int
的數組。
您可以像這樣使用ArrayList:
ArrayList<Integer[]> playedValues = ArrayList<Integer[]>();
int[] arrayOne = {1, 2, 3, 4, 5};
// Adding arrays to the list
playedValues.add(arrayOne);
// Iterating through all arrays in playedValues
for(int i = 0; i < playedValues.size(); i++) {
int[] currentArray = playedValues.get(i);
// Then, of course, you can loop over each array like normal:
for(int j = 0; j < currentArray.length; j++) {
System.out.println(
"Array #" + i + " - Element #" + j + " = " + currentArray[i][j]
);
}
}
如果您使用ArrayList的方式與使用2D數組的方式相同,但是您仍然想要ArrayList的所有靈活性和功能,請執行以下操作:
ArrayList<ArrayList<Integer>> playedValues = ArrayList<ArrayList<Integer>>();
那將playedValues設置為一個ArrayList,其中保存了包含int
的ArrayList。 與使用int[][]
非常相似,后者使用一個數組來保存持有int
s'的數組。
可以使用新的ArrayLists ArrayList來實現上述代碼,如下所示:
ArrayList<ArrayList<Integer>> playedValues = ArrayList<ArrayList<Integer>>();
int[] arrayOne = {1, 2, 3, 4, 5};
// Adding values to the playedValues
playedValues.add( Arrays.asList(arrayOne) );
// Iterating through all values in playedValues
for(int i = 0; i < playedValues.size(); i++) {
for(int j = 0; j < playedValues.get(i).size(); j++) {
System.out.println(
"Row #" + i + " - Column #" + j + " = " + playedValues.get(i).get(j)
);
}
}
如果您想存儲(可能是9x9的網格),則可以像這樣輕松地進行操作:
ArrayList<ArrayList<Integer>> playedValues = ArrayList<ArrayList<Integer>>();
int[] sampleRow = {0, 0, 0, 0, 0, 0, 0, 0, 0};
for(int i = 0; i < 9; i++) {
playedValues.add( Arrays.asList(sampleRow) );
}
我認為這里不需要使用ArrayList。 當我看到您擁有的代碼並閱讀您要執行的操作時,我立即想到2d array
。
在您的代碼或我的答案中,沒有任何事情是二維數組無法完成的。 這也可能使事情變得更簡單。 唯一的問題是,是否需要動態添加陣列。 2d數組無法做到這一點。
這是與上述相同的實現,帶有2d數組:
// 100 for rows and columns was chosen arbitrarily.
int[][] playedValues = new int[100][100];
int[] arrayOne = {1, 2, 3, 4, 5};
int[] arrayTwo = {1337, 9001, 1111111, 22222, 33333, 444, -1, -123, 246};
// Adding arrays to the list
playedValues[0] = arrayOne;
playedValues[1] = arrayTwo;
// Iterating through all arrays in playedValues
for(int i = 0; i < playedValues.length; i++) {
for(int j = 0; j < playedValues[i].length; j++) {
System.out.println(
"Array #" + i + " - Element #" + j + " = " + currentArray[i][j]
);
}
}
和setCell
方法:
public void setCell(int value, int row, int column, int[][] grid) {
grid[row][column] = value;
}
setCell
方法 如果我們有一個存儲int
數組的ArrayList,則可以使用此實現更改某個單元格:
// Making a call to set the cell in the 1st row at the 4th column, to 0
setCell(0, 1, 4, playedValues);
public void setCell(int value, int row, int column, ArrayList<Integer[]> grid) {
int[] rowArray = grid.get(row);
rowArray[column] = value;
}
問題不gridIndex
,而是cell
。
您可以從int
獲取NullPointerException
,因為在Java中所有int
的默認/空值均為0。 有關證明 , 請參見 此處 , 此處 , 此處 的文檔 以及 本文的答案 。
所以問題不在於setCell
方法,而是與您的cell
變量有關。 由於cell
為null
而不是傳遞給setCell
任何東西,因此引發NullPointerException 。
正如其他答案所指出的,確實是setCell
方法實際上不會做任何明顯的事情。 這是因為Java是按值傳遞的 ,而不是按引用傳遞的 。 您可以閱讀這篇文章以獲取詳細說明。
這在幕后的意思是,無論您傳遞給setCell
作為value
和gridIndex
任何實際數字值, setCell
都將具有的值 ,但沒有引用 。
這段代碼:
int gridIndex = 10, myValue = 2;
setCell(myValue, gridIndex);
將調用setCell
並傳遞gridIndex
和myValue
的值 (分別為10和2) setCell
方法從不看到實際變量gridIndex
和myValue
, setCell
沒有引用這些變量,它僅看到值 10和2。
這可能會造成混淆,因為值存儲在setCell
內的變量中, setCell
是您指定為參數名稱的變量(int值,int gridIndex),但這些變量不是傳遞給setCell
的變量。 參見以下代碼:
public static void main(String[] args) {
int gridIndex = 10, myValue = 9999;
setCell(myValue, gridIndex);
System.out.println(gridIndex);
}
public static void setCell(int value, int gridIndex) {
// In here, value is NOT the same variable, myValue, that
// we passed in. Just the same, gridIndex, is not the same
// variable that we passed in from main.
// In here, value and gridIndex have the SAME VALUES
// as the variables we pass in, but they are not the same
// variables. They are newly made variables, with the same values.
}
還要看下面的代碼:
public static void main(String[] args) {
setCell(10, 9999);
System.out.println(gridIndex);
}
public static void setCell(int value, int gridIndex) {
gridIndex = value;
}
我們沒有將變量傳遞給setCell
,但是在setCell
內部,我們將變量gridIndex
更改為等於value
。 這會告訴Java,數字9999的新值實際上應該是10嗎? 當然不是。 我們沒有更改傳入的內容,而是更改了保存傳入值的變量。
考慮發生情況的一種簡單方法是記住,每當在Java中使用int
變量時,都可以將變量名替換為其持有的值,並且代碼將保持完全相同。
以下面的代碼為例:
int gridIndex = 10, myValue = 9999;
setCell(myValue, gridIndex);
等效代碼為:
setCell(10, 9999);
正如我們在上面看到的,我們當然不能更改10或9999的值。我們不能僅僅確定數字等於其他數字。 當然,我們可以更改int
中保存的數字,但是沒有任何int
變量傳遞給setCell
,只有數字值(如10或9999)。
public void setCell(int value, int gridIndex) {
gridIndex = value;
}
上面的代碼什么都不做。 它需要兩個參數,並將其中一個參數本地設置為另一個。 然后,由於兩個變量都在函數中聲明,因此退出時它們都消失了。
由於此方法僅設置gridIndex,為什么不直接設置它呢?
gridIndex = 0;
編輯:為什么這不起作用的示例。
我在IDE中進行了嘗試-它與您擁有的setCell方法完全相同。
public static void main(String[] args) {
int gridIndex = 10;
setCell(0, gridIndex);
System.out.println(gridIndex);
}
public static void setCell(int value, int gridIndex) {
gridIndex = value;
}
控制台顯示10,因為setCell不執行任何操作。 它不設置gridIndex的值,也不編輯任何變量。 它什么也不做,因為它更改的唯一值是在其簽名中聲明的值,並且在方法退出時丟失。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.