2014-11-11 7 views
0

Я пытаюсь заполнить свой 2d-массив, который равен 5 на 5 с символом, таким как A в случайных координатах в массиве 2d. Когда я использую свой вложенный цикл for, я хотел бы сделать координаты массива 2d, где мой char будет случайным. Так что давайте скажем, что я попросил 40 процентов A, в 5 на 5 я должен получить 10 A, но я получаю 8. Когда я запускаю его, он не показывает процентного количества A, которого я хотел иногда. он будет печататься только как 6. Это потому, что когда строка и col в операторе if рандомизированы, то есть строка и col в цикле for? Именно поэтому char иногда заполняет меньше, чем запрос, потому что цикл for останавливается, если число рандомизирует длину массива 2d, который равен 5?Java Math.random с массивами

Также, когда он распечатывает 10 символов, иногда они проходят по 5 на 5. Пример будет равен 2 Как в строке, так и 7 во втором и 1 в третьем. Почему это?

public static void grid(char[][] arr, int percentofchar) 
{ 

    double charx = 0.0; 

    double totalpercentchar = 0; 
    totalpercentchar = (double) percentofchar/100; 

    cellx = totalpercentchar * (arr.length * arr.length); 

    for (int row = 0; row < arr.length; row++) 
    { 
    for (int col = 0; col < arr[row].length; col++) 
    { 
     if (charx > 0) 
     { 
     row = (int) (Math.random() * arr.length); 
     col = (int) (Math.random() * arr.length); 
     charx--; 
     arr[row][col] = 'A'; 
     System.out.print(arr[row][col] + " "); 
     } 
    } 
    System.out.println(); 
    } 
} 
+0

Это ваш оригинальный код? 'cellx' похоже, что это должно быть' charx'? –

+0

Да, я сделал cellx первым, чтобы сделать свой char 'X', но потом понял, что это может быть любой символ, так что изменил имя, пропустил это, спасибо, указав его! –

+0

также имел кучу классов с одним и тем же кодом, чтобы попробовать разные способы, чтобы быть причиной, почему я пропустил это. –

ответ

2

ваш код не должен быть чем-то вроде

public static void grid(char[][] array, int percentOfChar) 
    { 
    int charsToPlace = (int) (percentOfChar * array.length * array.length/100.0); 
    while (charsToPlace > 0) 
    { 
     int row = (int) (Math.random() * array.length); 
     int column = (int) (Math.random() * array.length); 
     if (array[row][column] != 'A'); 
     { 
      array[row][column] = 'A'; 
      charsToPlace--; 
      System.out.print(array[row][column] + " "); 
     }   
    } 
    System.out.println(); 
    } 

Нет необходимости проходным массива и использовать вложенный цикл, если вы только пытаетесь вставить символ в случайном положении.

Также

Является ли это потому, что, когда строка и столбец в отчете, если это рандомизированные, так это строка и столбец в цикл? Именно поэтому char иногда заполняет меньше, чем запрашивается, потому что цикл for останавливается, если число рандомизирует длину массива 2d, который равен 5? Также, когда он распечатывает 10 символов, иногда они переходят через 5 на 5. Пример будет равен 2 Как в строке , так и 7 во втором и 1 в 3-м. Почему это?

Более или менее. Вы рандомизируете строку и столбец, но при этом это может привести к преждевременному завершению итерации через массив. В худшем случае рассмотрите, что произойдет, если при первом вводе инструкции if случайные функции присваивают 4 значения как row, так и col. В общем, вы уверены, что в конце grid метод charx всегда будет равен 0?


Соображения

Как Мэтт отметил в комментариях ниже, этот метод не имеет проверку массива; поэтому он предполагает, что массив всегда является квадратным (т. е. строка X столбец = n X n). Если вы хотите принудительно использовать квадратный массив, вы можете создать класс-оболочку, например.

class IntegerSquareArray 
{ 
    public final int length; 
    int[][] array; 
    IntegerSquareArray(int length) 
    { 
     this.length = length; 
     this.array = new int[length][length]; 
    } 

    public int getValue(int row, int column) 
    { 
     if (row < length && column < length) 
      return array[row][column]; 
     throw new IllegalArgumentException(); 
    } 

    public void setValue(int row, int column, int value) 
    { 
     if (row < length && column < length) 
      array[row][column] = value; 
     else throw new IllegalArgumentException(); 
    } 
} 

Затем, вы можете просто изменить код grid быть

