b0rto
b0rto

Reputation: 35

Sequence of random numbers without repeats

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

Upvotes: 2

Views: 146

Answers (5)

b0rto
b0rto

Reputation: 35

	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.

Upvotes: 0

sprinter
sprinter

Reputation: 27946

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

Upvotes: 1

danilonet
danilonet

Reputation: 1795

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

Upvotes: 0

PedroJ
PedroJ

Reputation: 15

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

Upvotes: 0

Naresh Teli
Naresh Teli

Reputation: 138

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

Upvotes: 0

Related Questions