Reusing variable from a different class? - java

This is probably quite simple, but i just dont know how to do it?
How do i reuse this from a class file:
int randomNum = 5 + (int)(Math.random() * ((10 - 5) + 1));
To then use the same result that this procures in another class file?
My CityWall Class (The Class containing the int i want to use.)
public class CityWalls extends Thing {
int randomNum = 5 + (int)(Math.random() * ((10 - 5) + 1));
public CityWalls(City c, int st, int av, Direction d) {
super(c, st ,av ,d);
int oddIncrement = 0;
if (randomNum % 2 == 0)
{
oddIncrement = 1;
}
for (int i = 0; i < randomNum; i++) {
new Wall(c, i+(7-randomNum/2), (7-randomNum/2), Direction.WEST);
new Wall(c, i+(7-randomNum/2), (7+randomNum/2) - oddIncrement, Direction.EAST);
new Wall(c, (7-randomNum/2), i+(7-randomNum/2), Direction.NORTH);
new Wall(c, (7+randomNum/2)-oddIncrement, i+(7-randomNum/2), Direction.SOUTH);
}
}
public int getRandomNum() {
return randomNum;
}
}
Here is my World Class (The Class where i want to reuse the variable).
public class World {
public static void main (String[] args) {
int height = 0, width = 0, top = 5, left = 5, thingCount = 20;
World b = new World();
Random rand = new Random();
// int RandomNumber = rand.nextInt(9);
CityWalls cw = new CityWalls(Gothenburg, 5 , 5, Direction.NORTH);
int RandomNumber = cw.getRandomNum();
height = (int)(Math.random() * 0.5) + RandomNumber; // I want to use the variable here.
width = (int)(Math.random() * 0.5) + RandomNumber; // And here to replace the RandomNumber. then it should be correct.
City Gothenburg = new City(16,16);
Thing[] things = ThingSpawnCity(Gothenburg, width, height, top, left, thingCount);
RobotFinder terminator = new RobotFinder(Gothenburg, 7, 7, Direction.NORTH, 0);
terminator.run();
}
public static Thing[] ThingSpawnCity(City Gothenburg, int width, int height, int top, int left, int objects){
Thing things[] = new Thing[objects];
int avenue = 0, street = 0;
for (int i = 0; i < objects; i++){
avenue = (int)(Math.random() * width) + left;
street = (int)(Math.random() * height) + top;
things[i] = new Thing(Gothenburg, street, avenue);
}
return things;
}
}

You need a reference to an instance of the class you want to use. You need need to access the field you want to use in that class. e.g.
class A {
int randomNum = 5 + (int)(Math.random() * ((10 - 5) + 1));
}
class B {
public void printNum(B b) {
System.out.println("Random Num " + b.randomNum);
}
}
public static void main(String... ignored) {
A a = new A();
B b = new B();
b.printNum(a);
}

Have a read about encapsulation and getters and setters, and you could do it like this:
int randomNum = 5 + (int)(Math.random() * ((10 - 5) + 1));
MySuperOtherClass other = new MySuperOtherClass();
other.setX(randomNum);
// now you can get it back with other.getX();

Add a getter for it in your class and make it public
public int getRandomNum() {
return randomNum;
}
EDIT
Class containing your random number:
public class ClassHavingARandomNumner {
int randomNum = 5 + (int)(Math.random() * ((10 - 5) + 1));
public int getRandomNum() {
return randomNum;
}
}
Another class that wants to access the random number
public class ClassWantingARandomNumber {
public static void main(String[] args) {
// create an instance of the class containing the random number
ClassHavingARandomNumner c = new ClassHavingARandomNumner();
// call the getter method to retrieve the random number
System.out.println(c.getRandomNum());
}
}
EDIT 2
first move
int randomNum = 5 + (int)(Math.random() * ((10 - 5) + 1));
outside of the constructor the make randomNumber a member variable of the class CiytWalls
Second, add the getter to CityWalls
Then in main assign the result of the constructor call to a local variable
CityWalls cw = new CityWalls(Gothenburg, 5 , 5, Direction.NORTH);
after that you can acces the random number of the CityWalls object you have created using:
int rn = cw.getRandomNumber();