public static void grid3(IntegerSquareArray integerSquareArray, 
    int percentOfChar) 
{ 
    int charsToPlace = (int) (percentOfChar * integerSquareArray.length 
     * integerSquareArray.length/100.0); 
    while (charsToPlace > 0) 
    { 
     int row = (int) (Math.random() * integerSquareArray.length); 
     int column = (int) (Math.random() * integerSquareArray.length); 
     if (integerSquareArray.getValue(row, column) != 'A') 
     { 
      integerSquareArray.setValue(row, column, 'A'); 
      charsToPlace--; 
      System.out.print(integerSquareArray.getValue(row, column) + " "); 
     } 
    } 
    System.out.println(); 
} 
+1

+1 согласен с этим, хотя, если он хочет вставить определенный процент от A в сетке, он должен также проверить, содержит ли клетка-мишень уже «A» до декремента «charx». Я бы также подумал о переименовании 'charx' в нечто разумное, как' charsToPlace' ... также кажется, что этот код предполагает, что сетка квадратная –

+0

@MattCoubrough да, некоторые недовольны именованием в коде, я изменил свой ответ. – tigerjack89

+1

Будьте предупреждены, что это начинает ужасно неэффективно, когда percentOfChar высок, потому что вы начинаете получать больше попыток разместить в ячейках, которые уже содержат «A» ... Один из способов, которым я обходился в прошлом в своем коде, - создать список всех возможных позиций ячеек, перетасовать этот список, а затем поместить объект в первые позиции ячейки 'n' из перетасованного списка ... это решение становится O (N) после того, как было создано первоначальное создание списка и тасование. –

0

присваиваются случайные значения переменных цикла ... Теперь это так undeterministic, как это могло быть ...

В основном ваши вложенные петли заканчиваются, если случайно первые Math.random() приведут к arr.length - 1 и 2-м результатам в arr[arr.length - 1].length -1.

Я серьезно сомневаюсь, что это то, что вы хотели.

Чтобы контролировать, сколько случайных A s поместить в массив, просто использовать цикл для этого, но не присваивать случайные значения переменной цикла:

int max = arr.length * arr.length * percentofchar/100; 
for (int i = 0; i < max; i++) { 
    // Put `A` at a random location 
    int row = (int) (Math.random() * arr.length); 
    int col = (int) (Math.random() * arr.length); 
    arr[row][col] = 'A'; 
    System.out.print(arr[row][col] + " "); 
} 

Также отметим, что это все еще может привести к меньше A, чем процент будет означать, потому что одно и то же случайное местоположение может генерироваться несколько раз, поэтому один и тот же элемент массива может быть установлен на A несколько раз.

Если вы хотите, чтобы произвести точный подсчет A с, вы должны повторить, если случайное расположение уже A:

int max = arr.length * arr.length * percentofchar/100; 
for (int i = 0; i < max; i++) { 
    // Put `A` at a random location 
    int row, col; 
    do { 
     row = (int) (Math.random() * arr.length); 
     col = (int) (Math.random() * arr.length); 
    } while (arr[row][col] == 'A'); 
    arr[row][col] = 'A'; 
    System.out.print(arr[row][col] + " "); 
} 
0

Ваш код места «A» s случайным образом, так что некоторые «А» может размещен на том же месте.

Позвольте рассчитать возможность просмотра результатов 10 "A".

