For循环二维数组

For Loop 2D Array

在这个程序中,我想用三个 '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();
    }       
}

你需要分开循环。

先用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<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++;
    }  
}

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

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

只需在 (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

...

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

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) < 25rn.nextFloat() < 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) < numOs 意味着选择 O 的概率随着每个选择的 N 而增加,并随着每个选择的 O 而减少。因为 nextInt(bound) 将 return 0 之间的整数(包括) 和 bound (不包括)我们需要传入 numNs + 1 以便如果没有更多 Ns 可用我们使用绑定 1 因为它是排他的我们总是得到 0,它小于numOs只要有Os个可用(从而得到100%的概率)。

基于@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.