【问题标题】:Is there some pattern on Random() method?Random() 方法有什么模式吗?
【发布时间】:2014-11-11 16:09:10
【问题描述】:

我开始制作一个有山羊的项目!是的山羊。 目前只有一个功能,当我点击一只山羊时,它会在 Random 位置创建另一只山羊。 我意识到有一种位置模式:

代码如下:

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() 来定义山羊的位置,但我想知道为什么会创建这种模式。

我疯了吗?

【问题讨论】:

  • 你说的模式是什么意思?
  • @blackbelt 看图,山羊的位置是对角线图案。
  • 尝试在整个程序中使用 Random 的单个实例,而不是每次需要数字时都创建一个新实例。
  • @blackbelt 没有充分的理由创建这些立即成为垃圾回收候选对象的额外对象。

标签: android design-patterns random


【解决方案1】:

您在每次调用criarCabra 和每次调用onClick 时都会创建Random 的新实例。创建Random 的单个静态实例,然后重新使用它。

除非您真的知道自己在做什么并且有充分的理由这样做,否则最佳做法是只为每个程序创建一个 Random 实例,然后在您需要其他值时轮询它。

【讨论】:

  • 等待回复:D
  • ... 创建一个新的随机对象将如何导致 OP 看到的行为?
  • @laalto 通过与播种机制的交互。 Java 的Random 是一个线性同余生成器,当种子顺序相关时,那些臭名昭著的生成器会产生共线结果。请参阅 LCG Wikipedia page 上对 Marsaglia 定理的简要讨论。
【解决方案2】:

首先,您每次都创建一个新的Random 对象。在 Android 中,initial seed is derived from current time and the identity hash code:

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

对于按顺序创建的两个对象,身份哈希码彼此接近。在我的 Android KitKat Dalvik VM 上,我得到的身份哈希码仅相差 32。

currentTimeMillis() 对种子也没有太大区别。

随机数本身就是linear congruential generator的形式

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

其中random[0] 是种子,abc 是参数。

基于this answer,相似的种子确实在线性同余生成器中产生了相似的结果:

在给定相似种子的情况下,您会看到来自 nextDouble 的相似初始输出的原因是,因为下一个整数的计算只涉及乘法和加法,所以下一个整数的大小受低位差异的影响不大.

因此,您的两个使用默认种子连续生成的Randoms 将产生似乎相关的值并使您的山羊定位在一条线上。

要修复它,请使用相同的 Random 对象和/或比线性同余的更随机的伪随机生成器。

【讨论】:

  • 感谢@pjs 的一些研究。
猜你喜欢
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-10
  • 1970-01-01
  • 2010-10-14
  • 2023-03-15
相关资源
最近更新 更多