2016-08-10 3 views
2

в этой программе, я хочу заменить три «N в случайном месте с тремя« O ». я попытался использовать forloop для достижения этого, однако количество «O», которое я получаю, противоречиво. я не совсем уверен, какая часть пошла не так ...Для Loop 2D Array

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(); 
    }  
} 
+0

Если вы хотите заменить 3 ячейки в сетке, почему вы используете вложенные циклы вообще? Достаточно всего одного цикла, т. Е. Петли до тех пор, пока вы не установите 3 Os, например. путем выборочного выбора, проверяя, содержит ли он что-то другое, кроме O, а затем устанавливает его, а если он содержит O, вы принимаете еще один, пока не установите 3 Os. Конечно, это может занять много времени, если будут выбраны одни и те же ячейки, чтобы вы могли отслеживать те, которые все еще доступны. – Thomas

+1

@john - это ошибка на вашем лимите в вашей внутренней петле. Эта работа фактически, потому что у вас одинаковое количество строк, чем столбцы. вы должны проверить col против 'grid [row] .length'. И ответ @Eran - хороший – neomega

+0

Обратите внимание, что изменение названия вашего вопроса на 'closed thread-resolved' не является приемлемым способом, чтобы отметить, что на ваш вопрос был дан ответ. Если у вас есть ответ, который вы искали, вы должны отметить этот ответ как принятый (щелкните галочку рядом с ним). – Eran

ответ

2

Вам нужно отделить свои петли.

Сначала инициализировать массив с N с, а затем заменить 3 N S:

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 O с.

Вы можете заменить вторую петлю с петлей в то время, чтобы убедиться, что ровно 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

, как упоминалось в @john, во внутреннем цикле все еще есть небольшая опечатка - должна быть «сетка [строка] .length' – Drgabble

+0

также теоретически цикл while может быть бесконечным. – Drgabble

+0

@ Drgabble Да, это лучшая практика вообще, хотя для квадратных массивов это не имеет никакого значения. – Eran

1

Иногда немного абстракции делает вещи намного проще.

Почему случайные вещи в вашей петле? Ваше ограничение состоит в том, что вы хотите, чтобы ровно три из девяти индексов массива были «разными». Таким образом: не перебирайте массив и не вызывайте там случайную функцию.

Просто создайте случайные числа в диапазоне от (0,8 .), пока не получили три различных значения, а затем обновить соответствующие индексы в массиве

вы видите, сложная часть о точно три, что может быть достигнуто с кодом, как:

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

Или, как предлагает RealSceptic, вы создаете объект коллекции, который просто содержит все индексы от 0 до 8; и затем вы используете shuffle; чтобы затем выбрать первый три:

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 

...

+1

. Лучше использовать shuffle, чтобы «генерировать случайные числа, пока вы не получите три разных значения», которые теоретически могут быть бесконечным циклом. Идиома - создать коллекцию с серийными номерами, перетасовать ее, взять столько, сколько вам нужно из перетасованной коллекции. – RealSkeptic

+0

@RealSkeptic Хорошая идея, спасибо! – GhostCat

0

Другой подход, чтобы заполнить сетку с 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) < 25 или rn.nextFloat() < 0.25f.

Проблема здесь, однако, заключалась бы в том, что вы могли получить меньше 3-х из-за случайности от состояния, чтобы вы могли противостоять этому. Один из способов может состоять в том, чтобы обеспечить подсчет для Ns и увеличить вероятность для 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) будет возвращать целое число в диапазоне от 0 (включительно) и bound (эксклюзив), мы должны пройти в numNs + 1, так что, если больше нет доступных Ns, мы используем границу 1, и поскольку она является эксклюзивной, мы всегда будем получать 0, что меньше numOs, пока существуют Os (при этом получается 100 % вероятности).

-1

Опираясь на @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.

+0

aw, почему downvote? – Drgabble

+1

Не downvoter, но вы на самом деле не протестировали свой код, не так ли? Вы называете 'row', когда вы объявили' col'. А также, исходя из чужого ответа, хотя его следует упомянуть, недостаточно - ваш ответ должен стоять сам по себе, поэтому он должен объяснить, что происходит. И лучше упомянуть, что вы также полагаетесь на Java 8. – RealSkeptic

+0

Просто код публикации, основанный на чужом ответе, очень похож на то, что вы хотите получить прибыль от своих усилий. Также ответ должен содержать не только блок кода, но и объяснять, что было сделано и почему. В противном случае OP трудно чему-то научиться (и это явно похоже на учебное упражнение). – Thomas