Making a int with Math.random pick a new number when called - java

Right now my variables all are being rolled randomly but only once. How can I make it so that when the ints are called they roll a new number? All the stats are currently the same number. And everything is rolled only once.
int throwD4 = (int)(Math.random()*4+1);
int throwD6 = (int)(Math.random()*6+1);
int throwD8 = (int)(Math.random()*8+1);
int throwD10 = (int)(Math.random()*10+1);
int throwD12 = (int)(Math.random()*12+1);
int throwD20 = (int)(Math.random()*20+1);
int throwD100 = (int)(Math.random()*100+1);
int stat = (int)(throwD6 + throwD6 + throwD6);
String description = "A big strong dude with a cool longsword.";
String name = "Gladiator";
// stats
int STR = stat;
int DEX = stat;
int CON = stat;
int INT = stat;
int WIS = stat;
int CHA = stat;'

Yes, you will certainly find that if you calculate a formula and then store it in a variable, then the variable will keep its value unless the formula is re-calculated and stored again in the variable. Accessing a variable's value doesn't re-run the formula that created it; the variable is just a dumb number that doesn't remember the formula. The fact that variables don't change unless you change them will be mighty handy over the lifecycle of your program.
Consider creating a method that returns you a random number, and every time you want a random, call the method:
public int throwDice(int howManySides){
return (int)(Math.random()*(howManySides+1));
}
If you want more advice on how this might be used, add some contexts to your question as to how you're currently using e.g. throwD6
In essence, every time you think about writing throwD6, write throwDice(6) instead. For example:
//rolling a 6 kills the character
if(throwDice(6) == 6)
character.Kill();

Related

How to assign a random value to a constant so that it does not change its value

I wanted to generate a random number using Random() and make it unchanged with-in a given execution irrespective of number of calls to that method.
How can I do it?
The following explanation would make my question more clear.
I am generating a randomNumber within a range by the following method.
private int generateARandomNumber(int min, int max) {
// min = 101;
// max = 10001;
Random random = new Random();
myRandomNum = random.nextInt(max - min) + min ;
return myRandomNum;
}
How can I assign the value returned to a constant like
MYID = generateARandomNumber(101,10001),
which will remain unchanged for this execution?
Declare the constant and make it final:
final int MYID = generateARandomNumber(101, 10001);
Final variables cannot be changed after being assigned (similar to “let” statements in other programming languages).

JAVA seperate class method not incrementing a variable in my main class method

so this is the main code for my text-based game.
import java.util.Scanner;
public class D_M_RPG {
public static void main(String[] args) {
//Creating the class to call on my toolbox
D_M_RPGtoolbox toolbox = new D_M_RPGtoolbox();
//Creating the scanner class for user input
Scanner input = new Scanner(System.in);
//Initiating variables and final variables aswell as arrays
//token variable to validate open spots in an array
int slotCounter = 0;
int inventoryExpander = 11;
//First initiated will be the character creation variables
String hairColor = "";
String eyeColor = "";
String skinColor = "";
String gender = "";
//Initiating the arrays for character inventory slots
String[] weaponSlots = new String[10];
//initiating the arrays for the character creation
String[] hairColorARR = {"black","Green","Yellow","Brown","Blue","Blonde","Grey","White"};
String[] eyeColorARR = {"Green","Brown","Blue","Grey",};
String[] skinColorARR = {"White","brown","Black",};
String[] genderARR = {"Male","Female"};
//Creating the introduction title and introduction
System.out.println("Welcome to, COLD OMEN.");
System.out.println("\nNOVEMBER 12th, 2150: ONTARIO, CANADA");
System.out.println("\nYou hear loud shouts and gun fire all around you but can't pinpoint the location of anything, you feel a bit dazed until someone grabs you and you open your eyes and snap out of it.");
System.out.println("\nUnknown: 'Get up, its time to move out. Take this.'");
System.out.println("\nUnknown hands you a 'M4-A4 RIFLE'");
System.out.println("\nyou manage to catch a small glimpse of him before you get up.");
//Character creation screen
System.out.println();
//ONLY WORKS ONCE WONT INCREMEMENT THE SLOTCOUNTER
toolbox.insert(weaponSlots, slotCounter, inventoryExpander, "M4-A4 RIFLE");
System.out.println("\n" + weaponSlots[0]);
toolbox.insert(weaponSlots, slotCounter, inventoryExpander, "ak47");
System.out.println(weaponSlots[0]);
}
}
so I have this method I made to basically add an "item" to the weaponSlots array (the inventory) but whenever I run it it will add to the first element in the array [0] but it wont incremement the slotcounter which should go up by one every time the method is used so that I dont replace any items in the array It should just add items until its full which is checked using the inventoryExpander variable. at the moment I have it printing the element at 0 and 0 for the array but i have checked 1 aswell and 1 is just null no item added it only just replaces the element at 0. heres the code for the method to increment etc:
public class D_M_RPGtoolbox {
//method for random number generating to be used for crit hits, turns, loot generation etc
public int randomGen(){
int x = (int) (Math.random()*((20-0)+1)+0);
return x;
}
//method for inserting into an array ONLY WORKS ONCE WONT INCREMEMENT THE SLOTCOUNTER FIX
public void insert(String[] a, int b, int d , String c) {
if(b < d) {
a[b] = c;
b++;
}//end of if statement
}//end of method
}
What you are actually performing the ++ operation on in b is a copy of the value in slotCounter.
The variable slotCounter is passed into insert "by-value".
This unlike what you probably imagine, that it is passed "by-reference".
One solution would be to do the slotCounter++ from the call row instead; and another would be to let the toolbox own the slotCounter variable completely.
This question uses the image of passing a copy of document content (by value) where changes to the document would not be seen by the sender; or as a link to a shared document (by reference), where changes could be made to the same page that the sender sees.
Its always going to be zero since you are passing zero and incrementing the local variable b.
Try calling the method as below with post increment ++ to slotCounter and see if it works for you,
toolbox.insert(weaponSlots, slotCounter++, inventoryExpander, "M4-A4 RIFLE");

