【问题标题】:For Loop 2D ArrayFor 循环二维数组
【发布时间】:2016-08-10 09:14:58
【问题描述】:

在这个程序中,我想用三个“O”替换随机位置的三个“N”。我尝试使用 forloop 来实现这一点,但是,我得到的“O”的数量是不一致的。我不确定哪个部分出了问题...

static char grid[][];
public static void Board()
{
    Random rn = new Random();
    grid = new char [3][3];
    for(int row = 0; row<grid.length; row++)
    {
        for(int col = 0; col<grid.length; col++)
        {
        grid[row][col] = 'N';     
            for(int i = 0; i<3; i++)
            {
            grid[rn.nextInt(3)][rn.nextInt(3)] = 'O';  
            }
        System.out.print(grid[row][col]);   
        }
        System.out.println();
    }       
}

【问题讨论】:

  • 如果要替换网格中的 3 个单元格,为什么要使用嵌套循环?只需一个循环就足够了,即循环直到您设置 3 个 Os,例如通过随机选择一个,检查它是否包含除 O 以外的其他内容,然后设置它,如果它已经包含 O,则再取一个,直到设置 3 个 Os。当然,如果选择了相同的单元格,这可能会循环很长时间,因此您可能希望跟踪那些仍然可用的单元格。
  • @john 这是你的内部 for 循环中的一个错误。这实际上有效,因为您的行数与列数相同。你应该对照grid[row].length检查col。 @Eran 的答案很好
  • 请注意,将您的问题标题更改为closed thread- solved 是不可接受的方式来标记您的问题已得到回答。如果您得到了您正在寻找的答案,您应该将该答案标记为已接受(单击它旁边的复选标记)。
  • @Eran 哦,我明白了,我已经标记了,非常感谢!

标签: java arrays loops 2d


【解决方案1】:

你需要分开你的循环。

先用Ns初始化数组,然后替换3个Ns:

for(int row = 0; row<grid.length; row++) {
    for(int col = 0; col<grid[row].length; col++) {
        grid[row][col] = 'N'; 
    }
}
for(int i = 0; i<3; i++) {
    grid[rn.nextInt(3)][rn.nextInt(3)] = 'O';  
}

在内部初始化循环中运行 for(int i = 0; i&lt;3; i++) 会导致 3 个随机单元格被分配 O 3x3 次,这些单元格稍后可以被 N 覆盖,因为您是在初始化完成之前执行此操作。

您还应该注意,grid[rn.nextInt(3)][rn.nextInt(3)] = 'O' 分配的单元格可能不是 3 个唯一的单元格,因此您最终可能仍然少于 3 个 Os。

您可以用 while 循环替换第二个循环,以确保恰好替换了 3 个单元格:

int i = 0;
while(i < 3) {
    int x = rn.nextInt(3);
    int y = rn.nextInt(3);
    if (grid[x][y] != 'O') {
        grid[x][y] = 'O';
        i++;
    }  
}

【讨论】:

  • 正如@john 所提到的,内部循环中仍然有一个轻微的错字-应该是grid[row].length
  • 理论上while循环也可以是无限的。
  • @Drgabble 是的,这通常是一种更好的做法,尽管对于方形数组来说没有区别。
  • @Drgabble 你将不得不非常不幸地发生这种情况。
  • 是的!但我会说最好不要这样做
【解决方案2】:

有时一点点抽象会让事情变得更容易。

为什么在你的循环中随机出现一些东西?你的约束是你希望九个数组索引中的三个是“不同的。因此:不要迭代数组并在那里调用随机函数。

只需在 (0,8) 范围内创建随机数,直到获得三个不同的值;然后更新数组中的相应索引。

你看,棘手的部分大约是正好三个;这可以通过如下代码实现:

Set<Integer> randomIndexesToChange = new HashSet<>();
while (randomIndexesToChange.size() < 3) {
 randomIndexesToChange.put( ... another random number from (0, 8) );
}

