2014-09-17 10 views
10

Ho iniziato a fare un progetto dove ci sono le capre! Sì capre. Attualmente c'è una sola funzione, quando faccio clic su una capra, crea un'altra capra in una posizione casuale a. mi sono reso conto che c'è un modello di posizioni:C'è qualche schema sul metodo Random()?

I've made red lines on patterns

Qui è il codice:

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); 
    } 
} 

Vorrei sapere perché si sta creando questo schema, anche se sto usando Random().NextInt() a definire le posizioni delle capre.

Sono pazzo?

+0

cosa intendi per motivo? – Blackbelt

+0

@blackbelt Guardare l'immagine, la posizione delle capre è un modello diagonale. – Rafael

+2

Provare a utilizzare una singola istanza a caso tutto il programma invece di creare una nuova istanza ogni volta che avete bisogno di un numero. – Karakuri

risposta

5

Innanzitutto, si crea un nuovo oggetto Random ogni volta. In Android, la 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)); 
} 

Per due oggetti creati in sequenza, i codici di identità hash sono vicini l'uno all'altro. Sul mio Android KitKat Dalvik VM, ottengo codici identificativi di hash che differiscono solo di 32.

Il currentTimeMillis() non fornisce molta differenza neanche ai semi.

La stessa casuale è una linear congruential generator della forma

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

dove random[0] è il seme e a, b e c sono parametri.

Sulla base di this answer, semi simili infatti produrre risultati simili a generatori lineari congruenziali:

Il motivo per cui stai vedendo uscita iniziale simile da nextDouble dato semi simili è che, perché il calcolo del successivo numero intero unico comporta una moltiplicazione e un'aggiunta, la grandezza del prossimo numero non è molto influenzata dalle differenze nei bit più bassi.

Quindi, i tuoi due successivamente generate Random s con i semi di default produrrà valori che sembrano essere correlato ed effettuare le capre vengono posizionate su una linea.

Per risolvere il problema, utilizzare lo stesso oggetto Random e/o un generatore pseudocasuale più casuale di quello lineare congruente.

+0

Grazie a @pjs per alcune delle ricerche. – laalto

5

Si stanno creando nuove istanze di Random con ogni chiamata a criarCabra e ogni chiamata di onClick. Crea una singola istanza statica di Random, quindi riutilizzala.

A meno che non si sappia davvero cosa si sta facendo e si abbia una buona ragione per farlo, è consigliabile creare solo un'istanza di Random per programma e quindi eseguire il polling ogni volta che sono necessari valori aggiuntivi.

+0

In attesa di risposta: D – Nabin

+0

... e come sarebbe la creazione di un nuovo oggetto a caso causa il comportamento visto da OP? – laalto

+2

@laalto Tramite un'interazione con il meccanismo di semina. Java 'Random' è un generatore lineare congruente, quelle puzzolenti sono famigerate per produrre risultati collineari quando i semi sono correlati in sequenza. Vedere la breve discussione del teorema di Marsaglia sulla [pagina di LCG Wikipedia] (http://en.wikipedia.org/wiki/Linear_congruential_generator#Advantages_and_disadvantages_of_LCGs). – pjs