Multidata Type Array In Java

Complete newbie here guys. I'm working on a Java program to prompt the user for 3 variables which are used to calculate a future investment's value. Everything works perfectly, except when it comes time to put both my datatypes into ONE array.
Here's what the output SHOULD look like:
Year Future Value
1 $1093.80
2 $1196.41
3 $1308.65
...
This is what mine looks like:
Year 1
Future Value 1093.81
Year 2
Future Value 1196.41
Year 3
Future Value 1308.65
...
My year is an int value and my Future value is a double (rounded). I've been sitting here racking my brain and all the forums I can find and haven't been successful. Every time I put both value into an array I get an error about putting two different datatypes together. Any insight would be greatly appreciated. Below is the code for my full program:
import java.util.Scanner;
class investmentValue {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print("Enter investment amount: $");
double i = s.nextDouble();
System.out.print("Enter percentage rate: ");
double r = s.nextDouble()/100;
System.out.print("Enter number of years: ");
int y = s.nextInt();
for (y=1; y<=30; y++) {
double f = futureInvestmentValue(i,r,y);
System.out.println("Year " + y);
System.out.println("Future Value " + f);
}
}
public static double futureInvestmentValue (double investmentAmount, double monthlyInterestRate, int years){
double value=1;
value = investmentAmount*Math.pow((1+(monthlyInterestRate/12)),(years * 12));
double roundValue = Math.round(value*100.0)/100.0;
return roundValue;
}
}
One solution is to start by implementing a pad function. Something like,
public static String pad(String in, int len) {
StringBuilder sb = new StringBuilder(len);
sb.append(in);
for (int i = in.length(); i < len; i++) {
sb.append(' ');
}
return sb.toString();
}
Now we can combine that with String.format() to get the dollars and cents, use a consistent printf() for the header and output lines. To get something like,
// Print the header.
System.out.printf("%s %s%n", pad("Year", 12), "Future Value");
for (int y = 1; y <= 30; y++) {
String year = pad(String.valueOf(y), 13); // <-- One more in your alignment.
String fv = String.format("$%.2f", futureInvestmentValue(i,r,y));
System.out.printf("%s %s%n", year, fv);
}
The System.out.println command isn't the only method available to you!
Try this in your loop:
System.out.print(y); // note that we use print() instead of println()
System.out.print('\t'); // tab character to format things nicely
System.out.println(f); // ok - now ready for println() so we move to the next line
Naturally, you'll want to do something similar to put your headings in.
PS - I'm pretty sure this is just an output formatting question - you don't really want to put all these values into a single array, right?
Given that you really are looking for formatted output, it may be better to use the printf() method.
The following inside the loop (instead of the 3 lines I wrote above) should do the trick (untested - I haven't used printf() format strings in a long, long time).
System.out.printf("%i\t$%0.2f", y, f);
EDIT: edited to answer your question in the comments about constructors... You should also check out this for further understanding
You could create a class that will hold both of the arrays...
This would give you a single object, let's call it StockData, that holds two arrays for the two separate types you need. You need to create the object once and then insert the data separately by type.
class StockData {
double[] data1;
int[] data2;
// default constructor
StockData() {
}
// constructor
StockData(double[] data1, int[] data2) {
this.data1 = data1;
this.data2 = data2;
}
// getters, setters...
}
Then you add data to an array of its type:
// using default constructor to add a single value to both arrays
StockData sd = new StockData();
sd.data1[INDEX_X] = YOUR_DOUBLE;
sd.data2[INDEX_X] = YOUR_INT;
// using default constructor to add all data to both arrays
StockData sd = new StockData();
sd.data1 = YOUR_ARRAY_OF_DOUBLE;
sd.data2 = YOUR_ARRAY_OF_INTS;
// using constructor to add all array data directly
StockData sd = new StockData(YOUR_ARRAY_OF_DOUBLE, YOUR_ARRAY_OF_INTS);
You could also have an object that will hold the double and int value, so the object will represent a single stock information of 2 values and then create an array containing those objects...
class StockData {
double data1;
int data2;
// default constructor same as before
// constructor
StockData(double data1, int data2) {
this.data1 = data1;
this.data2 = data2;
}
// getters, setters...
}
// ...
Adding data:
// create an array of StockData objects
StockData[] sd = new StockData[TOTAL_AMOUNT_OF_DATA];
// ... obtain your data
// using default constructor to add a single value to the array
sd[INDEX_X] = new StockData();
sd[INDEX_X].data1 = YOUR_DOUBLE;
sd[INDEX_X].data2 = YOUR_INT;
// using constructor to add all data directly
sd[INDEX_X] = new StockData(YOUR_DOUBLE, YOUR_INT);
If you want the program to have an specific format you could try to change your code and put this where your for is:
System.out.println("Year Future Value");
for (y=1; y<=30; y++) {
double f = futureInvestmentValue(i,r,y);
System.out.print(y);
System.out.println(" " + f);
}
this way you will have your output in the format you need without using arrays. But if you want to do an array for this you could declare an array of objects and create a new object with two attributes (year and future value)
Also your class name is investmentValue and it is recommended that all classes start with upper case it should be InvestmentValue
I hope that this can help you
A fun data structure you would be able to use here is a Map (more specifically in Java, a HashMap). What you are doing is associating one value with another, an integer to a double, so you could make something that looks like this:
Map<Integer, Double> myMap = new HashMap<>();
This would take the year as the integer, and the double as the price value, and you could iterate over the map to print each value.
Additionally if you really are looking for a "multidata type array," Java automatically casts from integer to double should you need to. For example:
int i = 2;
double[] arr = new double[2];
arr[0] = 3.14
arr[1] = i;
The above code is perfectly valid.

Iterating through two arrays, having trouble with indices

I have a question about creating dynamic arrays and iterating through these arrays. I have a method setVoltage that takes as parameters a string and a double value. I needed some way to store these values so I created two arrays. What i need to do is iterate through the String array to see if the string parameter already exists and if it does, to set the corresponding voltage at that index. If it doesn't exist, i need to add the string device to the string array and also add the double voltage to the double array. Can someone check out my code and see what I am missing? I'm running into trouble because I want the array to realize the string is already in the array, or append it to the end of the array but I'm stuck on how to use index variables to achieve this. Thank you!
public final int sizeArray = 10;
private String[] deviceList = new String[sizeArray];
public double[] voltList = new double[sizeArray];
public synchronized void setVoltage(String device, double voltage) {
int index = 0;
for(int i = 0; i < deviceList.length; i++ ){
//if the device name already exists in the device array, overwrite voltage at that index
if(this.deviceList[i].equals(device)){
index = i;
voltList[index] = voltage;
}else{
//set deviceList[i] equal to device, set voltList[i] equal to voltage
deviceList[i] = device;
voltList[i] = voltage;
index++;
}
}
}
It sounds like perhaps you want a Map<String,Double> instead. This will let you store voltage values keyed by device name, and you can easily find, insert, and remove devices. See, for example, HashMap:
Map<String,Double> deviceVoltages = new HashMap<String,Double>();
deviceVoltages.put("liquifier", 8.4);
deviceVoltages.put("reflarbulator", 900.0);
deviceVoltages.put("liquifier", 13.3); // replaces previous 8.4
System.out.println(deviceVoltages.get("liquifier"));
deviceVoltages.remove("reflarbulator");
Your example code then reduces to simply:
private Map<String,Double> deviceVoltages = new HashMap<String,Double>();
public synchronized void setVoltage(String device, double voltage) {
deviceVoltages.put(device, voltage);
}
Performance will exceed that of your array, and you will not have a hard-coded limit on number of devices.
See generic Map documentation for links to other types of maps in the JDK.
See also ConcurrentHashMap if a finer synchronization granularity is desired and/or acceptable.
An alternative, if you must use arrays, is to create a Device class that encapsulates all the relevant information about a device and use a single array to simplify your logic, e.g.:
static class Device {
String name;
double voltage;
}
Device[] devices = new Device[10];
You can add new devices by replacing a null element in the array. You can update devices by finding the one with the specified name and changing its voltage field. You can optionally use a List<Device> to avoid hard-coded size limits.
It would be way better to use a Map<String,Double> in this scenario. But if you still want to use two arrays, your current code is not appending to the end of the array. Say if i=0 and deviceList[i] != device , then your code immediately overwrites deviceList[i] with the new value in the else block rather than appending it to the end of the array. To append, you have to move the code in the else part to after the for loop.
Your code will always overwrite the device if the device name was not found. It would be better if you used a Map but if you are required to use arrays you can try the following
for(int i = 0; i < deviceList.length; i++ ){
//if the device name already exists in the device array, overwrite voltage at that index
if(this.deviceList[i].equals(device)){
voltList[i] = voltage;
break;
}else if (deviceList[i] == null) {
//set deviceList[i] equal to device, set voltList[i] equal to voltage
deviceList[i] = device;
voltList[i] = voltage;
break;
}
}
You'll have to write some additional code to deal with a full array.
This is how I would do it as-is:
public void setOrAppend(String device, double voltage) {
int index = 0;
for ( ; index < deviceList.length; i++) {
if (device.equals(deviceList[index]) || deviceList[index] == null) {
break;
}
}
if (index == deviceList.length) {
deviceList = Arrays.copyOf(deviceList, deviceList.length + 1);
voltList = Arrays.copyOf(voltList, voltList.length + 1);
}
deviceList[index] = device;
voltList[index] = voltage;
}
I would recommend doing the set logic outside the loop. Additionally I would also recommend a Map for this kind of scenario since this kind of logic is simpler. A Map will already do what you are asking automatically (replace if exists otherwise append).

What is the purpose of variable duplication in a method?

I see this [below] all over in the Android code (and some other code sources). What is its point or purpose?
class Foo {
int mBar = 1337;
static void main(String... args) {
System.out.println(isFubar());
}
boolean isFubar() {
int ret = mBar; // <--- Focus of attention
if (ret == 666)
return true;
else
return false;
}
}
It seems like a waste of time and resources. mBar clearly isn't being modified. There is no risk of it being modified (in the given context), so why would one duplicate the primitive just to preform a noninvasive check on it and return?
EDIT Specific example from the class CellLayout in the Android Source
public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF dragRect) {
final boolean portrait = mPortrait; <--- Here it is
final int cellWidth = mCellWidth;
final int cellHeight = mCellHeight;
final int widthGap = mWidthGap;
final int heightGap = mHeightGap;
final int hStartPadding = portrait ? mShortAxisStartPadding : mLongAxisStartPadding;
final int vStartPadding = portrait ? mLongAxisStartPadding : mShortAxisStartPadding;
int width = cellHSpan * cellWidth + ((cellHSpan - 1) * widthGap);
int height = cellVSpan * cellHeight + ((cellVSpan - 1) * heightGap);
int x = hStartPadding + cellX * (cellWidth + widthGap);
int y = vStartPadding + cellY * (cellHeight + heightGap);
dragRect.set(x, y, x + width, y + height);
}
Perhaps for multi-threading. If the value of mPortrait changed between the following two lines you would have mixed results.
final int hStartPadding = mPortrait ? mShortAxisStartPadding : mLongAxisStartPadding;
final int vStartPadding = mPortrait ? mLongAxisStartPadding : mShortAxisStartPadding;
For example:
final int hStartPadding = true ? mShortAxisStartPadding : mLongAxisStartPadding;
// somehwere else: mPortraint = false
final int vStartPadding = false ? mLongAxisStartPadding : mShortAxisStartPadding;
A few ideas come to mind.
The expression needed to retrieve the class member variable might be really complicated (your example is not), so saving it in a local variable might be more readable.
It is possible that storing it in a local variable is more efficient, especially if the method has to access the value more than once. (Your example does not do this.)
Retrieving the value once gets its value at that moment in time, and not some later value that another thread may have modified in the meantime.
Storing it in a local variable makes it easy to examine with a debugger.
For your particular example, only reason (4) makes any sense.
I use it so i can modify the variable in recursion or loops and not mess with the original one. It also helps with passing the variables between classes and other methods.
Also, if it is changed while the method is running, the method will not mess up, it will continue with the variables it started with. I had this major problem while multi-threading my graphics printing and code. The code would change variables and weird stuff would happen on the screen.
I don't know about hardware or speed, but on the code side, it makes it very simple and flexible in many cases.

Categories