或者像 RealSceptic 建议的那样,你创建一个集合对象,它只包含从 0 到 8 的所有索引;然后你使用随机播放;然后选择前三个:

List<Integer> allIndexes = Arrays.asList(0, 1, ...
Collections.shuffle(allIndexes);
// now allIndexes is in random order
// so allIndexes.get(0) gives you the first index that should be O

...

【讨论】:

  • 最好使用 shuffle 然后“生成随机数,直到你得到三个不同的值”,理论上这可能是一个无限循环。成语是 - 用序列号创建一个集合,将其随机播放,从随机播放的集合中获取所需数量。
【解决方案3】:

另一种用 3 个随机 Os 填充网格的方法是在初始化时立即执行:

int numOs = 3; 
for(int row = 0; row<grid.length; row++) {
  for(int col = 0; col<grid[row].length; col++) {
    if( numOs > 0 && randomConditionForO() ) {
       grid[row][col] = 'O'; 
       numOs--;
    } else {
       grid[row][col] = 'N';
    }
  }
}

randomConditionForO() 可以是 rn.nextInt() % 2 == 0 等任何东西。如果你想提供设置 O 的概率,比如说 25%,你可以使用类似 rn.nextInt(100) &lt; 25rn.nextFloat() &lt; 0.25f 的东西。

然而,这里的问题是,由于条件的随机性,您可能会得到少于 3 个 Os,因此您可能想要解决这个问题。一种方法可能是同时提供 N 的计数并相应地增加 O 的概率。

例子:

int numOs = 3;
int numNs = gridSize - numOs; //gridSize would be 3x3 = 9 in your example 
for(int row = 0; row<grid.length; row++) {
  for(int col = 0; col<grid[row].length; col++) {
    if( numOs > 0 && rn.nextInt(numNs + 1) < numOs ) {
       grid[row][col] = 'O'; 
       numOs--;
    } else {
       grid[row][col] = 'N';
       numNs--;
    }
  }
}

这里rn.nextInt(numNs + 1) &lt; numOs 意味着选择 O 的概率随着每个选择的 N 增加而随着每个选择的 O 减少。因为 nextInt(bound) 将返回一个介于 0(包括)和 bound(不包括)之间的整数,我们需要传入numNs + 1,这样如果没有更多可用的N,我们使用绑定的1,因为它是独占的,所以我们总是得到0,只要有可用的O,它就会小于numOs(因此得到100 % 概率)。

【讨论】:

    【解决方案4】:

    基于@GhostCats 答案:

    static char grid[][];
    public static void Board()
    {
        int width=3, height=3;
    
        // create new array filled with 'N'
        grid = new char [width][height];
        for(char[] col: grid)
            Arrays.fill(col, 'N');
    
        // create list of all possible indexes
        List<Integer> index = IntStream.range(0,width*height).boxed()
                                         .collect(Collectors.asList());
        Collections.shuffle(index);
    
        // replace first three indexes with 'O'
        for(int i=0; i<3; i++)
            grid[index.get(i)/width][index.get(i)%width] = 'O';    
    }
    

    需要 Java 8。

    【讨论】:

    • 不是反对者,但您还没有真正测试过您的代码,是吗?当您声明 col 时,您引用了 row。而且,建立在别人的答案上,虽然应该被提及,但还不够——你的答案应该独立存在,因此它应该解释正在发生的事情。最好提一下,您也依赖于 Java 8。
    • 仅仅根据别人的回答发布代码看起来很像你想从他们的努力中获利。此外,答案不应该只包含一段代码,还应该解释已经做了什么以及为什么。否则 OP 很难学到一些东西(这显然看起来像是一个学习练习)。
    • 好的,感谢您的反馈。我的想法是,它添加的内容足以被认为是它自己的答案,并且有足够的 cmets 来解释它是如何工作的。以后我会更详细的。
    猜你喜欢
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    • 2019-06-02
    • 2021-05-02
    • 2015-06-12
    • 2013-09-18
    • 2015-10-02
    • 2016-01-20
    相关资源
    最近更新 更多