You can do so by making member variable randomNum as static variable of class CityWalls. And use that variable to your World class. By doing so you will get the same value as specified in CityWalls class. But you actually want to reuse or I would say use the variable with the same name & don't want to allocate memory for it or any other reason you find it useful for your case then you should extend CityWalls class to your World class.
Hope this clarified your doubt.

Related

Not getting right output for natural log formula

I'm trying to get my program to out the first 500 values for this formula: -12*ln(1-x) where x is the return of double next(). I don't know what I'm doing wrong because I can't get the right output. The random number uses this formula x(i+1) = (a * x(i) + c) mod k
public class myRnd {
// Linear values for x(i+1) = (a * x(i) + c) % k
final static int a = 7893;
final static int c = 3517;
final static int k = 8192;
// Current value for returning
int x;
int y;
int z;
public myRnd() {
// Constructor simply sets value to half of k
x = (125*k) /1024;
//y = (125*k) /1024;
}
double next() {
// Calculate next value in sequence
x = (a * x + c) % k;
// Return its 0 to 1 value
return (double)x / k;
}
public static void main(String[] args) {
int situation;
double sec_answer;
// Create a new myRnd instance
myRnd r = new myRnd();
// Output 53 random numbers from it
for (int i = 0; i < 53; i++) {
System.out.println (r.next());
}
System.out.println("random variable");
for(int b = 0; b < 500; b++){
sec_answer = (-12)*Math.log(1- r.next());
System.out.println(sec_answer);
}
}
}
I suppose these are the first 5 values you're expecting from your program in each loop!
0.9302978515625
0.270263671875
0.6204833984375
0.90478515625
0.8985595703125
random variable
31.962289651479345
3.78086405322487
11.626283246646423
28.21943313114782
27.45940262908609
In your main method you have only one instance of the class:
// Create a new myRnd instance
myRnd r = new myRnd();
This initialization is propagated to both for loops.
Simple Solution: Add another instance / initialization of myRnd for the second for loop, as an example you could reuse the same variable as r = new myRnd(); before the second loop.

create random mines for a minesweeper game

