2

I am trying to do a pvp event in my game server which uses 3 zones to do it randomly. I use the following code but always is returning me the values 1 and 2 and repeated as well. I need some sequence like this for example: 3-2-1-2-1-3 or something that never repeats the same number.

int random = Rnd.get(1, 3);

if (random == 1)
{
    setstartedpvpzone1(true);
}

if (random == 2)
{
    setstartedpvpzone2(true);
}

if (random == 3)
{
    setstartedpvpzone3(true);
}

this is what i get in rnd:

public final class Rnd
{
    /**
     * This class extends {@link java.util.Random} but do not compare and store atomically.<br>
     * Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
     * This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
     * @author Forsaiken
     * @see java.util.Random
     */
    public static final class NonAtomicRandom extends Random
    {
        private static final long serialVersionUID = 1L;
        private volatile long _seed;

        public NonAtomicRandom()
        {
            this(++SEED_UNIQUIFIER + System.nanoTime());
        }

        public NonAtomicRandom(final long seed)
        {
            setSeed(seed);
        }

        @Override
        public final int next(final int bits)
        {
            return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
        }

        @Override
        public final void setSeed(final long seed)
        {
            _seed = (seed ^ MULTIPLIER) & MASK;
        }
    }

and rnd.get:

/**
 * Gets a random integer number from min(inclusive) to max(inclusive)
 * @param min The minimum value
 * @param max The maximum value
 * @return A random integer number from min to max
 */
public static final int get(final int min, final int max)
{
    return rnd.get(min, max);
}
Zong
  • 6,160
  • 5
  • 32
  • 46
b0rto
  • 35
  • 6
  • 3
    Possible duplicate of [Unique (non-repeating) random numbers in O(1)?](http://stackoverflow.com/questions/196017/unique-non-repeating-random-numbers-in-o1) – Zong May 01 '16 at 17:26
  • 1
    What random number library is `Rnd`? That doesn't appear to be the Java standard `Random` library. Anyway, I suspect that the the end value you pass to `get` is **exclusive** so that `get(1, 3)` means get me a value greater than or equal to 1 but **strictly less than** 3. If so, changing to `get(1, 4)` should do the trick. – Oliver Dain May 01 '16 at 17:27
  • 1
    Please define *"never repeats the same number"* given that your example of `3-2-1-2-1-3` shows repeats of all three numbers. Did you mean that it should run a full sequence of non-repeating numbers before starting over? Or did you mean that the same number is not allowed to come up right next to each other? Or something else? – Andreas May 01 '16 at 17:42
  • i need only one number every time from 1 2 or 3, because i use this number to start the event random and never must be duplicated 2 times simultaneous. the number 1 correspond to the zone 1, number 2 zone 2 , number 3 zone 3, then i need new zone every time the event start. – b0rto May 01 '16 at 17:56

5 Answers5

1

If all you are looking for is a random number that doesn't equal the previous one returned then the solution is much simpler:

private Random random = new Random();
private int previousZone = 0;

public int nextZone() {
    int zone;
    do {
        zone = random.nextInt(3) + 1;
    } while (zone == previousZone);

    previousZone = zone; //store last "generated" zone

    return zone;
}
Christoph-Tobias Schenke
  • 3,250
  • 1
  • 11
  • 17
sprinter
  • 27,148
  • 6
  • 47
  • 78
0

This code never repeats any numbers, for example if you have 1,2,3 you can get a random sequence of 4 numbers, example 2,1,3.

Create an array with all numbers you need...

   int[] a = {1, 2, 3};

Then select random items

   for (int i=0; i<a.length; i++){
       int random = Rnd.get(0, a.length);
       //remove the selected item from the array
       ArrayUtils.removeElement(a, random);

       if (random == 1) {
            setstartedpvpzone1(true);
       } else if (random == 2) {
            setstartedpvpzone2(true);
       } else if (random == 3) {
            setstartedpvpzone3(true);
       }
    }
danilonet
  • 1,757
  • 16
  • 33
  • i am getting error in this line ArrayUtils.removeElement(a, random) the error says: the method removeElement(int[], int) is undefined for the type Arrayutils – b0rto May 01 '16 at 17:41
  • 1
    i can use that from my sources ArrayUtils.remove(array, value) but dont match with your code. thanks for your help.. – b0rto May 01 '16 at 17:43
  • error: the method remove(T[],T) in the type Arrayutils is not aplicable for the arguments (int[],int) – b0rto May 01 '16 at 17:53
  • as i see in javadocs removeElement is the right way http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/ArrayUtils.html – danilonet May 01 '16 at 18:03
  • yes you are right was fine, the problem was my mistake with a wrong import, but your code is returning me a secuence like this: 2-3-2-1-3-2-3-3-3-3-2-1-2-3-3-1-1, anyway thanks for try to help me, for some reason sometimes repeat the 3 lot of times. – b0rto May 01 '16 at 22:19
0

[not tested] It is possible that it may contain some syntax errors as I am not a Java programmer.

    int a=0,b=0;
    while(true)
   {
        int random = Rnd.get(1, 3);
        if(!(a==random or b==random))
        {
            a=b;
            b=random;
            break;
        }
   }

if (random == 1)
{
    setstartedpvpzone1(true);
}

if (random == 2)
{
    setstartedpvpzone2(true);
}

if (random == 3)
{
    setstartedpvpzone3(true);
}
Naresh Teli
  • 138
  • 1
  • 12
  • thanks for your help guys..im testing your code now. – b0rto May 01 '16 at 17:49
  • hello i tested your code and it return secuence of numbers like this: 3-2-2-3-1-2-2-1-3-2-1-2-2 always repeat the number 2, then is not valid because is repeating the numbers, anyway thanks for try to help me. – b0rto May 01 '16 at 22:17
  • may be it code in an function which you call again and again which cause value of a and b assign zero each time; a and b must global variable – Naresh Teli May 02 '16 at 18:04
0

Your problem boils down to a graph traversal in which from each current zone, you only have 2 possible next zones and those choices never change. So here is how I would implement it:

public static class EventLocator{
    private int currentZone;
    private Random random;
    private Map<Integer, int[]> locations;
    private static EventLocator instance;

    private EventLocator() {
    }

    public static EventLocator getInstance(){
        if (instance == null) {
            instance = new EventLocator();
        }
        return instance;

    }

    public int getNextZone(){
        if (this.currentZone == 0) {//first time called
            this.random = new Random();
            this.locations = new HashMap<>(3);//graph <currentZone, posibleZones>
            this.locations.put(1, new int[] { 2, 3 });
            this.locations.put(2, new int[] { 1, 3 });
            this.locations.put(3, new int[] { 1, 2 });

            this.currentZone = this.random.nextInt(3) + 1;// to 1-based Zones
            return currentZone;
        }
        int[] possibleZones = this.locations.get(this.currentZone);
        int randomIndex = this.random.nextInt(2);//0 or 1 index
        this.currentZone = possibleZones[randomIndex];
        return this.currentZone;
    }
}

You would call it like:

EventLocator eventLocator = MyProgram.EventLocator.getInstance();
System.out.println(eventLocator.getNextZone());
System.out.println(eventLocator.getNextZone());
PedroJ
  • 15
  • 5
  • hello tested and this class return me a number different to 1 - 2 - 3 because no worked, thanks for your help guys, i still trying to fix it , just 3 fu cking random number and cant do it xD – b0rto May 01 '16 at 22:15
  • a secuence of numbers like 1-2-3-1-2-3-1-2-3-1-2-3 is valid too – b0rto May 01 '16 at 22:24
  • the getNextZone() will return any zone (1,2 or 3), with no repetition. It is totally random. – PedroJ May 01 '16 at 23:35
  • EventLocator eventLocator = EventLocator.getInstance(); if (eventLocator.getNextZone() == 1) { setstartedpvpzone1(true); } if (eventLocator.getNextZone() == 2) { setstartedpvpzone2(true); } if (eventLocator.getNextZone() == 3) { setstartedpvpzone3(true); } i used like this and sometimes return a number between 123 but sometimes no, then the system dont work. – b0rto May 01 '16 at 23:49
  • Call EventLocator.getInstance().getNextZone() once, like int nextZone = EventLocator.getInstance().getNextZone(); if(nextZone==1){ ...}ELSE if(nextZone==2){ ...}ELSE{ ...} – PedroJ May 02 '16 at 00:14
  • hello thanks for your explanation , but dont worked, return me some number that is not 1 2 or 3. – b0rto May 02 '16 at 07:52
0

 private boolean _lastevent1 = false;
 
 public boolean lastevent1()
 {
  
  return _lastevent1;
 }
 
 public void setlastevent1(boolean val)
 {
  _lastevent1 = val;
 }
 
 private boolean _lastevent2 = false;
 
 public boolean lastevent2()
 {
  
  return _lastevent2;
 }
 
 public void setlastevent2(boolean val)
 {
  _lastevent2 = val;
 }
 
 private boolean _lastevent3 = false;
 
 public boolean lastevent3()
 {
  
  return _lastevent3;
 }
 
 public void setlastevent3(boolean val)
 {
  _lastevent3 = val;
 }

    if (!lastevent1())
    {
     setlastevent3(false);
     setstartedpvpzone3(false);
     
     setstartedpvpzone1(true);
     setlastevent1(true);
    }
    
    else if (!lastevent2())
    {
     setstartedpvpzone1(false);
     setstartedpvpzone2(true);
     setlastevent2(true);
    }
    
    else if (!lastevent3())
    {
     setlastevent1(false);
     setlastevent2(false);
     
     setstartedpvpzone2(false);
     setstartedpvpzone3(true);
     setlastevent3(true);
    }

hello finally i fixed using booleans and i get this secuence, 1-2-3-1-2-3-1-2-3-1-2-3 , i breaked my mind with it because is very confuse this code but it work now as a charm , thanks for all to try to help me i very appreciate it, great community.

b0rto
  • 35
  • 6