![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Professional Programmer
Join Date: Feb 2005
Posts: 327
Rep Power: 4
![]() |
why does it change both instances
Alright, so i have a class that contains a 2d array. I make 2 instances of it with the same 2d array arrangement in both of them. If i change one of them the other changes as well for some reason. I can not figure out why both change. Shouldn't only the one instance change?
Here is the node class import java.io.*;
public class GridNode
{
private int[][] state;
private GridNode firstChild;
private GridNode nextSibling;
// set state to newState and firstChild to newFirstChild and nextSibling to newNextSibling
public GridNode(int[][] newState, GridNode newFirstChild, GridNode newNextSibling)
{
state = newState;
firstChild = newFirstChild;
nextSibling = newNextSibling;
} // end GridNode constructor
// get current state
public int[][] getState()
{
return state;
} // end getState
public void setState(int[][] newState)
{
state = newState;
} // end setState
// set firstChild
public void setFirstChild(GridNode newFirstChild)
{
firstChild = newFirstChild;
} // end setFirstChild
// set nextSibling
public void setNextSibling(GridNode newNextSibling)
{
nextSibling = newNextSibling;
} // end setNextSibling
// get firstChild
public GridNode getFirstChild()
{
return firstChild;
} // end getFirstChild
// get nextSibling
public GridNode getNextSibling()
{
return nextSibling;
} // end getNextSibling
// print the current state
public void printNode()
{
for(int row = 0; row < 3; row++)
{
for(int col = 0; col < 3; col++)
System.out.print(state[row][col] + " ");
System.out.println();
} // end for
} // end printNode
// check to see if current state is equal to the goal state
public boolean isEqual(int[][] state, int[][] goalState)
{
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == goalState[row][col])
continue;
else
return false;
} // end for
} // end for
return true;
} // end isEqual
// calculates h1(n)
public int findHone(int[][] state, int[][] goalState)
{
int hOne = 0;
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] != goalState[row][col] && state[row][col] != 0)
hOne++;
else
continue;
} // end for
} // end for
return hOne;
} // end findHone
// find f(n) = g(n) + h(n)
public int findF(int g, int h)
{
return g + h;
} // end findF
// check to see if it can move left
public boolean canMoveLeft(int[][] state)
{
int tempPos = -1;
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == 0)
tempPos = col;
} // end for
} // end for
if (tempPos == 0)
return false;
else
return true;
} // end canMoveLeft
// check to see if it can move up
public boolean canMoveUp(int[][] state)
{
int tempPos = -1;
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == 0)
tempPos = row;
} // end for
} // end for
if (tempPos == 0)
return false;
else
return true;
} // end canMoveUp
// check to see if it can move right
public boolean canMoveRight(int[][] state)
{
int tempPos = -1;
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == 0)
tempPos = col;
} // end for
} // end for
if (tempPos == 2)
return false;
else
return true;
} // end canMoveRight
// check to see if it can move down
public boolean canMoveDown(int[][] state)
{
int tempPos = -1;
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == 0)
tempPos = row;
} // end for
} // end for
if (tempPos == 2)
return false;
else
return true;
} // end canMoveDown
// move it left, the old one
public void moveLeft(int[][] state)
{
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == 0)
{
state[row][col] = state[row][col-1];
state[row][col-1] = 0;
//printNode();
return;
} // end if
} // end for
} // end for
} // end moveLeft
// move it Up
public void moveUp(int[][] state)
{
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == 0)
{
state[row][col] = state[row-1][col];
state[row-1][col] = 0;
// printNode(state);
return;
} // end if
} // end for
} // end for
} // end moveUp
// move it right
public void moveRight(int[][] state)
{
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == 0)
{
state[row][col] = state[row][col+1];
state[row][col+1] = 0;
// printNode(state);
return;
} // end if
} // end for
} // end for
} // end moveRight
// move it down
public void moveDown(int[][] state)
{
//int tempPos = -1;
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
if (state[row][col] == 0)
{
state[row][col] = state[row+1][col];
state[row+1][col] = 0;
// printNode(state);
return;
} // end if
} // end for
} // end for
} // end moveDown
} // end GridNodemain where the 2 instances and everything is created public class NewMain
{
//insert new value, check to see if swap is needed
/* static void realInsert(GridNode parent, GridNode newNode)
{
if (parent.getFirstChild() == null)
parent.setFirstChild(newNode);
else
realInsert(parent.getFirstChild().getNextSibling(), newNode);
if(parent.canMoveLeft(parent.getState()))
{
parent.moveLeft(parent.getState());
System.out.println("parent after move left:");
parent.printNode();
newNode.setState(parent.getState());
System.out.println();
System.out.println("newNode after setState is called");
newNode.printNode();
parent.moveRight(parent.getState());
System.out.println();
System.out.println("parent after move back happens");
parent.printNode();
System.out.println("one final print out of newNode");
newNode.printNode();
} // end if
*/
// } // end realInsert
public static void main(String[] args)
{
int[][] initialState = {{7, 6, 4},
{8, 5, 2},
{1, 0, 3}
};
GridNode parent = new GridNode(initialState, null, null);
GridNode child = new GridNode(parent.getState(), null, null);
parent.setFirstChild(child);
child.moveLeft(child.getState());
System.out.println("this is the child");
child.printNode();
System.out.println();
System.out.println("This is the parent");
parent.printNode();
System.out.println();
System.out.println("this is the initial state");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
System.out.print(initialState[i][j] + " ");
}
System.out.println();
}
} // end main
} // end NewMain |
|
|
|
|
|
#2 |
|
Expert Programmer
|
Object variables in Java are references (similar to pointers in C). If you need an independent copy of an object you need to make it; this is usually done by implementing the Cloneable interface and overriding the clone method to create and return a new copy of the object. You might also want to investigate the difference between a "shallow" copy and a "deep" copy.
|
|
|
|
|
|
#3 |
|
Professional Programmer
Join Date: Feb 2005
Posts: 327
Rep Power: 4
![]() |
i thought that when a new instance of a class is created that a new copy of each of the methods and variables of that class went along with it. So you see the int[][] state. Lets say when i create a new GridNode, a new int[][] state is not created along with it? Then how do i do this? I do I make it so that when i say
GridNode n = new GridNode(initialState, null, null); How do i make it so that it will create a new initialState, another copy of int[][] for the new node. I am going to be doing minor manipulations to each new instance so my goal was to just create a copy of the first instances int[][] into the other ones and then do the manipulations on the other ones. But if i can't just do that with out it taking the old one with it, then what do i do? I have never heard of clonable or anything. i've been stuck on this problem for over 2 days and just want to know what im doing wrong and make it work properly. Thanks. |
|
|
|
|
|
#4 |
|
Expert Programmer
|
Now that I look more closely at your problem, I see that it is not object copying you are having trouble with but rather Java's strange implementation of arrays. Strangely enough, an array in Java is a actually a reference to an "array object" which holds references to its elements. So when you create a new GridNode as you do in the line of code you posted above, the variable n points to a distinct GridNode object. However, when you pass the initialState 2D array as an argument to the constructor, the state variable of the GridNode is a reference the original 2D array. The simplest solution is to simply call the array's clone method to create a new array. (Alternatively you could simply loop over each element and copy it into a new array; see this article for other methods.) The following example might help:
int[] p = { 1, 2, 3, 4 };
int[] q = p;
q[0] = 5;
System.out.println("p" + Arrays.toString(p) + ", q" + Arrays.toString(q));
// Output: p[5, 2, 3, 4], q[5, 2, 3, 4]
q = (int[])p.clone();
q[0] = 1;
System.out.println("p" + Arrays.toString(p) + ", q" + Arrays.toString(q));
// Output: p[5, 2, 3, 4], q[1, 2, 3, 4]Last edited by titaniumdecoy; Sep 18th, 2007 at 7:40 PM. |
|
|
|
|
|
#5 |
|
Professional Programmer
Join Date: Feb 2005
Posts: 327
Rep Power: 4
![]() |
so i think i get what your saying but then how would i make that happen because i am going to be creating like 17 or so of these GridNodes, each with a different 2d array associated to it. Should i have a method in the GridNode class that does this and then call that whenever i create a new instance or something? I tried this just to see if i could get it to work and it didnt.
GridNode parent = new GridNode(initialState, null, null);
GridNode child = new GridNode(initialState, null, null);
child.setState((int[][]) parent.getState().clone());I also tried this and it didnt work either GridNode parent = new GridNode(initialState, null, null);
GridNode child = new GridNode((int[][]) parent.getState().clone(), null, null); |
|
|
|
|
|
#6 |
|
Expert Programmer
|
Okay, you have another (big) problem: When you name a parameter of a method the same as an instance variable of that class, the parameter variable "hides" the instance variable. So, in this snippet of code, for example:
public class GridNode
{
private int[][] state;
...
public void moveRight(int[][] state) {
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
if (state[row][col] == 0) {
state[row][col] = state[row][col+1];
state[row][col+1] = 0;
return;
}
}
}
}
...
}this.state[row][col] = state[row][col+1]; Last edited by titaniumdecoy; Sep 18th, 2007 at 9:11 PM. |
|
|
|
|
|
#7 |
|
Expert Programmer
|
The cause of your problem is the fact that the clone method of a 2D array creates a shallow copy. (Stupid? Yes.) Think of a 2D array as an object with X references to Y 1D arrays (each of which contain additional references--the actual objects stored in the array). The clone method of a 2D array creates a new 2D array--but copies the references to the 1D arrays rather than cloning them! You can avoid this by writing your own method to copy a 2D array:
public static int[][] copy(int[][] a) {
int[][] b = new int[a[0].length][a.length];
for (int i = 0; i < a.length; i++)
for (int j = 0; j < a[0].length; j++)
b[i][j] = a[i][j];
return b;
}![]() |
|
|
|
|
|
#8 |
|
Resident Grouch
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jun 2005
Posts: 6,453
Rep Power: 10
![]() |
Titanium is giving you the scoop, but you don't seem to get it. Let me make an analogy. Suppose you post a memo on the bulletin board, very top left corner. Someone asks you what the memo says. You refer them to the upper left corner. Someone else asks you what the memo says. You refer them to the upper left corner.
If someone else comes along and scratches out part of the memo and replaces it, all referrals to the upper left corner memo look the same. The ARE the same. That's a reference. If you give someone a note that says, "Upper left corner", and someone else a note that says, "Upper left corner", that's two different notes, but the reference is the same, The second note is a shallow copy of the first. On the other hand, if you copy the memo and hand that out, instead of a reference to the bulletin board, that's a deep copy. If only Joe's is changed, Fred doesn't see that.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code. Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers |
|
|
|
|
|
#9 |
|
Professional Programmer
Join Date: Feb 2005
Posts: 327
Rep Power: 4
![]() |
alright so now if i wanted to make a tree with one child and then the child having up to 3 siblings all consisting of GridNodes but each int[][] state of the GridNodes would be different, how would i do that. I get the firstChild points to the child and then the nextSibling would point to the sibling and then i set those to null when i first create the instance and then when needed set them but i need to keep track of what level of the tree im in and all that too. I'm just really lost when it comes to trees so i took a class that deals with them hoping to learn only to find out today that the teacher doesn't help anyone so im actually kinda lost right now.
Alright so this is what i got on how to get it to work like i want it to int[][] initialState = {{7, 6, 4},
{8, 5, 2},
{1, 0, 3}
};
//int[][] childState = parent.copy(parent.getState());
GridNode parent = new GridNode(initialState, null, null);
int[][] childState = parent.copy(parent.getState());
GridNode child = new GridNode(childState, null, null);but now i ask if im gonna be creating a bunch of children, is there a way for me to do it without having to create a new corresponding int[][] along with it? Because then to refer to it instead of saying child.getState() to get the state couldnt i just not even use the class and just create a new int [][] within this class and just refer to that for everything? |
|
|
|
|
|
#10 |
|
Professional Programmer
Join Date: Feb 2005
Posts: 327
Rep Power: 4
![]() |
i think i got it. This is what the if statement looks like for making the left child of the tree
if (parent.canMoveLeft(parent.getState()))
{
child.setState(parent.copy(parent.getState()));
child.moveLeft(child.getState());
parent.setFirstChild(child);
System.out.println(parent.getFirstChild());
child.printNode();
System.out.println();
parent.printNode();
} // end if |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Change Link Order | matthewvb | PHP | 1 | Dec 20th, 2006 12:13 AM |
| How To Change The Style/Class Of An Object? | Sane | JavaScript and Client-Side Browser Scripting | 16 | May 26th, 2006 10:15 AM |
| Cant Change Font Properties, Urgent | brokenhope | Visual Basic .NET | 11 | Sep 20th, 2005 3:42 PM |
| how to change text colour in C | chungchung | C | 6 | Aug 16th, 2005 3:00 PM |
| How can I change .asp page of frame after every 5-10 minutes ? | sham | ASP | 1 | May 1st, 2005 8:25 PM |