Java - Saving values for use in a different function - java

So this is a stupid dbeginner's question.
I wrote a function that checks if a specific game move is legal (Reversi). The function must only return a boolean true/false value.
Later, in a different function, I actually make the move (makeMove function). In this function, before making the move I call the isLegal function to make sure the move is legal.
Now, when the isLegal function decides the move is legal, it would help me to save the specific info that lead to the decision, and use it in the makeMove function. I have no ideah ow to do that. I tried writing a function that will store the relevant data, and then send it back, but there's an obvious provlem with scopes here.
So here's the relevant code from isLegal:
else if(board[k][l]==player){relevantDirection=false; isLegal=true; ReversiPlay.saveLegalMove(direction, k, l);}
Then the problematic saving function:
public static int[] saveLegalMove(int direction, int row, int column){
if(direction==0){ //get info from function
return legalMoveData;
}
else{ //save legal move data
int[] legalMoveData = new int[3];
legalMoveData[0]= direction;
legalMoveData[1]= row;
legalMoveData[2]= column;
return null;
}
}
And lastly, I try calling the stored data:
int[] getSavedInfo = ReversiPlay.saveLegalMove(0, 0, 0);
I'm sure there's a very simple way of pulling the variables direction+k+l... anyone?
Thanks!
Edit: Here's a clearer example:
public static boolean A(int a){
...calculations...
int x = [value]
int y = [value]
return false;}
public static void B(int a){
...calculations...
boolean h = A(3);
[here I'd like to know what x,y were]
}

else { //save legal move data
int[] legalMoveData = new int[3];
legalMoveData[0]= direction;
legalMoveData[1]= row;
legalMoveData[2]= column;
return null;
}
This part doesn't save anything. It stores the values to a local variable and returns null.
An approach would be to make a Move object that contains the data you need:
public class Move {
private int direction;
private int row;
private int column;
...
}
Your isLegal method would only tell you if the move is legal. Then you can use that same Move instance to make the move.
if(ReversiPlay.isLegalMove(move)) {
ReversiPlay.makeMove(move);
}
There is no need to explicitly save the move; you already have that information inside the Move object instance.
UPDATE
Based on your edit, perhaps it is better to return an object instead of a boolean from A:
public static boolean A(int a) {
...calculations...
int x = [value]
int y = [value]
return new MyObject(x, y, false);
}
...
MyObject myObject = A(someValue);
Then you can query myObject to see what the value of the flag is.
UPDATE
You mentioned you aren't allowed to use objects. If so, instead of making the same calculations however, you can extract that logic into its own method and then call that. That way you won't have to duplicate logic.

Related

how can i achieve setter method in the object variable?? please explain

how can i access beginX & beginY to setBeginX & setBeginY.can i use setX() method for retrieving beginX & beginY
public class Line {
private Point begin;
private Point end;
public Line (Point begin, Point end) {
this.begin = begin;
this.end=end;
}
public Line (int beginX, int beginY, int endX, int endY) {
begin = new Point(beginX, beginY);
end =new Point(endX,endY);
}
public void setBeginX(int beginX) {
// how can i set beginX here.
}
public void setBeginY(int beginY) {
// how can i set beginY here.
}
Checking the API for Point (see https://docs.oracle.com/javase/7/docs/api/java/awt/Point.html) you can see that there is no setX() or setY() but there is:
setLocation(int x, int y)
Changes the point to have the specified
location. This method is included for completeness, to parallel the
setLocation method of Component. Its behavior is identical with
move(int, int).
The coordinates x and y are also public, meaning you could access them directly. You could technically do:
public void setBeginX(int beginX) {
this.begin.setLocation(beginX, this.begin.getY());
}
I would however recommend you change your own API perhaps to allow you to set both x and y at the same time.
If you are actually asking "how can I set beginX variable passed to the constructor", you can't without making it a member variable.

How to use an "is" method

I have to create an object that uses an "is" method, basically declaring the state of the object. I am not sure how this should work. Right now am writing the method as a boolean but I am wondering if I should use a different approach, here is the code,
public class Cell
{
public int move;
public Cell(int xmove)
{
xmove = 0;
}
public boolean isempty(int x)
{
if(x == 0)
{
return true;
}
else
{
return false;
}
}
}
You are kind of on the right track but there are a bunch of issues.
First, this is much simpler
public boolean isEmpty(){
return move == 0;
}
I assumed that an instance of Cell is empty if its move is 0.
Note that I've camel cased your method name. Also, isEmpty is supposed to say something about the state of an object. It doesn't make sense to pass in x (unless you want to compare x to some property on the object instance).
Second, you constructor takes an argument, then sets it to 0. That's not going to do anything. You probably want
public Cell(int move){
this.move = move;
}
Which takes an argument and sets the field on the current instance that is being constructed to the value passed in (you defined a field move, so you probably want to set it.).
So you could do something like
Cell cell1 = new Cell(1);
Cell cell2 = new Cell(0);
cell1.isEmpty() // false;
cell2.isEmpty() // true;

Dealing with ArrayList and pass by reference

I'm using a arraylist to add states(the board state for the 8 puzzle). My problem is when I get the children of the state it changes the values stored in my array list. I'm assuming this is because ArrayList just stores pointers to the objects and not the values themselves. In order to fix this I create a new object every time before I store it into the ArrayList but I'm still having the same problem.
I will also try to follow naming conventions more often thanks for the tip.
private ArrayList<int[][]>VisitedBoard;
if(RuleNumber ==2){
//Here is my problem. This will change what is stored in VistedBoards
NextState = new State(FireRule.Rule2(WM.get_Board()));//Fire Rule
for(int j=0;j<VisitedBoards.size();j++){
//Meaning this will always be true
if(Arrays.equals(VisitedBoards.get(j), NextState.get_Board())){
Loop =true; //Loop to previous state
}
if(j==VisitedBoards.size()-1 && Loop ==false){ //If the next state is not any previously visited
NotALoop =true;
VisitedBoards.add(NextState.get_Board());
WM.set_Board(NextState.get_Board());
}
}
}
public int[][] Rule2(int [][] Board){//The FireRule Class
Find_BlankLocation(Board);
int temp;
State NewState;
temp = Board[BlankLocation[0]-1][BlankLocation[1]];
Board[BlankLocation[0]-1][BlankLocation[1]] = 0;
Board[BlankLocation[0]][BlankLocation[1]] = temp;
NewState = new State(Board);
return Board;
}
public class State { //State class
private int[][] Board;
private int[][] Goal;
private Boolean GoalFound;
public State(int[][] Start, int[][] goal){
Board = Start;
Goal = goal;
GoalFound=false;
}
public State(int[][] NewState){
Board=NewState;
}
public int[][] get_Goal(){
return Goal;
}
public int[][] get_Board(){
return Board;
}
public void set_Board(int[][] board){
Board = board;
}
public Boolean get_GoalFound(){
return GoalFound;
}
}
Containers like ArrayList work the same in all languages: they are called data structures because they organize storage/retrieval of objects. Obviously they don't store the fields of the objects themselves.
Trying to interpret your problem, maybe you don't want to share the boards between the list of visitedBoards and WM (whatever it means...). Then simply implement get_Board() to return a copy of the array instead of the Board object itself:
public int[][] get_Board(int[][] src) {
int[][] dst = new int[src.length][src[0].length];
for (int i = 0; i < src.length; i++) {
System.arraycopy(src[i], 0, dst[i], 0, src[i].length);
}
return dst;return dst;
}
Beside this, as others already told you, you'd really better to adopt the standard Java naming conventions, use meaningful names, and encapsulate your x, y and int[][] in real application classes.
Presumably, the new State object contains a pointer to the same arrayList as before. You'll want to manually copy the array out to a new one (a "deep clone" or "deep copy" as it is called). You might find this useful: Deep cloning multidimensional arrays in Java...?
Every time you create a new instance of State, you pass it the same array (whatever is returned by WM.get_Board()).
You then add that same array to VisitedBoards when you call VisitedBoards.add().
The fact that you're creating new State objects is irrelevant, because only the return value of NextState.get_Board() gets added to the list.
As a result, the list VisitedBoards always contains several references to the exact same array.
As Raffaele has suggested, you'll be fine if you make sure get_Board() returns a copy of the array in stead of a reference to the original (assuming that doesn't mess up logic that exists elsewhere).
The main thing I learned from this question is how important it is to follow naming conventions.
Your unconventional capitalization has made me dizzy!
Following these rules will make it much easier for others to understand your Java code:
class names should be capitalized (ie PascalCase)
variable names should be lowercase (ie camelCase)
do not use underscores in method names, class names, or variable names (they should only be used for constants)
always use meaningful names when possible
My advice is to create your own container object for their 2D array and implement deep copying.
For example:
package netbeans;
import java.util.Arrays;
public class Container
implements Cloneable
{
private int [] _data;
private int _sx;
private int _sy;
public int get(int x, int y)
{
try { return this._data[y*this._sx+x]; }
catch (Exception e) { throw new ArrayIndexOutOfBoundsException(); }
}
public void set(int x, int y, int value)
{
try { this._data[y*this._sx+x] = value; }
catch (Exception e) { throw new ArrayIndexOutOfBoundsException(); }
}
public Object Clone() { return new Container(this); }
public Container(int sizeX, int sizeY, int [] data)
{
this._sx = sizeX;
this._sy = sizeY;
this._data = data;
}
public Container(Container cont)
{
this._data = Arrays.copyOf(cont._data, cont._data.length);
}
}

How to use writeStringArray() and readStringArray() in a Parcel

I recently came across a very stupid (at least from my point of view) implementation inside Androids Parcel class.
Suppose I have a simple class like this
class Foo implements Parcelable{
private String[] bars;
//other members
public in describeContents(){
return 0;
}
public void writeToParcel(Parcel dest, int flags){
dest.writeStringArray(bars);
//parcel others
}
private Foo(Parcel source){
source.readStringArray(bars);
//unparcel other members
}
public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>(){
public Foo createFromParcel(Parcel source){
return new Foo(source);
}
public Foo[] newArray(int size){
return new Foo[size];
}
};
}
Now, if I want to Parcel a Foo Object and bars is null I see no way to recover from this situation (exept of catching Exceptions of course). Here is the implementation of these two methods from Parcel:
public final void writeStringArray(String[] val) {
if (val != null) {
int N = val.length;
writeInt(N);
for (int i=0; i<N; i++) {
writeString(val[i]);
}
} else {
writeInt(-1);
}
}
public final void readStringArray(String[] val) {
int N = readInt();
if (N == val.length) {
for (int i=0; i<N; i++) {
val[i] = readString();
}
} else {
throw new RuntimeException("bad array lengths");
}
}
So writeStringArray is fine if I pass bars which are null. It just writes -1 to the Parcel. But How is the method readStringArray supposed to get used? If I pass bars inside (which of course is null) I will get a NullPointerException from val.length. If I create bars before like say bars = new String[???] I don't get any clue how big it should be. If the size doesn't match what was written inside I recieve a RuntimeException.
Why is readStringArray not aware of a result of -1 which gets written on null objects from writeStringArray and just returns?
The only way I see is to save the size of bars before I call writeStringArray(String[]) which makes this method kind of useless. It will also redundatly save the size of the Array twice (one time for me to remember, the second time from writeStringArray).
Does anyone know how these two methods are supposed to be used, as there is NO java-doc for them on top?
You should use Parcel.createStringArray() in your case.
I can't imagine a proper use-case for Parcel.readStringArray(String[] val) but in order to use it you have to know the exact size of array and manually allocate it.
It's not really clear from the (lack of) documentation but readStringArray() is to be used when the object already knows how to create the string array before calling this function; for example when it's statistically instanciated or it's size is known from another previously read value.
What you need here is to call the function createStringArray() instead.

Java bug or feature?

Ok, here is the code and then the discussion follows:
public class FlatArrayList {
private static ArrayList<TestWrapperObject> probModel = new ArrayList<TestWrapperObject>();
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] currentRow = new int[10];
int counter = 0;
while (true) {
for (int i = 0; i < 10; i++) {
currentRow[i] = probModel.size();
}
TestWrapperObject currentWO = new TestWrapperObject(currentRow);
probModel.add(counter, currentWO);
TestWrapperObject testWO = probModel.get(counter);
// System.out.println(testWO);
counter++;
if (probModel.size() == 10) break;
}
// Output the whole ArrayList
for (TestWrapperObject wo:probModel) {
int [] currentTestRow = wo.getCurrentRow();
}
}
}
public class TestWrapperObject {
private int [] currentRow;
public void setCurrentRow(int [] currentRow) {
this.currentRow = currentRow;
}
public int [] getCurrentRow() {
return this.currentRow;
}
public TestWrapperObject(int [] currentRow) {
this.currentRow = currentRow;
}
}
What is the above code supposed to do? What I am trying to do is load an array as a member of some wrapper object (TestWrapperObject in our case). When I get out of the loop,
the probModel ArrayList has the number of elements it is supposed to have but all have the same value of the last element (an array of size 10 with each item equal to 9). This is not the case inside the loop. If you perform the same "experiment" with a primitive int value everything works fine. Am I missing something myself regarding arrays as object members? Or did I just encounter a Java bug? I am using Java 6.
You are only creating one instance of the currentRow array. Move that inside the row loop and it should behave more like you expect.
Specifically, the assignment in setCurrentRow does not create a copy of the object, but only assigns the reference. So each copy of your wrapper object will hold a reference to the same int[] array. Changing the values in that array will make the values appear to change for all other wrapper objects that hold a reference to the same instance of the array.
i don' t want to sound condescending, but always try to remember tip #26 from the excellent pragmatic programmer book
select isn't broken
it is very rare to find a java bug. keeping this in mind often helps me to look over my code again, turn it around, and shake out the loose bits until i finally discover where i was wrong. of course asking for help early enough is very encouraged, too :)

Categories

Resources