Java. How to skip over an initialized variable? - java

So im making a program and a different class refers to an int in a different class:
if (Doihavetools==0 && Stone.StoneCounter>=10 && Wood.WoodCounter>=50){
but in the other class, the int is initialized before the value is "++"ed
int WoodCounter;
#Override
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
if (action.equals("Chop some wood")) {//ADD A .25 SECOND DELAY INBETWEEN CLICKS
Random Rand = new Random();
int W = Rand.nextInt(3) + 1;
if(W==2){
WoodCounter++;
}
Wood.setText("Click To Collect Wood : Wood:" + WoodCounter);
System.out.println(WoodCounter);
}
}
Is there a way so i can successfully initialize it and add to it at the same time? (i want to be able to continuously add to it)
Thanks in Advance,
Jack

I think what you want is for the variable to hold it's value. Try making another variable, a boolean, and before you initialize it, make a check to see if you have already done so. Also, declare this boolean in the class where
if (Doihavetools==0 && Stone.StoneCounter>=10 && Wood.WoodCounter>=50){
is present, at the top. (make it public)
so... then you can
if(initialized == false)
{
int WoodCounter;
initialized = true;
}
Either that, or just use Wood.WoodCounter instead of declaring a new variable.

You shouldn't declare a woodCounter variable unless you want to use it for something. Write wood.woodCounter to access the variable you seem to intend.

Related

Is there a way to force a variable out of existence in Java?

Basically, my goal is to be as efficient as possible by "deleting" variables when I'm done with them, even if still in scope. So far, I've been using if(true) to manually create a scope that defines the lifetime of variables, but I'm looking for something like, var.close(), a function that's only purpose is to cause a variable to essentially go out of scope and no longer have a memory location reserved for it.
The example I use below could obviously use for() to sidestep this particular instance(the assignment wants me not to use for()), but my concern is wider than variables used as indexes.
(ignore any other logic/syntax errors present, as I haven't proofread this yet)
package root;
import javax.swing.JOptionPane;
public class DebugEight4
{
public static void main(String[] args)
{
String array[] = new String[100];
String entry = " ";
final String STOP = "/']";
StringBuffer message = new StringBuffer(
"The words in reverse order are:\n"
);
if(true)
/*
*forces x out of scope
* after while statement ends
*/
{
int x = 0;
while(!entry.equals(STOP))
{
entry = JOptionPane.showInputDialog(null,
"Enter another word\n" +
"Enter " + STOP + " when you want to stop");
if(!entry.equals(STOP) && x != 100)//prevents fragmentation error
{
array[x] = entry;
}
else
{
JOptionPane.showMessageDialog(null, "That\'s all! Let's see the results.");
}
++x;
}
}/* end x scoping if
* If the if(true) wasn't here, x would still exist!
*/
for(int y = array.length-1; y > 0; --y)
{
message.append(array[y]);
message.append("\n");
}
JOptionPane.showMessageDialog(null, message);
}
}
Any thoughts?
This is exactly what scopes are for. You don't need to invent your own scoping system. Any variable should be declared in the smallest possible enclosing scope. But that's as far as you need to go with this. It is a visibility principle, not an efficiency principle, as all the stack needed for a method is allocated on entry to the method, and inner scopes don't correspond to bytecode instructions in any way.
To create a more-limited scope is easy enough. Just create a new block:
public static void whatever() {
int a = 5; // Exists until end of method
{
int b = 5; // Exists until end of outer block
{
int c = 5; // Exists until end of inner block
}
// c is no longer accessible
}
// b is no longer accessible
}
I'd recommend against this for a few reasons:
It's harder to read for little gain
The compiler or JIT can automatically figure out the lifetime of variables and automatically handle what you're attempting to do
You can't overlap variable lifetimes this way (nesting means that the most-nested variable must expire off the stack before less-nested ones)

How do I transfer a local variable between two classes?

I am writing a noughts and crosses code that can take console arguments to decide which strategy to use (different AI classes). If the user selects 'ultimatecomputerplayer' then this is implemented as p1/p2 depending in which order they input this and the other strategy (could be 'humanplayer' etc.)
My problem is that the ultimate class needs to know which symbol it is, at the moment the game running class just assigns p1 to X and p2 to O but my ultimate class is written assuming it is X so this poses an issue.
This is the code that assigns the strategies and symbols:
NCGridV3 theGrid = new NCGridV3(gridSize, gridSize);
GameRunnerV3 theGame = new GameRunnerV3();
Scanner sc = new Scanner(System.in);
ArrayList <NCPlayer> ret = new ArrayList <NCPlayer>();
for (int i = 1; i < args.length; i++)
{
switch (args[i])
{
case "RandomComputerPlayer":
ret.add(new RandomComputerPlayer());
break;
case "SimpleComputerPlayer":
ret.add(new SimpleComputerPlayer());
break;
case "UltimateComputerPlayer":
ret.add(new UltimateComputerPlayer());
break;
case "HumanPlayer":
ret.add(new HumanPlayer(sc, theGame));
break;
}
}
NCPlayer p1 = ret.get(0);
NCPlayer p2 = ret.get(1);
p1.setMySymbol(SquareStatus.CROSS);
p2.setMySymbol(SquareStatus.NOUGHT);
I tried to assign the strategy's symbol like so:
public class UltimateComputerPlayer extends GenericPlayer implements NCPlayer
{
public UltimateComputerPlayer()
{
super();
}
#Override
public GridCoordinate getNextMove(NCGridV3 currentGrid)
{
SquareStatus symbol = GenericPlayer.getMySymbol();
But eclipse tells me I cant make a static reference to a non-static method.
Another option I tried was passing an integer into the UltimateComputer Class which would be 'i' from the loop in the game runner class, then having the symbol assign dependent on which place the class was called like so:
public UltimateComputerPlayer()
{
super();
SquareStatus mysymbol;
if (NC == 1)
mysymbol = NCGridV3.SquareStatus.CROSS;
if (NC == 2)
mysymbol = NCGridV3.SquareStatus.NOUGHT;
}
#Override
public GridCoordinate getNextMove(NCGridV3 currentGrid)
{
.......
But this variable is not assigned in the GridCoordinate class and I dont know how to make it.
Any help is greatly appreciated, Thanks.
The second option can't work because NC is not defined (at least I can't tell where it would be) and also you assign the symbol to a local variable SquareStatus mysymbol in your constructor, which is gone as soon as you leave the constructor. You firstly have to make mysymbol an instance variable (by moving it above the constructor). Then you have the choice to either use the setter after construction or add the number to the constructor
class UltimateComputerPlayer {
private SquareStatus mysymbol;
public UltimateComputerPlayer(int nc) {
super();
if (nc == 1)
mysymbol = NCGridV3.SquareStatus.CROSS;
if (nc == 2)
mysymbol = NCGridV3.SquareStatus.NOUGHT;
}
// [...]
}
However that seems to be a generic concept and should be moved up into the parent class. Also, I would avoid using magic numbers inside the class. Make the decision of what symbol to use outside the class and call the constructor with the symbol as parameter, rather than the number.
And as #VictorSorokin says, in your first solution, just call getMySymbol() instead of GenericPlayer.getMySymbol()

Set variable to reference another variable, Java

In Android Studio, I have two array lists with a custom object
ArrayList<MenuMaker> consessionlist = new ArrayList<MenuMaker>();
ArrayList<MenuMaker> entrylist = new ArrayList<MenuMaker>();
And have a few voids that depending on which mode we are in, it needs to use one ArrayList or the other:
private void createMenuButtons()
{
int FoodSize = consessionlist.size();
...
I realize I could do an if statement that if mode = 0 use consessionlist, else use entrylist, but is there a way to say
private void setmode(mode)
{
if (mode == 0){
menulist = consessionlist;
}
else
{
menulist = entrylist;
}
}
private void createMenuButtons()
{
int FoodSize = menulist.size();
...
*Pass-by-reference vs pass-by-value seem to kick my butt on the Oracle test.
I thought I would have to use an if statement overtime I need to choose or have to add some weird complexity, but thus far its actually working as I wanted it to.

How do I check if I have just clicked on a certain object from an array?

Basicly I am creating a game that you click on falling objects, E.G cookies, and I need to know how to check and see if a certain cookie has been pressed so it can disappear but the problem is that its in an array.
Here is a bit of my code:
Input class...
public class Input implements MouseListener, MouseMotionListener{
#Override
public void mousePressed(MouseEvent e) {
if(e.getSource().equals(MainGame.CG)){
if(MainGame.MG.inGame){
//There is actually something else here but its classified (haha sorry about that)
if(e.getPoint().x > /*I NEED SOMETHING HERE*/){
//tells you if the object has been pressed
MainGame.CG.cookieClicked = true; //CG = ClickerGame
}
}
}
}
}
class with array...
public class ClickerGame extends JPanel{
public int amount;
public FallingObject[] fo = new FallingObject[120]; //THE ARRAY I'M HAVING TROUBLES WITH
/*THE REST IS A SECRET (SORRY ABOUT THAT)*/
}
If you don't understand here is a picture to demonstrate what I need...
In order to avoid having to check the coordinates of 120 different items on each click, make every element inside FallingObject[] aware of three things:
Its own area of influence (see sn00fy's answer)
The containing class (in this case probably ClickerGame
Its location in the array (an int)
To do this, you would need to change your FallingObject constructor to look something like this:
public void FallingObject(ClickerGame master, int index); //add whatever else is needed for Falling Object.
Then you could instantiate the array as follows.
for(int i = 0; i < 120; i++) {
fo[i] = new FallingObject(this, i ); //add anything else needed for the constructor
}
Then each FallingObject is responsible for its own state, and when clicked it is able to report back to the ClickerGame instance. All you need now is a method in ClickerGame which each FallingObject can call.
public void clickedObj(int index) {
FallingObject temp = null;
if(index >= 0 && index < 120) {
temp = fo[index];
//Do stuff with temp :)
}
}
To call this method from within FallingObject just reference the 'master' variable (which you should probably save as a global variable within the class.
You have to check every element in your FallingObject[] array if it intersects with the mouse pointer coordinates at the moment of the click.
You can implement a simple rectangle test or use a circle for each cookie as explained here:
Equation for testing if a point is inside a circle

Java: Copy Constructor not going as planned

I have a bit of a problem. I'm making a Finite Automata checker.
Given an input, and the DFA, does it end on a accepting state.
My problem is creating a new DFA_State from another's target.
DFA_State state0, state1, curr_state, init_state, temp; //fine, I think
state0 = new DFA_State();
state1 = new DFA_State();
state0 = new DFA_State("State 0",true, state0, state1); //fine, I think
init_state = new DFA_State(state0); //fine, I think
but, this bit is throwing up problems.
temp = new DFA_State(curr_state.nextState(arr1[i]));
*
*
curr_state = new DFA_State(temp);
Thanks for any help,
Dave
Edit:
God I was retarded when I did this, AFAIK, I just wasn't thinking straight, added methods to set the values to the DFA_State object.
//in DFA_State class
public void set(DFA_State on_0, DFA_State on_1, Boolean is_accepting, String name){
this.on_0 = on_0;
this.on_1 = on_1;
this.is_accepting = is_accepting;
this.name = name;
}
//in main
DFA_State state0, state1, curr_state;
state0 = new DFA_State();
state1 = new DFA_State();
state0.set(state0, state1, false, "State 0");
state1.set(state1, state0, true, "State 1");
curr_state = state0;//initial state
//iterate across string input changing curr_state depending on char c
curr_state = getNextState(c);
//at end
if(curr_state.isAccepting())
System.out.println("Valid, " + curr_state.getName() + " is accepting);
else
System.out.println("Invalid, " + curr_state.getName() + " is not accepting);
In that first line, you declare the variables state0, state1, curr_state, init_state and temp as being variables of type DFA_State. However, that only declares them, they are not yet initialized. The next few lines are all okay. Second line creates a state without anything in it and assigns it to state0, so does the third line for state1. Fourth line overwrites your previous state0 assignment with a new DFA_State that has actual contents. Fifth line creates a DFA_State as a copy of state0 and assigns it to init_state.
Assuming there's nothing in between this and the first line of your second code block, now you'll get a problem. You're assigning temp with a new DFA_State that uses a copy-constructor with an argument relying on curr_state. But at that point, that variable hasn't been initialized yet. Just because it was declared doesn't mean it has somehow already been structured in memory. When you call nextState on it, there's simply no variable to resolve this to. Don't expect to get something like a pointer that will eventually point to a part of what you put in curr_state.
I'm just guessing, but from your code style I'd say you have a background in C or C++. Look into the differences between those languages and Java. If possible, I'd also advise you to make your DFA_State class immutable, since this is more reliable and will avoid mistakes. That means getting rid of the no-args constructor. Here's a reworking of it (not actually compiled, might contain errors):
package foundations.of.computing;
/**
*
* #author Kayotic
*/
class DFA_State {
private final String state;
private final DFA_State on_0;
private final DFA_State on_1;
private final boolean isAccepting;
//private DFA_State dummy;
public DFA_State(DFA_State arg) {
//this(arg.is_accepting(), arg.on0(), arg.on1());
state = arg.get_name();
isAccepting = arg.is_accepting();
on_0 = arg.on0();
on_1 = arg.on1();
}
public DFA_State(String name, Boolean accepting, DFA_State on0, DFA_State on1) {
state = name;
isAccepting = accepting;
on_0 = on0;
on_1 = on1;
}
public String get_name(){
return state;
}
public Boolean is_accepting() {
return isAccepting;
}
public DFA_State on0() {
return on_0;
}
public DFA_State on1() {
return on_1;
}
public DFA_State nextState(char i) {
if (i == '0') {
return on0();
} else if (i == '1') {
return on1();
} else {
System.out.println("Error with input");
return null;
}
}
}
Even if you can't make the instance variables final, it's best to at least make them private, since you already have methods for getting them.
There are better memory representations of DFAs than the object-oriented.
You should use a simple lookuptable:
int[] table = new int[vocabularyCount][stateCount];
Every State and every word gets a number, starting with 0.
Fill the table with the state transitions, or -1, if there is no transition. Now you just need the translation methods for the states and the words.
Heres a generic DFA algorithm:
public boolean checkSentence(String s, int[] finishes) {
// fill table
int state = 0; // assuming S0 is the start state
for (int i = 0; i < s.length(); i++) {
state = table[translate(s.charAt(i))][s];
}
for (int i = 0; i < finishes.length; i++) {
if (finishes[i] == state) {
return true;
}
}
return false;
}
The program is quite poorly written. Look at this in your FoundationsOfComputing.java:
state0 = new DFA_State();
state1 = new DFA_State();
state0 = new DFA_State("State 0",true, state0, state1);
You essentially created 3 instances of state - two instances which are not initialized (first two lines in your code) - all their instance variables are null.
Then you create the third instance, which you point to the first two uninitialized ones, and assign it to state0 variable. Please note, at this point, it is only the value of the variable that changes, not the values you passed in the DFA-State constructor!!! So, what you now have in state0 is a state that points to two uninitialized states.
Now let's look at the code further down in the FoundationsOfComputing.java:
while (i < arr1.length) {//loops through array
System.out.println(i + ". scan shows " + arr1[i]);
temp = new DFA_State(curr_state.nextState(arr1[i]));
System.out.println(" "+curr_state.get_name()+ " moves onto " + temp.get_name());
curr_state = new DFA_State(temp);
i++;
}
I am guessing this throws NullPointerException - that code moves to the on_0 state of state0 - which is a state that has not been initialized (all it's instance variables are null), so in the following pass of the loop, when it calls curr_state.nextState(whatever), it would return null and you are trying to pass that to the copy-constructor which would result in NPE.
Ok so we know this is homework. Let's do this instead of telling you the answer let's try and work through it on your own. If you are seeing a NullPointerException (NPE). Grab the second line of the exception:
java.lang.NullPointerException: null
at com.blah.blah.SomeObject.someMethod(SomeArgumentType):1234 <<< here
....
That 1234 is the line number in the file that contains SomeObject. If you goto that line number you can see exactly where the NPE is being generated from. For example if line 1234 was:
this.foo = bar.indexOf("caramel");
You can easily deduce what was null. No clue? Well this can never be null so this.foo isn't the problem. If this could be null you couldn't be inside that method because this points to the instance you are currently within. Therefore, the only other statement where a variable is being dereferenced is bar so bar must be null. Let's look at your code:
temp = new DFA_State(curr_state.nextState(arr1[i]));
Say you find out the line above is tossing an exception. Well there could be several things that could be null. curr_state could be null, or arr1 could be null in which case this line would blow up. However, if arr1[i] is null or curr_state.nextState() is returning null then you won't see the NPE pointing at this line, but would be coming out of the constructor should someone try to call methods on that method parameter.
Hopefully, this will give you the tools you need to track down problems in your application by understanding exception stack traces.

Categories