gpt4 book ai didi

java - 将二维数组位置存储在ArrayList中

转载 作者:行者123 更新时间:2023-12-01 10:03:10 26 4
gpt4 key购买 nike

我想在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

如果您不熟悉制作课程,则可以学习基础知识 herehere

这是我们的 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问题

我不太确定您打算将ArrayList playedValues用于什么,因此我不得不做出一些有根据的猜测,即您想让ArrayList保存数组,而不是单个值。

那很简单!

您当前的声明:

ArrayList<Integer> playedValues = ArrayList<Integer>();


设置 playedValues以保存 Integerint值。要改为设置 playedValues来保存 int的数组,请执行以下操作:

ArrayList<Integer[]> playedValues = ArrayList<Integer[]>();


然后 playedValues将存储 Integerint的数组。

您可以像这样使用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,其中包含ArrayList,这些ArrayList包含 int。与使用 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吗?

我认为这里不需要使用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方法

如果我们有一个ArrayList存储 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;
}




原始错误

问题不在于 gridIndex,而在于 cell

您可以从 NullPointerException获得 int,因为Java中所有 int的默认/空值均为0。有关证明,请参见文档 herehereherethis post's answers

因此,问题不出在 setCell方法上,而是在您的 cell变量上。因为 cellnull,而不是传递给 setCell的任何内容,所以引发NullPointerException。



为什么setCell最初不起作用

正如其他答案所指出的,方法 setCell确实不会做任何明显的事情。这是因为Java是按值传递,而不是按引用传递。您可以阅读 this post以获得详细说明。

这在幕后的意思是,无论您以 setCellvalue的形式传递给 gridIndexsetCell的实际数字值是多少,而没有引用。

这段代码:

int gridIndex = 10, myValue = 2;
setCell(myValue, gridIndex);


将调用 setCell并传递 gridIndexmyValue的值(分别为10和2)。 setCell方法从不看到实际的变量 gridIndexmyValuesetCell没有引用这些变量变量,则只会看到值10和2。



这可能会造成混淆,因为值存储在 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)。

关于java - 将二维数组位置存储在ArrayList中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36661169/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com