I'm trying to figure out how to randomize the object selected as a parameter in a method. So I created two Pokemon classes below (rattata and pidgey)
class WildPokemon {
private static int randomHealth(int min, int max) {
int range = (max - min) + 1;
return (int)(Math.random() * range) + min;
}
private static int randomAttack(int min, int max) {
int range = (max - min) + 1;
return (int)(Math.random() * range) + min;
}
private static int randomSpeed(int min, int max) {
int range = (max - min) + 1;
return (int)(Math.random() * range) + min;
}
static Pokemon rattata = new Pokemon("Rattata",randomHealth(15,20),randomAttack(2,5),randomSpeed(2,6));
static Pokemon pidgey = new Pokemon("Pidgey",randomHealth(10,17),randomAttack(3,4),randomSpeed(3,5));
}
Below I am able to call rattata in the method Pokemon.battle() and it functions as expected. Is there a way I could randomize my second parameter to where it could be either rattata or pidgey selected at random?
public class PokemonTester{
public static void main(String[] args){
Pokemon.battle(starter, WildPokemon.rattata);
}
}
Important remark : using static methods and static fields for model is generally not advised.
Instead you should create an instance of WildPokemon and call method on it.
Do it in the same way you have already done to calculate random values.
You should use a List of pokemon rather than doing the compute with two hard coded values.
Try this :
public class WildPokemon{
...
private Random rand = new Random();
private List<Pokemon> pokemonList;
...
public WildPokemon(){
pokemonList = new ArrayList();
Pokemon rattata = new Pokemon("Rattata",randomHealth(15,20),randomAttack(2,5),randomSpeed(2,6));
pokemonList.add(rattata);
Pokemon pidgey = new Pokemon("Pidgey",randomHealth(10,17),randomAttack(3,4),randomSpeed(3,5));
pokemonList.add(pidgey);
...
}
private Pokemon getRandomPokemon() {
int n = rand.nextInt(pokemonList.size());
return pokemonList.get(n);
}
...
}
And call it :
WildPokemon wildPokemon = new WildPokemon();
Pokemon.battle(starter, wildPokemon.getRandomPokemon());
Use an array (or list) of objects and randomly generate an index value.
public class PokemonTester{
public static void main(String[] args){
WildPokemon[] pokemons = { rattata, pidgey };
Pokemon.battle(starter, pokemons[ (int)(Math.random()*pokemons.length) ] );
}
}
Related
So i am trying to build a genetic algorithm on java i stuck on getting
fitness of my population here 3 classes from my project:
Class Individu
public class Individu {
int Popsize=4;
int Health[]= new int[Popsize];
int Attack[]= new int[Popsize];
int Atspeed[]= new int[Popsize];
int Move[]= new int[Popsize];
int health,attack,lifetime,dmgdone,attspeed,range,move;
double fitness;
double Pitness[]= new double[20];
Random random = new Random();
public int setHealth(){
health = random.nextInt(150 - 75) + 75;
return health;
}
public int setAttack(){
attack = random.nextInt(10 - 5) + 10;
return attack;
}
public int setAttspeed(){
attspeed = random.nextInt(3 - 1) + 3;
return attspeed;
}
public int setMoveSpeed(){
move = random.nextInt(8 - 4) + 1;
return move;
}
public int getGeneHealth(int index) {
return Health[index];
}
public int getGeneAttack(int index) {
return Attack[index];
}
public int getGeneAtspedd(int index) {
return Atspeed[index];
}
public int getGeneMove(int index) {
return Move[index];
}
public void setGene(int index, int value) {
Health[index]=value;
Attack[index]=value;
Atspeed[index]=value;
Move[index]=value;
fitness = 0;
}
public int size() {
return Popsize;
}
public double[] GenerateIndividual(){
for (int i = 0; i <Popsize; i++) {
Health[i]=setHealth();
Attack[i]=setAttack();
Atspeed[i]=setAttspeed();
Move[i]=setMoveSpeed();
}
return Pitness;
}
Class Fitness
public class Fitness {
Individu individu= new Individu();
double fitness;
double Pitness[]= new double[20];
public double getFitness(){
individu.GenerateIndividual();
for (int i = 0; i <=3; i++) {
fitness=
individu.getGeneHealth(i)+individu.getGeneAtspedd(i)+
individu.getGeneAttack(i)+
individu.getGeneMove(i));
fitness=fitness/171;
Pitness[i]=fitness;
System.out.println("Health from class
fitness"+individu.Health[i]);
}
return fitness;
}
}
Main Class
public class main {
public static void main(String[] args) {
Individu aaa=new Individu();
Fitness bbb= new Fitness();
bbb.getFitness();
aaa.GenerateIndividual();
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(3);
for (int i=0; i<=3; i++){
//System.out.println("Fitness ");
System.out.println("Generasi ke :"+i+1);
System.out.println("Health "+aaa.getGeneHealth(i));
System.out.println("Attackspeed "+aaa.getGeneAtspedd(i));
System.out.println("Attack "+aaa.getGeneAttack(i));
System.out.println("movementSpeed "+aaa.getGeneMove(i));
}
}
}
What i struggle is when i run this script i got 2 double value from 1 variable first value is from Fitness class as i printed here
System.out.println("Health from class fitness"+individu.Health[i]);
and second variable i printed here from Main Class
System.out.println("Health "+aaa.getGeneHealth(i));
that 2 variable is always have different value causing my fitness and my generation is not correlated each other.
My question is how to make this 2 variable print same value?
Well, aside from the many problems I can detect about the essentials of Genetic Algorithms, I see 'individu' and 'aaa' are two different Java objects.
Individu aaa=new Individu();
aaa.GenerateIndividual();
and
Individu individu= new Individu();
individu.GenerateIndividual();
Since your Health and Fitness are randomly generated on GenerateIndividual(), both 'aaa' and 'individu' will get different Health values.
I strongly recommend you to review GA essentials, since I can see many conception errors in your system.
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);
}
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;
}
[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);
}
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());
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);
}
}
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.
prob 1 : What is this code its a constructor or a method or else?
prob 2 : How is this return statement working (both)?
Can anyone please explain...
public class RandomIntGenerator
{
private final int min;
private final int max;
private RandomIntGenerator(int min, int max) {
this.min = min;
this.max = max;
}
public static RandomIntGenerator between(int max, int min) //Prob 1
{
return new RandomIntGenerator(min, max); //Prob 2
}
public static RandomIntGenerator biggerThan(int min) {
return new RandomIntGenerator(min, Integer.MAX_VALUE); //Prob 2
}
public static RandomIntGenerator smallerThan(int max) {
return new RandomIntGenerator(Integer.MIN_VALUE, max);
}
public int next() {...} //its just a method
}
Basically they are methods which return new instances of the RandomIntGenerator class. Once you have those you can use the next() method to get random numbers.
RandomIntGenerator generator = RandomIntGenerator.between(5, 10);
int a = generator.next(); //a is now a "random" number between 5 and 10.
If the constructor was public, you could replace the first line with the line below, as they have the same effect.
RandomIntGenerator generator = new RandomIntGenerator(5, 10);
Arrays.sort() gives and error of:
FiveDice.java:19: error: no suitable method found for sort(int)
Arrays.sort(compNums);
If I take anything out of the for loop, it thinks thee is only 1 number or gives an error. What other sorting options would be usable?
import java.util.*;
public class FiveDice {
public static void main(String[] args) {
int x;
int compNums = 0;
int playerNums;
Die[] comp = new Die[5];
Die[] player = new Die[5];
System.out.print("The highest combination wins! \n5 of a kind, 4 of a kind, 3 of a kind, or a pair\n");
//computer
System.out.print("Computer rolled: ");
for(x = 0; x < comp.length; ++x) {
comp[x] = new Die();
compNums = comp[x].getRoll();
//Arrays.sort(compNums); <--does not work
System.out.print(compNums + " ");
}
//player
System.out.print("\nYou rolled: \t ");
for(x = 0; x < player.length; ++x) {
player[x] = new Die();
playerNums = player[x].getRoll();
System.out.print(playerNums + " ");
}
}
}
die class
public class Die {
int roll;
final int HIGHEST_DIE_VALUE = 6;
final int LOWEST_DIE_VALUE = 1;
public Die()
{ }
public int getRoll() {
roll = ((int)(Math.random() * 100) % HIGHEST_DIE_VALUE + LOWEST_DIE_VALUE);
return roll; }
public void setRoll()
{ this.roll = roll; }
}
Easiest way is to implement Comparable to Die class , set value of roll in constructor of Die not in the getter method and your problem is solved.
public class Die implements Comparable<Die> {
private int roll;
final int HIGHEST_DIE_VALUE = 6;
final int LOWEST_DIE_VALUE = 1;
public Die() {
roll = ((int)(Math.random() * 100) % HIGHEST_DIE_VALUE + LOWEST_DIE_VALUE);
}
public int getRoll() {
return roll;
}
public void setRoll(int roll) {
this.roll = roll;
}
public int compareTo(Die d) {
return new Integer(d.getRoll()).compareTo(new Integer(this.getRoll()));
}
}
now Arrays.sort(Die[]) will sort the array of Die.
You don't have to use 2 arrays for the sorting. If you implement the Comparable<T> interface, your classes can be sorted by Java Collections API. In your case, Die class can implement Comparable<T> and provide a way for the Java framework to compare dice values.
Take a look at the Java API:
http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html
In your case:
public class Die implements Comparable<Die>{
int roll;
final int HIGHEST_DIE_VALUE = 6;
final int LOWEST_DIE_VALUE = 1;
public Die() { }
public int computeRoll() {
roll = ((int)(Math.random() * 100) % HIGHEST_DIE_VALUE + LOWEST_DIE_VALUE);
return roll;
}
// I also changed this to store the value
public int getRoll() {
return roll;
}
public void setRoll() { this.roll = roll; }
// This is the method you have to implement
public int compareTo(Die d) {
if(getRoll() < d.getRoll()) return -1;
if(getRoll() > d.getRoll()) return +1;
if(getRoll() == d.getRoll()) return 0;
}
}
Whenever you have a Collection of Dies, like an ArrayList or LinkedList, you simply sort the collection itself. Below is a sample code.
ArrayList<Die> myCollection = new ArrayList<Die>();
myCollection.add(die1);
// more array population code
// ...
Collections.sort(myCollection);
You can't perform sort() on compNums because it is a single value. You declare it as an int value, rather than as an array of integers.
Instead, you should make compNums an array, populate it with the Die roll values, and then perform a sort operation on the resultant array. I believe the following will achieve what you are after.
int[] compNums = new int[5];
...
for(x = 0; x < comp.length; ++x) {
comp[x] = new Die();
compNums[x] = comp[x].getRoll();
}
Arrays.sort(compNums);
// print results
you must pass an array to the Array.Sort(arr) not parameter you must do something like this Array.Sort(int[]compNums);
and if you are using a anonymous type like comp[]compNums you must do it like this
java.util.Arrays.sort(comp[]compNums, new java.util.Comparator<Object[]>() {
public int compare(Object a[], Object b[]) {
if(something)
return 1;
return 0;
}
});
I have an enum that I would like to randomly select a value from, but not truly random. I would like some of the values to be less likely of being selected so far. Here is what I have so far...
private enum Type{
TYPE_A, TYPE_B, TYPE_C, TYPE_D, TYPE_E;
private static final List<Type> VALUES =
Collections.unmodifiableList(Arrays.asList(values()));
private static final int SIZE = VALUES.size();
private static final Random RANDOM = new Random();
public static Type randomType() {
return VALUES.get(RANDOM.nextInt(SIZE));
}
}
Is there an efficient way of assigning probabilities to each of these values?
Code found from here
several ways to do it, one of them, similar to your approach
private enum Type{
TYPE_A(10 /*10 - weight of this type*/),
TYPE_B(1),
TYPE_C(5),
TYPE_D(20),
TYPE_E(7);
private int weight;
private Type(int weight) {
this.weight = weight;
}
private int getWeight() {
return weight;
}
private static final List<Type> VALUES =
Collections.unmodifiableList(Arrays.asList(values()));
private int summWeigts() {
int summ = 0;
for(Type value: VALUES)
summ += value.getWeight();
return summ;
}
private static final int SIZE = summWeigts();
private static final Random RANDOM = new Random();
public static Type randomType() {
int randomNum = RANDOM.nextInt(SIZE);
int currentWeightSumm = 0;
for(Type currentValue: VALUES) {
if (randomNum > currentWeightSumm &&
randomNum <= (currentWeightSumm + currentValue.getWeight()) {
break;
}
currentWeightSumm += currentValue.getWeight();
}
return currentValue.get();
}
}
Here's a generic approach to choosing an enum value at random. You can adjust the probabilities as suggested here.
Assuming you have a finite number of values you could have a separate array (float[] weights;) of weights for each value. These values would be between 0 and 1. When you select a random value also generate another random number between and only select the value if the second generated number is below the weight for that value.
You can create an enum with associated data bby provding a custom constructor, and use the constructor to assign weightings for the probabilities and then
public enum WeightedEnum {
ONE(1), TWO(2), THREE(3);
private WeightedEnum(int weight) {
this.weight = weight;
}
public int getWeight() {
return this.weight;
}
private final int weight;
public static WeightedEnum randomType() {
// select one based on random value and relative weight
}
}
import java.util.*;
enum R {
a(.1),b(.2),c(.3),d(.4);
R(final double p) {
this.p=p;
}
private static void init() {
sums=new double[values().length+1];
sums[0]=0;
for(int i=0;i<values().length;i++)
sums[i+1]=values()[i].p+sums[i];
once=true;
}
static R random() {
if (!once) init();
final double x=Math.random();
for(int i=0;i<values().length;i++)
if (sums[i]<=x&&x<sums[i+1]) return values()[i];
throw new RuntimeException("should not happen!");
}
static boolean check() {
double sum=0;
for(R r:R.values())
sum+=r.p;
return(Math.abs(sum-1)<epsilon);
}
final double p;
static final double epsilon=.000001;
static double[] sums;
static boolean once=false;
}
public class Main{
public static void main(String[] args) {
if (!R.check()) throw new RuntimeException("values should sum to one!");
final Map<R,Integer> bins=new EnumMap<R,Integer>(R.class);
for(R r:R.values())
bins.put(r,0);
final int n=1000000;
for(int i=0;i<n;i++) {
final R r=R.random();
bins.put(r,bins.get(r)+1);
}
for(R r:R.values())
System.out.println(r+" "+r.p+" "+bins.get(r)/(double)n);
}
}
Here is another alternative which allows the distribution to be specified at runtime.
Includes suggestion from Alexey Sviridov. Also method random() could incorporate suggestion from Ted Dunning when there are many options.
private enum Option {
OPTION_1, OPTION_2, OPTION_3, OPTION_4;
static private final Integer OPTION_COUNT = EnumSet.allOf(Option.class).size();
static private final EnumMap<Option, Integer> buckets = new EnumMap<Option, Integer>(Option.class);
static private final Random random = new Random();
static private Integer total = 0;
static void setDistribution(Short[] distribution) {
if (distribution.length < OPTION_COUNT) {
throw new ArrayIndexOutOfBoundsException("distribution too short");
}
total = 0;
Short dist;
for (Option option : EnumSet.allOf(Option.class)) {
dist = distribution[option.ordinal()];
total += (dist < 0) ? 0 : dist;
buckets.put(option, total);
}
}
static Option random() {
Integer rnd = random.nextInt(total);
for (Option option : EnumSet.allOf(Option.class)) {
if (buckets.get(option) > rnd) {
return option;
}
}
throw new IndexOutOfBoundsException();
}
}
You can use EnumeratedDistribution from the Apache Commons Math library.
EnumeratedDistribution<Type> distribution = new EnumeratedDistribution<>(
RandomGeneratorFactory.createRandomGenerator(new Random()),
List.of(
new Pair<>(Type.TYPE_A, 0.2), // get TYPE_A with probability 0.2
new Pair<>(Type.TYPE_B, 0.5), // get TYPE_B with probability 0.5
new Pair<>(Type.TYPE_C, 0.3) // get TYPE_C with probability 0.3
)
);
Type mySample = distribution.sample();