2

thanks in advance for taking time to look at my Q. and anyone with the same problem i hope we get a solution...

so basicly i have an app that spins 2 coins at the same time and displays what the result is.

This method generates the first coin...

    public void coinResult1(){
     ImageView coin1View = (ImageView) findViewById(R.id.coin1);
     Random r = new Random();
     int coin1result = r.nextInt(2);

     if (coin1result == 0){
        coin1View.setBackgroundResource(R.drawable.coinheads);
        coinresult1 = 0;
     }
        else if (coin1result == 1) {
            coin1View.setBackgroundResource(R.drawable.cointails);
            coinresult1 = 1;
        }
}

and this is for the second coin

public void coinResult2(){
    ImageView coin2View = (ImageView) findViewById(R.id.coin2);

    Random r = new Random();
    int coin2result = r.nextInt(2);

    if (coin2result == 0){
        coin2View.setBackgroundResource(R.drawable.coinheads);
        coinresult2 = 0;
    }
        else if (coin2result == 1) {
            coin2View.setBackgroundResource(R.drawable.cointails);
            coinresult2 = 1;
        }
}

this is linked to onclick() of button which check the results to a player selection

public void checkResult(){
        coinResult1();
        coinResult2();
        coinResult = coinresult1 + coinresult2;
        if (coinResult == playerSelection){
            playerWins();
            buttonsReset();
        }
        else {
            playerLost();
            buttonsReset();
        }
    }

Now the only problem i have is... the results of both coins of 1000 presses are this... HeadsHeads 54%

HeadsTails 2%

TailsTails 44%

of 1000000 spins was roughly the same percentages

when each coin result was counted seprately

COIN1 heads 53% tails 47%

COIN2 heads 48% tails 52%

Now my friend says their is something wrong with those odds....beacause HeadsTails wasnt a high enough percent, hes expecting it to be close to 33% each combination at random

the code seems to favour HeadsHeads and TailsTails or HeadsTails.....ive tried several times and keep getting a low % of HeadsTails

can anyone shead some light on whats going on....and what is causing HeadsTails to rarely come out?

hope to hear back soon

  • 2
    Instances of `Random` are seeded with the system time by default. If two instances happen to be created within a millisecond, they will effectively generate the same pseudo-random numbers. – Tobias Mar 06 '14 at 10:22

3 Answers3

5

Your repeated instantiation of Random is ruining the statistical properties of the generator.

You need to create one instance and pass that into your functions. Better still, use a field in your class.

Please refer to this question for concerns over thread safety of the Random class:Is Random class thread safe?. It seems to suggest that you should synchronize the nextInt calls.

Community
  • 1
  • 1
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Sorry, which threading issues did you refer to? According to http://stackoverflow.com/questions/5819638/is-random-class-thread-safe Random class is thread safe... – Germann Arlington Mar 06 '14 at 10:26
  • @GermannArlington: That's very nice. I'm an old paranoid cat. Do you mind if I absorb this into my answer? – Bathsheba Mar 06 '14 at 10:26
  • thanks for your answers they have all been great...ill changeCode and see what happens – user3387276 Mar 06 '14 at 10:43
1

You should never re-create random number generator over and over again:

  public void coinResult1(){
    ImageView coin1View = (ImageView) findViewById(R.id.coin1);
    Random r = new Random(); // <- That's the source of errors!
    int coin1result = r.nextInt(2);
    ...

Instead, create random generator instance once and for all:

  // Simplest, not thread-safe amendment
  private static Random s_Gen = new Random();
  ...

  public void coinResult1(){
    ImageView coin1View = (ImageView) findViewById(R.id.coin1);

    int coin1result = s_Gen.nextInt(2);
    ...

The cause of the misbehaviour is that when you re-create Random it often re-initializes from the same seed (which is usually current time) and so generates the same values.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
0

You must create only one instance of Random.

    private Random r;

    // initialize r in onCreate or somehere else only once 

protected void onCreate(Bundle savedInstanceState){
            // ...
    r = new Random();
}

public void coinResult1(){
     ImageView coin1View = (ImageView) findViewById(R.id.coin1);
     int coin1result = r.nextInt(2);

     if (coin1result == 0){
        coin1View.setBackgroundResource(R.drawable.coinheads);
        coinresult1 = 0;
     }
        else if (coin1result == 1) {
            coin1View.setBackgroundResource(R.drawable.cointails);
            coinresult1 = 1;
        }
}

public void coinResult2(){
    ImageView coin2View = (ImageView) findViewById(R.id.coin2);
    int coin2result = r.nextInt(2);

    if (coin2result == 0){
        coin2View.setBackgroundResource(R.drawable.coinheads);
        coinresult2 = 0;
    }
        else if (coin2result == 1) {
            coin2View.setBackgroundResource(R.drawable.cointails);
            coinresult2 = 1;
        }
}
Dadroid
  • 1,444
  • 15
  • 16