Reputation: 35
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
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
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
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
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
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