【问题标题】:Passing a specific index of an ArrayList<String[]> but String is actually a String[][]传递 ArrayList<String[]> 的特定索引,但 String 实际上是 String[][]
【发布时间】:2021-01-20 17:18:36
【问题描述】:

很抱歉,如果没有很好地解释或者不是解决这个问题的正确方法,但我是编码新手,这是我在这里的第一个问题,所以放轻松。无论如何,我正在尝试制作一个琐事游戏,其中我的代码从单独的文本文件中读取问题和答案,并将它们中的每一个保存到自己的 ArrayList 中。每个问题都保存到ArrayList&lt;String&gt; 类型的特定索引中。现在对于我的答案,我将每个问题的特定答案保存到单独的二维字符串数组 (String[1][4]) 中,以便稍后转移到自己的答案ArrayList&lt;String[]&gt;。这样,两个 ArrayList 的索引都匹配(问题与他们的答案)。我想创建自己的 shuffle 方法,这样 ArrayList 与它们之间的匹配索引保持等效。现在我的代码确实可以完美运行,然后突然决定这是一个糟糕的主意!过去几天我一直在尝试以 0 运气修复它。我的问题在于我试图打乱每一个问题的答案;这样,答案选项的顺序永远不会相同。我的代码如下:

private static void shuffle(ArrayList<String> questions,
                            ArrayList<String[]> answers) {
    int chosenIndex;
    int questionsSize = questions.size();
    for (int i = 0; i < questionsSize - 1; i++) {
        chosenIndex = (int) (Math.random() * questionsSize);
        swap(i, chosenIndex);
        for (int j = 0; j < answers.get(i).length; j++) {
            int answerIndex = (int) (Math.random() * answers.get(i).length);
            swapAnswers(i, j, answerIndex);
        }
    }
}
private static void swap(int i, int j) {
    String temp = questions.get(i);
    String[] temp2 = answers.get(i);

    questions.set(i, questions.get(j));
    answers.set(i, answers.get(j));

    questions.set(j, temp);
    answers.set(j, temp2);
}
private static void swapAnswers(int i, int j, int a) {
    for (String[] row : answers) {
        String currentColIndexCopy = row[j];
        String randomIndexToSwitch = row[a];

        row[j] = randomIndexToSwitch;
        row[a] = currentColIndexCopy;

        break;
    }
}

现在我的代码再次 100% 工作,但我必须做了一些微小的事情,因为现在当它到达我的 swapAnswers() 中的每个循环时,我的答案永远不会改变我的 ArrayList&lt;String[]&gt; 答案的正确索引。我还没有注意到任何趋势。代码的工作原理是,在shuffle() 中,第一个 for 循环对两个 ArrayList 进行了洗牌,因此它们的索引对应。然后第二个 for 循环打乱了问题的答案,但是一旦我到达swapAnswers(),for each 循环的答案变量与当前问题的答案不一致! (我的意思是在shuffle() 中,我的第一次迭代会打乱所有答案,但是当我增加到下一个问题时,swapAnswers() 中的答案变量可能会保留在前面的问题答案中)就像我说的我还是很新所以也许这是某个地方的语法错误,但我已经尝试了所有方法,但似乎无法让这个东西再次工作!

注意:这些是类变量,问题和答案都保存在

public static ArrayList<String> questions;
public static ArrayList<String[]> answers;

它们是静态的,这意味着(我认为)可以在课堂上的任何地方轻松访问它们。当我调用 shuffle() 时,我将这些作为参数传递,我认为这是不必要的,但这样做是为了保证安全。制作这个时我唯一不明白的是,我最初如何能够将每个答案 String[][] 传递给 swapAnswers() 但我让它工作了,所以直到它停止我才质疑它。我只是假设它知道它正在使用的当前对象。我试图为每个循环制作

for (String[] row : answers.get(i))

其中 i 是参数;它来自shuffle() 的当前 i 索引,并且答案将返回 String[][] 但出现错误并且不太确定为什么?我知道发生的事情很小,就像可能使一个方法成为实例而不是静态的,但如果你能够发现我的错误,那就太好了!

附:根据我目前所学到的,使用 ArrayList 似乎是编写这个程序的一种很好且有条理的方式,但我从这里的几个问题中读到从未使用过;或者至少避免ArrayList&lt;String[]&gt;,我不太清楚为什么?对我来说,我相信它可以让我的对象在很多方面变得更加可变,但我可能是错的,如果我解释为什么不这样做,更好的选择对我的理解来说会很棒。此外,您可能已经看到我可能犯的任何其他错误或想法,这些错误或想法可能有缺陷、错误或只是采取的愚蠢路线,我们将不胜感激!我是自学的,所以任何事情都有帮助。谢谢

【问题讨论】:

    标签: java arraylist multidimensional-array reference pass-by-reference


    【解决方案1】:

    我也是新手。我注意到你的 swapAnswers 写错了。它是如何编写的,它总是只会打乱答案的第一个索引,因为你传入 int i 但从不使用它。正确的方法如下。

    private static void swapAnswers(int i, int j, int a) {
        String[] row = answers.get(i);
        String currentColIndexCopy = row[j];
        String randomIndexToSwitch = row[a];
    
        row[j] = randomIndexToSwitch;
        row[a] = currentColIndexCopy;
    }
    

    我建议不要创建两个问题和答案列表,而是创建一个名为 Card 的类,该类将包含一个字符串问题和一个列表答案。这将有助于避免此类情况,并有助于提高编码质量。然后,您可以创建函数将其保存为两个列表格式并从两个列表格式加载它。

    我还注意到您的第一个函数 shuffle 中的一个潜在错误,其中 for (int i = 0; i &lt; questionsSize - 1; i++) 应该是 for (int i = 0; i &lt; questionsSize; i++)。你的代码永远不会洗牌最后一个索引,除非你的幸运和最后一个索引被随机选择与前面的索引一起洗牌。

    您的原始代码:for (String[] row : answers.get(i)) 不起作用的原因是因为 answers.get(i) 返回一行 (String[] row) 而不是可迭代的。

    我不知道为什么人们说要避免使用ArrayList&lt;String[]&gt;,但这可能是因为你所经历的那样令人困惑。您应该始终致力于在列表中仅包含对象或基本数据类型(字符串、浮点数等)。

    【讨论】:

    • 这实际上也是我尝试过的东西,发现经过几次运行后,它似乎工作得很好,但我注意到一个小逻辑错误是,如果第一个索引每次递增交换 1,那么这意味着相应的答案索引将是唯一被打乱的索引。这意味着我应该创建一个新的对象列表,它是答案的副本,并使用该列表来增加和交换答案。然后将新列表的随机答案返回到原始列表;如果我是对的?这比我最初知道的代码添加了更多代码,现在回想起来似乎很奇怪。
    • 我明白了,这很有意义,而且绝对看起来是一种更有条理的方法,谢谢!很好,谢谢你的解释!这就是我的假设,我真的看不出它是如何工作的,但从我记得我的代码完美运行的情况来看,我想说它就在那里(这就是我发布这个问题的原因)。罗杰,再次感谢你的帮助和详细的解释,他们真的很有帮助,终于让我继续我的程序!!!
    • 很高兴能帮上忙!我认为您创建答案副本的想法可能会奏效,但它不是很漂亮。如果你使用 Card 类方法,你可以处理洗牌的一种方法是给每个类一个名为 order 的属性,它是一个浮点数,当你想要洗牌时,只需为每张牌调用 random 并将其存储在 order 变量中,然后然后从低到高排序。这会给你一个随机的顺序,也可以用答案来完成,虽然它也不一定漂亮。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多