Есть ли какой-нибудь шаблон в методе Random()?

Я начал делать проект, где есть козы! Да, козы. В настоящее время существует только одна функция, когда я нажимаю на козу, она создает другую козу в позиции Random. Я понял, что есть структура позиций:

I've made red lines on patterns

Вот код:

public class GameActivity extends Activity {

    private int[] arrGoats = new int[5];
    private RelativeLayout battlefield;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);

        battlefield = (RelativeLayout) findViewById(R.id.rel_battlefield);

        arrGoats[0] = R.drawable.amarelo;
        arrGoats[1] = R.drawable.azul;
        arrGoats[2] = R.drawable.branco;
        arrGoats[3] = R.drawable.verde;
        arrGoats[4] = R.drawable.vermelho;

        criarCabra(60, 100);

    }

    private void criarCabra(float x, float y) {
        int cabraImg = arrGoats[new Random().nextInt(4)];

        ImageView cabra = new ImageView(this);
        cabra.setImageResource(cabraImg);
        cabra.setX(x);
        cabra.setY(y);

        LayoutParams params = (LayoutParams) new LayoutParams(MarginLayoutParams.WRAP_CONTENT,
                MarginLayoutParams.WRAP_CONTENT);
        params.width = 150;
        params.height = 120;
        cabra.setLayoutParams(params);

        cabra.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                criarCabra(new Random().nextInt(2000), new Random().nextInt(1000));
            }
        });

        battlefield.addView(cabra);
    }
}

Я хотел бы знать, почему этот шаблон создается, хотя я использую Random().NextInt() для определения позиций коз.

Я сошел с ума?

Ответ 1

Сначала вы создаете новый объект Random каждый раз. В Android начальное значение выводится из текущего времени и хеш-кода идентификатора:

public Random() {
     // Note: Using identityHashCode() to be hermetic wrt subclasses.
     setSeed(System.currentTimeMillis() + System.identityHashCode(this));
}

Для двух объектов, созданных последовательно, хэш-коды идентичности близки друг к другу. На моем Android KitKat Dalvik VM я получаю коды хеш-идентификаторов, которые отличаются только 32.

currentTimeMillis() также не имеет большого значения для семян.

Само случайное является линейным конгруэнтным генератором вида

random[i+1] = a * random[i] + b (mod c)

где random[0] - это семя, а a, b и c - параметры.

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

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

Следовательно, ваши два сгенерированных последовательно Random с семенами по умолчанию будут создавать значения, которые, по-видимому, коррелированы и заставят ваших коз позиционировать на линии.

Чтобы исправить это, используйте тот же объект Random и/или более случайный псевдослучайный генератор, чем линейный конгруэнтный.

Ответ 2

Вы создаете новые экземпляры Random при каждом вызове criarCabra и каждом вызове onClick. Создайте один статический экземпляр Random, затем повторно используйте его.

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