我想在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[][]
成立?
答案 0 :(得分:1)
在聊天中与你交谈后,我们确定你正在制作数独游戏,并且你想存储动作,并且能够撤消这些动作。
您将电路板存储为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
&#39;
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
&#39}的数组,请执行以下操作:
ArrayList<Integer[]> playedValues = ArrayList<Integer[]>();
然后playedValues
将存储Integer
或int
&#39}的数组。
您可以像这样使用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]
);
}
}
如果您像使用2D阵列一样使用ArrayList,但仍然需要ArrayList的所有灵活性和功能,那么请执行以下操作:
ArrayList<ArrayList<Integer>> playedValues = ArrayList<ArrayList<Integer>>();
将playbackValues设置为ArrayList,其中包含保存int
的ArrayLists。与使用int[][]
非常相似,int
使用包含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)
);
}
}
s&#39;的数组的数组。
上面的代码可以使用这个新的ArrayList的ArrayList来实现,如下所示:
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) );
}
如果您想存储,可能是9x9网格,您可以轻松地这样做:
2d array
我在这里看不到使用ArrayList的巨大 需要 。当我看到你的代码并阅读你想要做的事情时,我立即想到// 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]
);
}
}
。
您的代码或我的答案中没有任何内容可以通过二维数组完成。它可能会使事情变得更简单。唯一的问题是,如果您需要动态添加数组。 2d数组不能这样做。
这是与上面相同的实现,带有2d数组:
setCell
public void setCell(int value, int row, int column, int[][] grid) {
grid[row][column] = value;
}
方法:
setCell
int
方法如果我们有一个存储// 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;
}
的数组的ArrayList,我们可以使用此实现更改某个单元格:
gridIndex
问题不在cell
,与NullPointerException
有关。
您可以从int
获得int
,因为所有setCell
在Java中的默认/空值均为0。 请参阅文档 here,here,here,和 this post's answers ,以获取相关证明。 强>
问题不在于cell
方法,而在于cell
变量。由于null
为setCell
,因此抛出 NullPointerException ,而不是您传递给setCell
的任何内容。
正如其他答案所指出的那样,方法setCell
实际上并没有做任何明显的事情。这是因为Java 按值传递,而不是按引用传递。您可以阅读this post了解详细说明。
这背后的意思是,无论您将value
和gridIndex
传递给setCell
的实际数字值,int gridIndex = 10, myValue = 2;
setCell(myValue, gridIndex);
都会有 值 ,但 引用 。
此代码:
setCell
将致电gridIndex
并传递myValue
和setCell
的 值 ,分别为10和2. {{ 1}}方法从不看到实际变量gridIndex
和myValue
,setCell
没有引用这些变量,它只看到 值 10和2.
这可能令人困惑,因为值存储在setCell
内的变量中,您指定的变量是参数名称(int value,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。
答案 1 :(得分:-1)
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的值,也不编辑任何变量。它什么都不做,因为它改变的唯一值是在其签名中声明的值,并且当方法退出时会丢失。