JButton[][] buttons = new JButton[20][20];
public void mines(){
ArrayList<Integer> x = new ArrayList<>();
ArrayList<Integer> y = new ArrayList<>();
for(int a=0;a<20;a++){
x.add(a);
y.add(a);
}
for(int i=0;i<30;i++){
int random_x = x.get(new Random().nextInt(x.size()));
int random_y = y.get(new Random().nextInt(y.size()));
x.remove(random_x);
y.remove(random_y);
buttons[random_x][random_y].setText("X");
}
}
I Want to create random mines for a minesweeper game..can anyone tell what I am doing wrong ?If i run the program it won't show me 30 random mines
You have chosen an unusual model for holding information on where mines are located. While you will likely resolve the immediate problem through some judicious debugging I expect it will cause you further problems down the track.
I would suggest changing your model to be something more direct such as:
class Cell {
private final JButton button = new JButton();
private boolean mine = false;
private boolean hidden = true;
public Cell() {
button.setText(" ");
}
public void setMine() {
assert hidden;
mine = true;
}
public boolean hasMine() {
return mine;
}
public void reveal() {
hidden = false;
button.setText(mine ? "X" : "-");
}
public boolean isHidden() {
return hidden;
}
}
class Field {
public static final int SIZE = 20;
private final Cell[][] cells = new Cell[SIZE][SIZE];
public Field(int minesToAdd) {
for (int x = 0; x < SIZE; ++) {
for (int y = 0; y < SIZE; y++) {
cells[x][y] = new Cell();
}
}
Random random = new Random();
while (minesToAdd > 0) {
Cell cell = cells[random.nextInt(SIZE)][random.nextInt(SIZE)];
if (!cell.hasMine()) {
cell.setMine();
minesToAdd--;
}
}
}
public JPanel getButtonPanel() {
....
}
}
I believe that would make your intention clearer. There are a few issues with this such as the tight link between the model and presentation (JButton) but that's entirely fixable with various design patterns.
Try this method:
public static void mines(JButton[][] buttons)
{
Random rand = new Random();
int mineCount = 0;
while (mineCount < 30)
{
int randomInteger = (int) (rand.nextDouble() * buttons.length);
int randomInteger2 = (int) (rand.nextDouble() * buttons[0].length);
if (buttons[randomInteger][randomInteger2].getText().equals("X"))
continue;
else
{
buttons[randomInteger][randomInteger2].setText("X");
mineCount++;
}
}
}
.nextDouble() method returns a Double value less than 1.0. But we need a random integer between 0 and 19(which is buttons.length-1).
So we multiply this random double value with the size of the button list, which is 20, and we cast it to int. So we can get values between 0 and 19.
Difference between buttons.length and buttons[0].length is, with the first one you get the length of first dimension(it's a two dimension array, as you know) and the second one gives the length of the second dimension. So you get the number dynamically and multiply with the random number, to avoid ArrayIndexOutOfBounds exception.
You can use this method with any size of two dimensional buttons array, it will work. But warning, if you use an array which has less than 30 buttons, while loop will continue forever, as you can't get 30 mines :)
One way to improve this method would be parameterizing mineCount, so you can change the method like public static void mines(JButton[][] buttons, int mineCount) so you can set mine count on method call.
This here:
for (int i = 0; i < 30; i++) {
int random_x = x.get(new Random().nextInt(x.size()));
int random_y = y.get(new Random().nextInt(y.size()));
x.remove(random_x);
y.remove(random_y);
....
is going to generate a IndexOutOfBoundsException some when....
Your List have 20 elements and you are removing 30 times element from it...
Your random coordinates may be larger than your grid size. If the size of x is 20, and your random_x is also 20, you will have an IndexOutOfBoundsException.
Change it to:
int random_x = x.get(new Random().nextInt(x.size() - 1));
int random_y = y.get(new Random().nextInt(y.size() - 1));
Which will give you a random number between 0 and 19, if the size is 20.
Additionally, because your List is of type Integer, the x.remove(random_x) call is interpreting it as the index in the list, not the object itself.
To fix this, use an Integer, not an int when calling remove(). Such as:
x.remove(Integer.valueOf(random_x));
Edit:
To further improve/fix the random generator, change it to:
int random_x = x.get(new Random().nextInt(x.size() == 1 ? 1 : x.size() - 1));
When tested with the following snippet:
Test t = new Test();
t.mines();
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
if ("X".equals(t.buttons[i][j].getText())) {
System.out.println("x:" + i + ", y:" + j);
}
}
}
Gives the output:
x:0, y:18
x:1, y:5
x:2, y:1
x:3, y:3
x:4, y:9
x:5, y:15
x:6, y:14
x:7, y:10
x:8, y:8
x:9, y:11
x:10, y:16
x:11, y:17
x:12, y:0
x:13, y:7
x:14, y:4
x:15, y:12
x:16, y:2
x:17, y:6
x:18, y:13
x:19, y:19
You can try with this:
int x = 20;
int y = 20;
JButton[][] buttons = new JButton[x][y];
public void mines(){
int mines = 30;
Random rand = new Random()
while(mines>0){
int random_x = rand.nextInt(x);
int random_y = rand.nextInt(y);
if(buttons[random_x][random_y]!=null){
buttons[random_x][random_y] = new Button();
buttons[random_x][random_y].setText("X")
mines--;
}
}
}

Java Bean Drop, Only Going to The Right

I have this game where a ball drops on the screen. The problem is, the ball only goes to right.
I believe the issue is in the transition from The LR method to the main game loop. I created a variable and it takes the LR method and runs it inside the loop that refreshes and clears the canvas every second.
Here is the code:
package cats;
public class BeanDrop {
public static void main(String[] args) throws InterruptedException {
mainGameLoop();
}
public static void mainGameLoop() throws InterruptedException{
double x = .5;
double y = .9;
while (true){
int choice = LR();
arena();
ball(x , y);
if (choice == 1){
// right outcome
x = x + .1;
}
else if(choice == 2){
//left outcome
x = x -.1;
}
y = y - .1;
Thread.sleep(1000);
StdDraw.clear();
}
}
public static void arena(){
StdDraw.picture(.5, .5, "balldrop.jpeg");
}
private static int LR(){
int choice = ((int) Math.random() * 2 + 1);
return choice;
}
public static void ball(double x , double y){
StdDraw.picture(x, y, "ball.jpeg",.05,.05);
}
}
Take a look at this:
How do I generate random integers within a specific range in Java?
What it says basically is to use this to get a random number:
Random rand;
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
So for you, you could use this:
private static int LR(){
int choice = rand.nextInt(2) + 1;
return choice;
}
EDIT: You must make an instance of Random and name it rand at the top of your code:
private Random rand;
And have this before you initialize the game loop:
rand = new Random();

