3

I am trying to set the background color of a view using a timer to change the color every few seconds, but often a color is set twice in a row due to the fact that the random number referring to a specific color is generated twice. How can I change the code to avoid generating the same random number twice in a row?

final Runnable runnable = new Runnable() {

    @Override
    public void run() {

        Random rand = new Random();
        int n = rand.nextInt(3);
        n += 1;


        switch (n){

            case 1:

                colorView.setBackgroundColor(Color.GREEN);
                break;

            case 2:

                colorView.setBackgroundColor(Color.MAGENTA);
                break;

            case 3:

                colorView.setBackgroundColor(Color.CYAN);
                break;

        }

    }
};
Lucas Tony
  • 99
  • 2
  • 8

4 Answers4

1

The only way is to make a test if the old number equals to the newest generated.

    Random rand = new Random();
    int n = rand.nextInt(3);
    n += 1;
    while (n == oldValue) {
        n = rand.nextInt(3);
        n += 1;
    }
    switch (n){
    ...
    }
    oldValue = n; //The oldValue should be global
  • Thanks! I got it running by tracking the numbers with a list and then comparing them, but this is way easier, can't believe I haven't thought of solution this sooner – Lucas Tony Sep 23 '19 at 17:06
0

Try this:

    Set<Integer> generated = new HashSet<>();
    int randomMax = 3;
    final Runnable runnable = new Runnable() {

        @Override
        public void run() {

            Random rand = new Random();
            int n = rand.nextInt(randomMax);
            while (generated.contains(n) && generated.size() < randomMax) {
                n = rand.nextInt(randomMax);
            }
            if (generated.size() == randomMax) {
                throw new Exception("all numbers already generated")
            }
            generated.add(n);
            n += 1;
            switch (n){

                case 1:

                    colorView.setBackgroundColor(Color.GREEN);
                    break;

                case 2:

                    colorView.setBackgroundColor(Color.MAGENTA);
                    break;

                case 3:

                    colorView.setBackgroundColor(Color.CYAN);
                    break;

            }

        }
    };
Shadkirill
  • 92
  • 6
  • Almost good, but with this method, the generated collection will contain all of the numbers, after that? what will happen? Also, the question just wants to have two separated after each other, it does not say that it can be repeated at all. – barotia Sep 23 '19 at 10:16
  • @barotia I showed to the author how can he change the code to avoid generating the same random number twice in a row. – Shadkirill Sep 23 '19 at 10:21
  • 1
    Ok, now lets say runnable part will be executed like 4 times, the author posted as separate code and mentioned that it will be in a timer, what will be the output? – barotia Sep 23 '19 at 10:26
  • @barotia You are right. It will be dublicate in this case. I edited answer. Thnx! – Shadkirill Sep 23 '19 at 10:33
  • You're welcome, but I have another mention, throwing an exception is not necessary, because the repetition is allowed, but not after each other, 1,2,1,3,1... is still a valid series of numbers, also check the other answer, which provides a simpler solution, remember, KISS, keep it stupid simple. – barotia Sep 23 '19 at 10:38
0

You can store the integer that was created the last time in a variable 'temp' and compare it to the integer that is created in the current step:

final Runnable runnable = new Runnable() {

    @Override
    public void run() {
        if(tempInt == null){
            int tempInt = 0;
            int n = 0;
        }
        Random rand = new Random();
        while(n == tempInt){
            n = rand.nextInt(3);
            n += 1;
        }
        tempInt = n;
        switch (n){

            case 1:

                colorView.setBackgroundColor(Color.GREEN);
                break;

            case 2:

                colorView.setBackgroundColor(Color.MAGENTA);
                break;

            case 3:

                colorView.setBackgroundColor(Color.CYAN);
                break;

        }

    }
barotia
  • 428
  • 4
  • 12
GitPhilter
  • 171
  • 9
0

You can do something like this

    //set it as a global variable

    int previousRandomNumber=0; //set it as 0 for first time

    final Runnable runnable = new Runnable() {

    @Override
    public void run() {
        int currentRandomNumber=new Random.nextInt(3);
        currentRandomNumber+=1;

        while(currentRandomNumber == previousRandomNumber){
        currentRandomNumber = new Random.nextInt(3);
        currentRandomNumber+=1;
        }

        /*store the current number as the previous number to check with next the generated number is the same or not*/

        previousRandomNumber=currentRandomNumber;

        switch (n){

            case 1:

                colorView.setBackgroundColor(Color.GREEN);
                break;

            case 2:

                colorView.setBackgroundColor(Color.MAGENTA);
                break;

            case 3:

                colorView.setBackgroundColor(Color.CYAN);
                break;

        }

    }
};
camelCode
  • 243
  • 3
  • 16