I'm trying to create a 2 dimensional array of "Node" objects as follows
public static void main(String[] args) throws IOException {
length=getNumber("Enter the length of the field: ");
breadth=getNumber("Enter the breadth of the filed: ");
node n = new node();
node [][] field = new node[length][breadth];
for(i=0;i<=length;i++){
for(j=0;j<=breadth;j++){
F =getNumber("Enter the F value");
field[i][j].setF(F);
System.out.println(" "+field[i][j].getF(F);
}
}
}
in above code getNumber is a function wherein i print and accept the number
Here is my node class:
public class node {
public int F;
public int G;
public int H;
public boolean isVisited;
public boolean isCurrent;
public void node(int F,int G,int H,boolean isVisited, boolean isCurrent){
this.F=F;
this.G=G;
this.H=H;
this.isVisited=isVisited;
this.isCurrent=isCurrent;
}
public int getF() {
return G+H;
}
public void setF(int f) {
F = f;
}
public int getG() {
return G;
}
public void setG(int g) {
G = g;
}
public int getH() {
return H;
}
public void setH(int h) {
H = h;
}
public boolean isVisited() {
return isVisited;
}
public void setVisited(boolean isVisited) {
this.isVisited = isVisited;
}
public boolean isCurrent() {
return isCurrent;
}
public void setCurrent(boolean isCurrent) {
this.isCurrent = isCurrent;
}
}
all i want to do is, to store/access various values of F,G,H etc in each of the node objects, the problem however is i'm getting java.lang.NullPointerException for field[i][j].setF(F);
i dont know where i'm going wrong, need some help.
You initialized the array, but you did not populate it.
Consider this line:
field[i][j].setF(F);
When you do
field[i][j]
you are accessing the array; i.e. getting what is in the array at that position. Since you didn't put anything in the array, you get a null. But you immediately try to call setF.
I noticed you do
node n = new node();
outside the loop. You probably want to do that in the loop.
node n = new node();
n.setF(F);
field[i][j] = n;
This code creates a node instance, sets a value on it, and then puts it in the array at the specified position. A bit more fancy approach would be to do something like
node n = field[i][j];
if (n == null) { // initialize n at the position if it doesn't exist
n = new node();
field[i][j] = n;
}
field[i][j].setF(f);
Alternatively, you could loop over the array and put a new node at each position, right after you initialize the array.
Finally, in Java standard practice is to start class names with capital letters. node should be Node.
Try this:
for(i=0;i<=length;i++){
for(j=0;j<=breadth;j++){
F =getNumber("Enter the F value");
node tmp = new node();
tmp.setF(F);
field[i][j] = tmp;
System.out.println(" "+field[i][j].getF(F);
}
}
PS in java it is convention for class names to start with a capital and should be written in CamelCase
[edit]
Be careful with your get/setF() functions as they do not operate on the same variables
not related to your question, but you might want to read through this document this will teach you about naming conventions in java and help you write code that is easier to read
Related
I'm trying to test out my program to see how it works, but I'm not sure how to call upon it in the main method. I've tried doing Assignment5Solution.findOrder() but it does not work. Any help with this issue would be greatly appreciated. The code is supposed to take the number of classes a student has to take along with the prerequisites for each course if there are any, and put the correct order of what classes the student should take.
package Assignment5;
import java.lang.reflect.Array;
import java.util.*;
/**
*
* #author harpe
*/
class Assignment5Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
int E = prerequisites.length;
Graph G = new Graph(numCourses);
for (int i = 0; i < E; i++) {
G.addEdge(prerequisites[i][1], prerequisites[i][0]);
} // Graph is constructed
DFS d = new DFS(G); // depth first search
return d.reverseDFSorder();
}
public class DFS {
private boolean[] marked;
private int[] courseOrder; // i.e., reverse post order
private boolean hasCycle;
private int index; // index for the array courseOrder, index 0 is for the course taken first, …
private HashSet<Integer> callStack; // used to detect if there are cycles on the graph
DFS(Graph G) {
marked = new boolean[G.V()];
courseOrder = new int[G.V()];
index = courseOrder.length - 1; // index 0 of courseOrder will be course taken first, lastIndex will be taken last
callStack = new HashSet<Integer>(); // HashSet is a hash table, for O(1) search
for (int v = 0; v < G.V(); v++) { // to visit each node, including those on islands or isolated
if (!marked[v] && !hasCycle) {
dfs(G, v);
}
}
}
private void dfs(Graph G, int v) {
marked[v] = true;
callStack.add(v); // use HashSet to simulate callStack
for (int w : G.adj(v)) {
if (!marked[w]) {
dfs(G, w);
} else if (callStack.contains(w)) // search in HashSet is O(1)
{
hasCycle = true; // this is a cycle!
break;
}
}
callStack.remove(v);
courseOrder[index--] = v; // index starts from array length -1, decrease by 1 each time, and then ends at 0
}
public int[] reverseDFSorder() {
if (hasCycle) {
return new int[0]; // return an empty int array (with size 0)
}
return courseOrder;
}
} // end of class DFS
public class Graph {
private int V;
private List[] adj;
Graph(int V) // constructor
{
this.V = V;
adj = new List[V];
for (int i = 0; i < V; i++) {
adj[i] = new ArrayList<Integer>();
}
}
public void addEdge(int v, int w) {
adj[v].add(w);
}
public Iterable<Integer> adj(int v) {
return adj[v];
}
public int V() {
return V;
}
} // end of class Graph
} // end of class Solution
public int[] findOrder(int numCourses, int[][] prerequisites) {}
would need to be:
public static int[] findOrder(int numCourses, int[][] prerequisites) {}
The static keyword means you do not need to a declare an object of the class to use it. So you can use it using:
Assignment5Solution.findOrder(numCourses, prerequisites)
//numCourses and prerequisites can be any int and int[][] respectively.
EDIT: Another note too, depending on where your main method is you may need to make class Assignment5Solution a public class with:
public class Assignment5Solution {
It currently is package protected so it will only be able to be used if it is in the same package.
EDIT2:
If you want to use it as a nonstatic method you need to do something like this(change null and 0 to the real values):
Assignment5Solution test = new Assignment5Solution() {};
int numCourses = 0;
int [][] prereqs = null;
int[] reverseOrder = test.findOrder(numCourses, prereqs);
public class Solution {
public static void main(String[] args) throws Exception { //have this return the result of DFS
Scanner input = new Scanner(System.in);
int vertices = input.nextInt();
Graph mygraph = new Graph (vertices);
int edges = input.nextInt();
//set up input as edges
while (input.hasNextInt()) {
int from = input.nextInt() - 1;
int to = input.nextInt() - 1;
//add the reciprocating vertex neighbors
mygraph.nodes[from].addNeighbor(mygraph.nodes[to]);//null pointer here
mygraph.nodes[to].addNeighbor(mygraph.nodes[from]);
}
}
}
class Graph {
int size;
Vertex[] nodes;
Graph(int size) {
this.size = size;
this.nodes = new Vertex[size];
}
}
class Vertex {
int value;
Vertex[] neighbors;
int available;
Vertex(int value) {
this.value = value;
this.neighbors = new Vertex[50];
this.available = 0;
}
//add to the neighbors list of this array
void addNeighbor(Vertex v) {
this.neighbors[this.available] = v;
this.available = this.available + 1;
}
}
not sure as to why I'm getting a null pointer here? To my understanding, null pointers are when something is not getting initialized properly--any guidance?
What I'm trying to do is add the neighbors of vertices to one another as they come up in the input. One possible issue is that in the Vertex class I'm initializing the size of the Vertex array as size, but I don't see any other way to accurately get the size of the array.
I haven't seen any other problem online like this one, hence why Im asking!
I am trying to to create a stacks which has the following API:
Stacks(int n)// creates stacks of size n
pop() //returns the last element pushed in the stacks
pop(int n) //returns an array of of n elements
push(int e) //appends an element to the stacks
push(int n, ar[]) //appends an array to the stack
The stacks should be able to dynamically change size when needed, so client programs dont have to do it every time.
I have done all that only my problem is when assigning object A to object B doesn't that mean that A will now points to the address of B?
Here is my code and i hope it explaines what i mean
public class Stacks {
/*
* constructs a stack object
* #param n that will determine that size of the stacks to be constructed
*/
public Stacks(int n)
{
this.elemetns= new int[n];
this.size=n;
this.top=-1;
}
/*
* constructs a stack object, with size of 2 when no parameter is given
*/
public Stacks()
{
this.elemetns= new int[2];
this.size=2;
this.top=-1;
}
public int pop()
{
if (top<0)
{
System.out.println("Error code 2: Empty stacks");
return -1;
}
else
{
int n= this.elemetns[top];
top--;
return n;
}
}
public int [] pop(int size)
{
if (this.size<size)
{
System.out.println("Error code 3: The Maximum number of elements that can be acquired is "+ this.size);
return null;
}
else
{
int res[]= new int[size];
for (int i=0;i<size;i++)
{
res[i]=pop();
}
return res;
}
}
public void push(int e)
{
if (!isFull())
{
this.elemetns[++top]=e;
System.out.println(e+" has been pushed to the stack ");
}
else
{
updateStacksSize(this);
this.elemetns[++top]=e;
System.out.println(e+" has been pushed to the stack ");
}
}
public void push(int n,int [] ar)
{
for (int i=0;i<n;i++)
this.push(ar[i]);
}
private void updateStacksSize(Stacks s)
{
int newSize= s.top*2;
Stacks newStacks= new Stacks(newSize);
for (int i = s.top; i>-1;i--)
newStacks.elemetns[i]=s.pop();
s= newStacks;//shouldnt newStacks get garbage collected
//and s gets the new address and attributes of newStacks?
}
private boolean isFull(){return this.size==(this.top+1);}
public static void main(String[] args)
{
Stacks s= new Stacks(5);
for (int i=0;i<7;i++)
s.push(i+1);
System.out.println();
int []arr= s.pop(6);
for (int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
private int elemetns[];
private int top;
private int size;
}
Why does running this program results in problem with the old size although the current object's has been updated.
one more question is it possible to assign this= newStacks instead of instantiating new Stacks object
In Java you assign object references to variables.
I have done all that only my problem is when assigning object A to object B doesn't that mean that A will now points to the address of B?
s= newStacks;//shouldnt newStacks get garbage collected
//and s gets the new address and attributes of newStacks?
It is the other way around since the assignment in Java is from right to left.
"I have done all that only my problem is when assigning object A to object B doesn't that mean that A will now points to the address of B?"
if this is what you meant then:
Stacks A = new Stacks();
Stacks B = A;
Then what this means is that B is now pointing to A.
You're kinda over do it. A stack should consist of a chain of nodes, like an singel-linked list of nodes. I've written an example on this below, see if you can see how it works.
public class Stack <E> {
private StackItem<E> currTop;
private int size;
private int max;
private static class StackItem<E> {
private E e;
private StackItem<E> next;
}
public Stack(int max) {
currTop = null;
size = 0;
this.max = max;
}
public void add(E e){
if ((size+1) == max) throw new StackOverflowError("Max items in stack is reached");
StackItem<E> old = currTop;
currTop = new StackItem<>();
currTop.e = e;
currTop.next = old;
size++;
}
public E getFirst() {
if (currTop == null) return null;
E output = currTop.e;
currTop = currTop.next;
size --;
return output;
}
public E showFirst() {
return currTop.e;
}
public int getSize() {
return size;
}
}
I am having problems on how to instantiate bi-dimensional array of objects. I tried to demonstrate below a small sample to reproduce the error I am getting.
I have this class named Node that basically stores one character. This class is used inside the class named Test as a bi-dimensional attribute. I used some user input to establish the size of the array and instantiate it inside the instantiate() method. Then, I try to populate the map using a set method. However, the compiler gives me the following error message:
Eclipse Console Output:
Exception in thread "main" java.lang.NullPointerException
at Test.populate(Main.java:44)
at Main.main(Main.java:77)
My input was:
Enter height:
3
Enter width:
3
Below is the code I am using to reproduce this error:
Class Node:
class Node {
private char content;
Node(){
this.content = ' ';
}
Node(Node node){
this.content = node.getContent();
}
//Setter
public void setContent(char c) {
this.content = c;
}
//Getter
public char getContent() {
return this.content;
}
}
Class Test:
class Test {
private Node[][] map;
private int height, width;
public void instantiate(){
Scanner reader = new Scanner(System.in);
System.out.println("Enter height: ");
this.height = reader.nextInt();
System.out.println("Enter width: ");
this.width = reader.nextInt();
map = new Node[height][width];
reader.close();
}
public void populate(){
for(int i=0;i<height;i++)
for(int j=0;j<width;j++){
if((i+j) %2 == 0)
map[i][j].setContent('a');
else
map[i][j].setContent('b');
}
/*
* a b a b
* b a b a ...
* a b a b
* b a b a
* . . .
*/
}
public void print(){
for(int i=0;i<height;i++){
for(int j=0;j<width;j++){
System.out.print(map[i][j].getContent());
}
System.out.println();
}
}
public Node[][] getMap(){
return this.map;
}
}
Main method:
public class Main {
public static void main(String[] args) {
Test testing = new Test();
testing.instantiate();
testing.populate();
testing.print();
}
}
The code can also be seen here: http://pastebin.com/agFMmB38
I am still getting used to Java (coming from C++), so they have some differences that I couldn't figure it out yet.
Any help would be greatly appreciated.
Thank you!
map[i][j] needs to be set to a new object, like map[i][j] = new Node('a') (well, if you had a constructor in Node which worked like that: it would be written Node(char a) { this.content = a; }).
You cannot do map[i][j].setContent('a') because it is not a preexisting Node object.
You need to init an Node object before use setContent(char c) method.
public void populate() {
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++) {
map[i][j] = new Node();
if((i+j) %2 == 0)
map[i][j].setContent('a');
else
map[i][j].setContent('b');
}
}
}
Then use method getContent() to retrieve value what you want.
public void print() {
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++) {
System.out.print(map[i][j].getContent());
}
System.out.println();
}
}
Im trying to code an algorithm that can learn by his experiences (in the game connect four). For that I wanted to save all the single steps in a List. But if I am adding Elements to my List, Every Element in the List gets overridden by the Element i am adding. I have no clue why this is like this and even after 1Hour searching I dont know why, because there is no static field in my Runde.java. The code is here: (Im German so dont be suprised by that weird names for the variables)
package me;
public class Runde{
private int[][] spielfeld;
private int[][] x= new int[7][5];
private int lastx;
private int lasty;
public Runde(int[][] spielfeld1, int xi, int jetzgzuege, int y){
spielfeld=spielfeld1;
lastx=xi;
x[xi][4]=jetzgzuege;
lasty=y;
}
public boolean equal(int[][] spielfeld){
if(spielfeld.equals(spielfeld)){
return true;
}else{
return false;
}
}
public void finishround(boolean sieg, int geszuege){
x[lastx][0]+=1;
if(sieg){
x[lastx][1]+=1;
x[lastx][2]+=geszuege;
}else{
x[lastx][3]+=geszuege;
}
}
public int[][] getSpielfeld(){
return spielfeld;
}
public int[][] getData(){
return x;
}
public int getlastx(){
return lastx;
}
public int getlasty(){
return lasty;
}
}
static ArrayList<Runde> liste= new ArrayList<Runde>();
static ArrayList<Runde> Steps= new ArrayList<Runde>();
static void erzeugeGen(){
int[][] spielfeld=leeresSperzeugen();
int x=0;
int y=0;
int zug=0;
int rand = new Random().nextInt(2);
boolean player;
if(rand==1){
player = true;
}else{
player=false;
}
while(!winner(spielfeld,x,y) && zug<42){
zug++;
player=!player;
Runde r;
if(player){
r= Computerzug(spielfeld.clone(),1,zug); // If i have a look in to the spielfeld in this element, its fine
Steps.add(r); // But after adding like this, its overridden :(
}else{
r= Computerzug(spielfeld.clone(),2,zug);
}
x=r.getlastx();
y=r.getlasty();
if(player){
spielfeld[y][x]=1;
}else{
spielfeld[y][x]=2;
}
}
if(zug<42){
GenAuswerten(zug,player);
zuege+=zug;
}else{
gen--;
}
}
static void GenAuswerten(int zug, boolean win){
for(Runde r: Steps){
r.finishround(win, zug);
ArrayList<Runde> removal = new ArrayList<Runde>();
for(Runde r2 : liste){
if(r2.equal(r.getSpielfeld())){
removal.add(r2);
}
}
for(Runde r3: removal){
liste.remove(r3);
}
}
for(Runde r: Steps){
liste.add(0,r);
}
Steps.clear();
}
you will need to clone the 2nd level arrays when you clone this
r= Computerzug(spielfeld.clone(),1,zug);
so the correct code is
int spielfeldclone[][] = new int[spielfeld.length][];
int i = 0;
for(int[] spielfeldArray: spielfeld){
spielfeldclone[i] =spielfeldArray.clone()lone();
i++;
}
r= Computerzug(spielfeldclone,1,zug);
the reason is that you are doing shallow copy of 2d array
and remeber 2d array is an array of array
normaly clone() of any array would work if the array was of primitive type like int
but here the array you are cloning contain arrays
that mean you will get new references to the same 2nd level array object
So
spielfeld[0] == spielfeld.clone()[0]
is true
since both spielfeld[0] and spielfeld.clone()[0] point to same object
now to resolve that we needed to do shallow copy of the inner arrays each one alone which resulted in deep copy