Первый «А» всегда пуст, поэтому вы видите 1 «А» на 100% Для размещения второго «А» есть 1 место, занятое «А» и 24 пустым местом, поэтому вы видите 2 " A "после размещения второго" А "на 96%. (Второй А может быть размещен там, где первый «А» помещается в возможность 1 из 25 (4%). . В-третьих, возможно (24/25) * (23/25). ... опущено с 4 по 9-е. Для 10-го, вы видите, 10 "А" с в возможности (24/25) (23/25) (22/25) (21/25) (20/25) (19/25) (18/25) (17/25) (16/25). (Значение составляет около 12,4%)

В этом расчете указано, что код может отображаться в 10 "A" в результате примерно один раз в восемь.

+0

ну, на самом деле это не главная причина, почему As не отображаются хорошо. Если вы снова проверите код, вы увидите, что случайные функции могут привести к преждевременному завершению итерации через массив. – tigerjack89

+0

Я думаю, что «А» помещены в случайном порядке. Проблема. Никто не может отличить одиночные буквы «А» и «А» от напечатанного «А». –

+0

Неправда. Что делать, если в первый раз, когда вы вводите оператор if, случайные функции присваивают значение 4 как «row», так и «col»? В общем, уверены ли вы, что в конце метода 'grid'' charx' всегда будет равен 0? – tigerjack89

1

Только для полноты, вот что я упомянул в комментариях к решению tigerjack's. В соответствии с комментариями я использовал бы оболочку для сетки, а не для массивного многомерного массива.

Мое решение для случайного размещения немного сложнее, но оно будет намного более эффективным для более высоких процентных ставок размещения (т. Е. Если вы пытаетесь заполнить более 90% ячеек) и всегда будет точно заполнять указанный процент символов.

При желании, можно использовать метод tigerjack для случайных размещений, когда percentOfCellsToSet ниже, и этот метод, когда percentOfCellsToSet выше, используя if заявление в методе setRandomCells().

Вот мой полный compileable пример использования перемешиваются метод списка:

import java.awt.Point; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 

public class MyGrid 
{ 
    private int width; 
    private int height; 
    private char[][] grid; 

    public MyGrid(int width, int height, char defaultCell) 
    { 
     this.width = width; 
     this.height = height;   
     grid = new char[height][width]; 

     // populate grid with defaultCells: 
     for(int x=0; x < width; ++x) 
     { 
      for(int y=0; y < height; ++y) 
      { 
       grid[y][x] = defaultCell; 
      } 
     } 
    } 

    public int getWidth() { return width; } 

    public int getHeight() { return height; } 

    public char getCell(int x, int y) { return grid[y][x]; } 

    public void setCell(int x, int y, char cellValue) { grid[y][x] = cellValue; } 

    public void setRandomCells(char cellValue, float percentOfCellsToSet) 
    { 
     // determine the number of cells to set (rounding to nearest int): 
     int numCellsToSet = (int)(Math.round((width * height * percentOfCellsToSet)/100.0)); 

     // create a list containing all possible cell positions: 
     List<Point> listAllCellLocations = new ArrayList<>(); 
     for(int x=0; x < width; ++x) 
     { 
      for(int y=0; y < height; ++y) 
      { 
       listAllCellLocations.add(new Point(x,y)); 
      } 
     } 

     // shuffle it 
     Collections.shuffle(listAllCellLocations); 

     // now set the cells 
     for(int i=0; i < numCellsToSet; ++i) 
     { 
      Point pt = listAllCellLocations.get(i); 
      setCell(pt.x, pt.y, cellValue); 
     } 
    } 

    public void debugPrintGrid() 
    { 
     for(int y=0; y < height; ++y) 
     { 
      for(int x=0; x < width; ++x) 
      { 
       System.out.print(getCell(x,y)); 
      } 
      System.out.println(); 
     } 
    } 

    public static void main(String[] args) 
    { 
     MyGrid myGrid = new MyGrid(10, 10, '0'); 
     myGrid.setRandomCells('A', 68); 
     myGrid.debugPrintGrid(); 
    } 

} 

и вот пример вывода из кода в методе main():

AAAA0A0AAA 
0AAAAAAAA0 
A00A00AA0A 
AAAAA0AAA0 
AA0A0AAAA0 
0A0AAAA0AA 
A0AAA0A0AA 
A0A00AAAAA 
AAA000A0A0 
0AA0AAA0A0 

Надежда кто-то считает это полезным.

+0

ну, вы знаете, я, как и у С. Томаса, я немного поработал с моим и вашим кодом, и это результаты 100 000 симуляций с минимальными, максимальными и средними значениями (он предполагает массив 15x15). С процентом 0% 100% http://pastebin.com/W90WUALR С процентом 0% 40% http://pastebin.com/XAgaBru5 – tigerjack89

+0

Хорошая работа с профилированием: с сеткой 1000 x 1000 и процентом 95% I получить минимально лучшую производительность с помощью моего метода на моей машине (исключая любой вывод консоли, который может исказить результаты). При 100% охвате сетки 1000 х 1000 я получаю более чем 3-кратное быстродействие с помощью моего метода. На 90% ваш метод всегда будет быстрее. Показывает важность профилирования! –

+0

вы используете первый метод (без класса обертки), правильно? Я тестировал его, используя второй (с классом IntegerSquareArray). Кроме того, я изменил свои тестовые примеры, чтобы принять во внимание ваш метод тасования с моим IntegerSquareArray. Я покажу результат через несколько минут. – tigerjack89

Смежные вопросы