Java - How to declare table[i][j] elements as instance variables? - java

All,
I am trying to code a Connect4 game. For this, I have created a P4Game class and a P4Board class which represents the i X j dimensions of the Connect4 board.
In P4Game, I have the following:
public class P4Game{
//INSTANCE VARIABLES
private int nbLines;
private int nbColumns;
private P4Board [][] position;
//CONSTRUCTOR
public P4Game(int nbLines, int nbColumns){
this.nbColumns = nbColumns;
this.nbLines = nbLines;
P4Board [][] position = new P4Board [nbLines][nbColumns]; //Creates the table to receive the instances of the P4Board object.*/
for (int i=0; i<nbLines; i++){
for (int j=0; j<nbColumns; j++){
this.position[i][j] = new P4Board(i,j); //Meant to create each object at (line=i, column=j)
}
}
}
This causes a NullPointerException in the nested loops where I mention this.position[i][j]. I reference those objects in other methods of this class so I need them to be instance variables. I suppose the exception is due to the fact that I have not listed the table element position[i][j] as an instance variable at the beginning of the class.
my question to people here is (1) is my assumption correct, and if so (2) what would be the syntax to declare instance variables of this form?
Thank you all for your help with what I realize is a very basic question. Hopefully it will also benefit other newbies.
Cheers,
JDelage

See added comment inlined... You code is fine except for one little detail, where you're creating a new position variable where you actually mean to use the instance variable.
public class P4Game{
//INSTANCE VARIABLES
private int nbLines;
private int nbColumns;
private P4Board [][] position;
//CONSTRUCTOR
public P4Jeu(int nbLines, int nbColumns){
this.nbColumns = nbColumns;
this.nbLines = nbLines;
// You're creating a LOCAL variable called position here if you don't comment what's commented:.
/*P4Board [][] */position = new P4Board [nbLines][nbColumns]; //Creates the table to receive the instances of the P4Board object.*/
for (int i=0; i<nbLines; i++){
for (int j=0; j<nbColumns; j++){
this.position[i][j] = new P4Board(i,j); //Meant to create each object at (line=i, column=j)
}
}
}
}

Your assumption is incorrect.
In the constructor, you're making a local variable with the same name as the field. (By writing P4Board [][] position = ...) This creates a local variable and does not affect the field, which remains uninitialized. You need to remove the P4Board [][] to change it from a variable declaration to an assignment of the existing field. (Just like you write this.nbLines = ... to assign the field)

You're redefining P4Board [][] position in the constructor and then calling this.position which is not initialized (i.e. null).

Look out carefully! You are hiding the instance variable > P4Board [][] position = new P4Board [nbLines][nbColumns];

As others have said you are hiding the instance variable with a local variable. You should really check out checsktyle as it has checks to tell you if you have made such a mistake. Two other tools are PMD and FindBugs.

Your assumption is incorrect. Try looking a few lines higher for the bug in your homework.

This runs for me. I substituted into for P4Board, since you didn't supply it:
public class P4Game
{
private int nbLines;
private int nbColumns;
private int [][] position;
public static void main(String[] args)
{
P4Game game = new P4Game(3, 3);
System.out.println(game);
}
public P4Game(int nbLines, int nbColumns)
{
this.nbColumns = nbColumns;
this.nbLines = nbLines;
this.position = new int[this.nbLines][this.nbColumns];
for (int i=0; i < this.nbLines; i++)
{
for (int j=0; j < this.nbColumns; j++)
{
this.position[i][j] = i+j;
}
}
}
public String toString()
{
StringBuilder builder = new StringBuilder(1024);
builder.append('[');
for (int i = 0; i < this.nbLines; ++i)
{
builder.append('{');
for (int j = 0; j < this.nbColumns; ++j)
{
builder.append(this.position[i][j]).append(',');
}
builder.append('}');
}
builder.append(']');
return builder.toString();
}
}

Related

JAVA Pass by reference error in method

I was trying to perform sorting of integers in an array and it worked fine.
But when i try to modify the program by including a "pass by reference" concept via a method, it is throwing error "cannot find symbol".
I am new to JAVA and learning by my own, Please help me with what I am doing wrong here.
import java.util.*;
import java.io.*;
public class Sort {
public static void main(String[] args) {
Sort obj = new Sort();
Scanner in = new Scanner(System.in);
int i, p, k, arr[];
arr = new int[10];
System.out.println("Enter the numbers for sorting \n");
for (i = 0; i < 5; i++) {
arr[i] = in.nextInt();
}
for (i = 0; i < 5; i++) {
for (p = 0; p < 5; p++) {
if (arr[i] < arr[p]) {
/*
* moving the below block for swapping to a new method. k =
* arr[i]; arr[i]= arr[p]; arr[p]= k;
*/
obj.swap(obj);
}
}
}
System.out.println("\n");
for (i = 0; i < 5; i++)
System.out.println(arr[i]);
}
public void swap(Sort m) {
m.k = m.arr[i];
m.arr[i] = m.arr[p];
m.arr[p] = m.k;
}
}
The error I am getting is :
"Sort.java:44: error: cannot find symbol
m.k = m.arr[i];
^
"
Similarly 10 such errors for other variables as well.
You are trying to use index variables (i and p) that don't exist in the context you are trying to use them (inside swap() method body) as well as members of Sort (k and arr) which don't exist. The scope of all these, you have limited to the method body of main():-
public void swap(Sort m) {
m.k = m.arr[i]; //No 'i' in swap(). No 'k' or 'arr' in 'm'(an instance of 'Sort')
m.arr[i] = m.arr[p]; //No 'p' in swap()
m.arr[p] = m.k;
}
Short-term Solution
Change your swap() method to
//Now accepting in i and p
public void swap(Sort m, int i, int p) {
m.k = m.arr[i];
m.arr[i] = m.arr[p];
m.arr[p] = m.k;
}
then call it like this
obj.swap(obj, i, p); //pass in i and p
and move your Sort variables to be accessible members of Sort
public class Sort {
public static int k; //now accessible with m.k
public static int[] arr = new int[10]; //now accessible with m.arr
...
}
Lastly, is it intentional that your array is 10 long but you only fill it with 5 numbers?
Pass-by-Reference
There is no "pass-by-reference" in Java. Everything is passed by value. The confusing thing is that what is passed by value is technically a reference to the object, meaning you get strange effects like you can edit the object but not reassign it.
Solution: move the stuff back from the swap method to where it was.
Alternatively, provide the necessary values as parameters to swap.

Java: How to use functions of a class which has been instantiated by ArrayList

Here is just a simple example. Obviously there are simpler ways to set everything up within the constructor, but the arrayList I'm actually working with has already been set up, I just need to change individual sections of it. There HAS to be a way to call a class's functions in ArrayList, but for the life of me I can't figure out how.
import java.util.ArrayList;
public class ArrayTest{
public static void main(String[] args){
//Here's an example of a regular array:
Length[] lArray = new Length[3];
for (int i = 0; i < 3; i++){
lArray[i].setLength(i + 1);
}
//Here's how I was hoping ArrayList would function:
ArrayList<Length> lList = new ArrayList<Length>(3);
for (int i = 0; i < 3; i++){
lList[i].setLength(i + 1);
// --OR--
lList.setLength(i, i + 1);
}
}
}
Here's the length class:
public class Length{
private int length;
Length(){
length = 0;
}
Length(int s){
length = s;
}
public void setLength(int s){
length = s;
}
}
Thanks!
You add elements to the ArrayList with add.
Since it's an ArrayList<Length>, you add Length objects:
lList.add(new Length());
And in your specific loop :
ArrayList<Length> lList = new ArrayList<Length>(3);
for (int i = 0; i < 3; i++){
Length l = new Length();
l.setLength(i+1);
lList.add(l);
}
BTW, the array initialization is also missing an important initialization :
for (int i = 0; i < 3; i++){
lArray[i] = new Length(); // added
lArray[i].setLength(i + 1);
}
If the ArrayList already contains the elements, and you just want to modify them, you can write something like this:
lList.get(i).setLength(i + 1);
assuming that the ArrayList contains the ith element.
You could create a method with your operation/algorithm like
public void foo(){
System.out.println("some algorithm!");
}
inside Length class. This will operate on each instance of Length class.
And for iterating, you can use
ArrayList<Length> lList = new ArrayList<Length>(3);
for (Length l : lList){
l.foo();
}
This will call everything you code inside foo.

doubling Array size if full

I have an array of objects. When the array fills up, I want to make a new array twice as large as the old one, and transfer all the elements over. I'm doing something wrong, I think its something to do with I'm not creating the correct reference to the new array. Here's my code, any help figuring this out would be appreciated.
private int DIRECTORY_SIZE = 6;
Entry [] directory = new Entry[DIRECTORY_SIZE];
private int numberOfElements = 0;
public int getNumOfElements(){
return numberOfElements;
}
public void setDirectorySize(int size){
DIRECTORY_SIZE = size;
}
public int getDirectorySize(){
return DIRECTORY_SIZE;
}
public void addEntry(String surname, String initial, String num) {
// TODO add an entry to an array, also increments numberOfElements variable tracking whats in array
if(getNumOfElements() == getDirectorySize()){ // if array is full
doubleArraySize(); // put temp values into new bigger directory array
}
int i = findFreeLocation();
directory[i] = new Entry(surname, initial, num);
numberOfElements++;
}
private void doubleArraySize(){
Entry[] temp = new Entry[DIRECTORY_SIZE]; //make new temp array same size as old one
for(int i = 0; i < DIRECTORY_SIZE ; i++){
temp[i] = directory[i]; // cycle through array putting all values into temp
// works up to here
}
setDirectorySize(DIRECTORY_SIZE*2); // double size of array
Entry[] directory = new Entry[DIRECTORY_SIZE]; // create new, double size directory array
for(int i = 0; i < temp.length ; i++){
directory[i] = temp[i];
}
}
private int findFreeLocation() {
int i;
for (i = 0; i < DIRECTORY_SIZE; i++)
{
if(directory[i] == null)
{
break;
}
}
return i;
}
In doubleArraySize() function , this is the issue :
Entry[] directory = new Entry[DIRECTORY_SIZE];
// you are not assigning it to the class attribute directory
// instead you are creating a local array directory
Make the following change :
this.directory = new Entry[DIRECTORY_SIZE];
// this will assign the newly created array to the class attribute
Note : I personally prefer to use this pointer to refer to class attributes so that it makes my code more readable, and its clear to everyone that the variable in question is a class attribute rather than local variable.
**SIZE has already double by this point. No need to multiple by 2
I remember doing something exactly like this when I was making a Vector ADT. However, I used instance variables instead of methods in my code for element number and the capacity. I definitely didn't initialize a Vector inside a method for a Vector.
setDirectorySize(DIRECTORY_SIZE*2); // double size of array
Entry[] directory = new Entry[DIRECTORY_SIZE]; // create new, double size directory array
Isn't DIRECTORY_SIZE an instance variable? Because if it is, I don't think you can initialize an object using an instance variable from the object you are overwriting.
Putting my code into your context, it would look something like this:
private void doubleDirectorySize()
{
Entry[] new_array = new Entry[new_directory_size*2];
for (int i = 0; i < directory_size; i++)
{
new_array[i]= directory[i];
}
directory= new_array;
}
This only works if directory was initialized to null, though, moving the pointer directory to the new array.

Having trouble working with a class with an array

When i call my TruthTable class & populate it w/inputs, I can't access individual slots in the array when I'm trying to set the inputs of the AND gates?
threeAndGates.java -the class where the error happens
import java.util.Scanner;
public class threeAndGates {
public static void main(String[] args){
LogicGate and1 = new LogicGate(LogicGate.AND);
LogicGate and2 = new LogicGate(LogicGate.AND);
LogicGate and3 = new LogicGate(LogicGate.AND);
System.out.print("What is the number of Inputs? ");
Scanner scan = new Scanner(System.in);
int numOfInputs = scan.nextInt();
System.out.print("What is the number of Outputs? ");
int numOfOutputs = scan.nextInt();
TruthTable Table1 = new TruthTable(numOfInputs,numOfOutputs);
Table1.PopulateTruthTable();
//below is where it is giving me "the type of the expression must be an array type but it resolves to TruthTable"
for(int r = 0; r<(Math.pow(2, numOfInputs)) ; r++ ){
and1.setInput1(Table1[r][0]);
and1.setInput2(Table1[r][1]);
and2.setInput1(Truth1[r][2]);
and2.setInput2(Truth1[r][3]);
and3.setInput1(and1.getOutput());
and3.setInput2(and2.getOutput());
Table1[r][numOfInputs + numOfOutputs] = and3.getOutput();
}
Table1.printTruthTable();
}
}
TruthTable.java
public class TruthTable {
private int numOfInputs;
private boolean[][] table;
public TruthTable(int inputs, int outputs){
this.numOfInputs = inputs;
int rows = (int) Math.pow(2,inputs);
int columns = inputs + outputs;
table = new boolean[rows][columns];
}
public void printTruthTable(){
for(int r = 0 ; r < table.length ; r++){
for(int c = 0; c < table[r].length; c++)
System.out.printf("%-5b ", table[r][c]);
System.out.println();
}
}
public String toString(){
String outStr = new String();
for(int r = 0; r < table.length; r++){
for(int c = 0; c < table[r].length; c++)
outStr += String.format("%-5b ", table[r][c]);
outStr += '\n';
}
return outStr;
}
public boolean[][] PopulateTruthTable(){
String s;
String r ="";
int[] Line = new int[numOfInputs];
boolean bit;
for ( int i= 0; i < Math.pow(2,numOfInputs) ; i++){
int x = numOfInputs - Integer.toBinaryString(i).length();
for(int j = 0; j<x ; j++)
r += "0";
s = r + Integer.toBinaryString(i);
for(int k=0; k<s.length() ;k++){
Line[k] = s.charAt(k)-48;
}
for(int m=0 ; m<numOfInputs ; m++){
if(Line[m]==1) bit = true;
else bit = false;
table[i][m] = bit;
}
r="";
}
return table;
}
}
Your TruthTable class is not an Array. It contains an Array. You could add a get and set method to your TruthTable class:
public boolean getValueAt(int x, int y) {
return this.table[x][y];
}
public void setValueAt(int x, int y, boolean value) {
this.table[x][y] = value;
}
and use that to work with the TruthTable values.
This is unrelated to your problem, but when naming variables in your classes, the general practice is to use lower case. For example you have:
TruthTable Table1 = new TruthTable(numOfInputs,numOfOutputs);
would be better
TruthTable table1 = new TruthTable(numOfInputs,numOfOutputs);
and probably best as
TruthTable truthTable = new TruthTable(numOfInputs,numOfOutputs);
The better and more consistent you name things the easier it will be to read down the road.
Your TruthTable class isn't a mutil-dimensional array; it has a multi-dimensional array field. Therefor, you can not use the following syntax:
tableInstance[x][y]
If you TruthTable's table field was public, or better yet, it had a getter, you could do womthing like this instead...
tableInstance.getTable()[x][y]
Some languages (like C#) also support operator overloading which would allow you define the behaviour of using the [] index operator (or others like +, /, etc.). This would allow you to make the indexing work. Unfortunately, Java doesn't have this feature.
This is more of a comment than an answer but I needed more space.
If your code causes you problems later, may I make a suggestion? Break down populateTruthTable into 2 or 3 methods, putting each loop in it's own well named method because Each method should do exactly one thing
Also you probably shouldn't be accessing the array directly from the main class, instead put all the code from your main classes "for" loop into a method in the TruthTable class and call that method from main because you should Tell an object what to do rather than asking for it's data.
I'm not trying to say you're doing it wrong or anything, you are obviously doing very well, but it's always good to pick up more coding tricks/practices as you go along and you seem like you are at the level where these would come in handy.

Errors with closing braces/semicolons

I've got two compile errors in one of my classes and I don't understand why they're there.
The top error is saying there needs to be another semi-colon and the bottom one says it needs another closing brace.
The bottom error disappears if i put in another curly brace but the top one doesn't. Any ideas?
(This is probably a case of me being blind/stupid so i apologise in advance :)
package com.pathfinding;
import java.util.ArrayList;
public class EdgeNodeFactory
{
static boolean[][] edgeMatrix = new boolean[100][100];
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 100; j++)
{
edgeMatrix[i][j] = false;
}
}
static ArrayList<Node> nodes = new ArrayList<Node>();
static ArrayList<Edge> edges = new ArrayList<Edge>();
static int edgeCount = 0;
static int nodeCount = -1;
}
You've tried to put code (the for loop) directly in your class - it's not in a constructor, a method, or a static/instance initializer. That's not valid. When do you want that code to be executed?
I suspect your code should really look like this:
public class EdgeNodeFactory
{
private boolean[][] edgeMatrix = new boolean[100][100];
private int edgeCount = 0;
private int nodeCount = -1;
private List<Node> nodes = new ArrayList<Node>();
private List<Node> edges = new ArrayList<Edge>();
public EdgeNodeFactory()
{
// You *could* put your for loop here... but the array
// elements will all be false anyway, as that's the default...
// If you don't need any code in this constructor, and you
// don't declare any other constructors, you can remove it
// entirely - the compiler will create it by default.
}
// Other methods here
}
Note how I've made all the fields private and non-static... you should almost certainly be creating an instance of EdgeNodeFactory rather than using static fields, and you should almost always make fields private.
Has been a while since I did any Java, but I believe that for loop should be inside a method or function of some description, rather than the class declaration.
I would imagine you mean that to be in a constructor.
I think what the for loops are meant to do is initialization of static array field. In this case you should put the code in a static initializer like this:
package com.pathfinding;
import java.util.ArrayList;
public class EdgeNodeFactory
{
static boolean[][] edgeMatrix = new boolean[100][100];
static {
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 100; j++)
{
edgeMatrix[i][j] = false;
}
}
}
static ArrayList<Node> nodes = new ArrayList<Node>();
static ArrayList<Edge> edges = new ArrayList<Edge>();
static int edgeCount = 0;
static int nodeCount = -1;
}
The code inside static { ... } at the class level is executed the first time the class is loaded (only once). This means it will be executed before any instances of the class are created and before any other code can access the class.
It remains debatable whether the fields should be static, but if you're sure they should, this is how you should initialize them.

Categories