How can I display an array from a void method?

I am a beginner with java and am trying to make a game of Yahtzee and am required to take a random dice roll as an array from a void method. Could someone explain to me why this wont work?
import java.util.Arrays;
public class YatzeeGame {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] diceRolls = new int[5];
diceRolls = throwDice(diceRolls);
System.out.println(display(diceRolls));
}
public static void throwDice(int [] dice) {
int [] roll = {(int)(Math.random()*6+1),
(int)(Math.random()*6+1),(int)(Math.random()*6+1),
(int)(Math.random()*6+1),(int)(Math.random()*6+1),
(int)(Math.random()*6+1)};
dice = roll;
}
public static String display(int [] dice) {
String str = Arrays.toString(dice);
str = str.replace("[", "");
str = str.replace("]", "");
str = str.replace("," , " ");
return str;
}
They want you to replace the array, which doesn't happen if you just assign it. Note that returning the array is still considered a better way. Extra tricky: in your existing code you make one array of size 5 and the other of size 6. Since you're calling it zahtzee we'll use 5.
public static void throwDice(int [] dice) {
for (int x = 0; x < 5; x++)
dice[x] = (int)(Math.random()*6+1);
}
There's quite a few things wrong in your code.
In the throwDice method, dice is a local variable, therefore changing it to roll, which is another local variable, doesn't affect anything outside that method.
Also your return type is void, so you cannot set any variable using the method.
You could have a method that returns an int[]:
public static int[] throwDice() {
int[] roll = new int[6];
for (int i = 0; i < 6; i++) {
roll[i] = (int) (Math.random() * 6) + 1;
}
return roll;
}
Then use it like:
int[] diceRolls = throwDice();
Explanation of why it's not working:
What you're trying to do: Change dice (the parameter you passed in) to equal to roll. Essentially, (if i'm not wrong here) you're trying to change diceRolls using throwDice.
What you're actually doing: You've passed in diceRolls and said "here, let's call it dice". Then, at the end of your function, you've essentially said "dice doesn't mean diceRolls anymore. dice now means roll". Which means that diceRolls still hasn't changed.
You need to change the actual values of dice instead of changing what dice is.
eg:
public static void throwDice(int[] dice) {
// change the actual values of dice, instead of changing dice
dice[0] = (int) (Math.random() * 6 + 1);
dice[1] = (int) (Math.random() * 6 + 1);
dice[2] = (int) (Math.random() * 6 + 1);
dice[3] = (int) (Math.random() * 6 + 1);
dice[4] = (int) (Math.random() * 6 + 1);
}

How to create an array with a random amount of values

I need to create an array that has a random amount of values from 8 to 12, but it says my variable is incompatible. What do I have to change? Should x not be an int?
Here is the first part of the code that includes the problem:
public class Fish {
int min = 8;
int max = 12;
int x = min + (int)(Math.random() * ((max-min) + 1));
static Fish[] myFish = new Fish[x];
static int Fcount=0;
private float weight;
public Fish(float w) { weight = w;
myFish[Fcount] = this;
Fcount++;
}
public float getWeight( ) { return weight; } }
The second part of my code is:
public class GoFish {
public static void main(String[] args) {
float[] myWeights;
for (int i = 0 ; i < x ; i++){
int min = 1;
int max = 20;
myWeights[i] = min + (int)(Math.random() * ((max-min) + 1));
}
for ( float w : myWeights ) { new Fish(w); }
for ( Fish f : Fish.myFish ) {
System.out.println( f.getWeight() );
} } }
Could you also explain the problem, because I would like to understand what I'm doing wrong. I also have to make the weight a random number between 1 and 20, but I can't get this type of random numbers to work.
Edit: Since we are making the x variable static, how do I use it in the other file? because I need the array values to be random.
x is an instance variable. You're trying to access (javac compiler would say "reference") instance variable (javac would say "non-static variable") from a static context (javac would say the same thing). This won't compile because during the static Fish[] myFish = new Fish[x]; there is no any Fish instance.
You can change your code to:
static int min = 8;
static int max = 12;
static int x = min + (int)(Math.random() * ((max-min) + 1));
This will make non-static variable x static.
Here's the official explanation of static variables (officials prefer to call them class variables).

Categories

Resources