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
Related
I have an assignment to create an array class where there are 2 constructors where each constructor sets a different size for the array.
The array is already an instance variable along with another instance variable to keep track of the current position in the array.
I have to create a method called add with an integer parameter that will store the parameter value in the array at the index of the position variable, then add 1 to the position variable. If the incremented position variable is outside the bounds of the array, the method calls the addspace method.
The addspace method creates a new array 25% larger than the instance variable array, copies all the values of the instance array to the new array, and assigns the new array to the instance variable.
I also need a method called size that will return the value in the position variable and a method called get that with 1 parameter(an index), the method returns the value at the parameter index.
The last thing I need is a print method that uses a for loop to print the values in the array.
So far this is what I have
public class ArrayClass
{
private int array[];
private int x=0;
public ArrayClass()
{
this.array= new int[10];
add(1);
getThat(0);
print();
}
public ArrayClass(int y)
{
this.array= new int[y];
add(2);
getThat(0);
print();
}
public void add(int a)
{
array[x]=a;
x++;
if(x>array.length)
addspace();
}
public void addspace()
{
double d=array.length+(array.length*0.25);
int v=(int)d;
int newArray[]= new int[v];
for(int i=0; i<array.length; i++)
{
newArray[i]=array[i];
System.out.println(newArray[i]);
}
}
public int size()
{
return x;
}
public int getThat(int index)
{
return array[index];
}
public void print()
{
for(int i=0; i<array.length; i++)
System.out.println(array[i]+" ");
}
public static void main(String[] args)
{
new ArrayClass();
new ArrayClass(5);
}
}
I know the title only asks for help with the first method but if someone would be kind enough to help with the other methods and the reason why my code won't run and print what I want it to that would be much appreciated.
Use the ArrayClass for only for declaring your functionality.Call add method as obj.add(number) until and unless you need to add something inside ArrayClass constructor itself.
Modified these things as per my understanding
In your add method you are assigning the value first and then adding space if the array is full, in this case, you are increasing the size even if it might not be needed (i.e not calling add method again).
Instead of this increase the size only when you require it.
In print function you are iterating through the whole array.Modified to-> it will iterate till the last index of value (i.e x)
package com.example;
public class ArrayClass
{
private int array[];
private int x=0;
private final int DEFAULT_SIZE=4;
public ArrayClass(){
this.array = new int[DEFAULT_SIZE];
}
public ArrayClass(int size){
this.array = new int[size];
}
public void add(int number){
//check whether array have space or not .if not then increase the space.
if(x > this.array.length-1){
addSpace();
}
array[x] =number;
x++;
}
private void addSpace(){
double newSize = array.length + array.length * 0.25;
int tempArray[] = new int[(int) newSize];
for(int i=0; i<array.length; i++){
tempArray[i]=array[i];
}
this.array = tempArray;
}
public int size()
{
return x;
}
public int getThat(int index)
{
return array[index];
}
public void print()
{
//instead of of printing the whole array Printed till last value index.
for(int i=0; i<x; i++)
System.out.println(array[i]+" ");
}
}
From the main method
ArrayClass ac1 = new ArrayClass();
ac1.add(5);
ac1.add(4);
ac1.add(5);
ac1.add(4);
ac1.add(7);
ac1.add(19);
ac1.print();
ArrayClass ac2 = new ArrayClass(5);
ac2.add(1);
//rest of your function call here
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);
I have a very simple program and I just need to check an array for a value in it.
I have a class called bulkBean. this is it.
public class bulkBean {
private int installmentNo;
private double amount;
public int getInstallmentNo() {
return installmentNo;
}
public void setInstallmentNo(int installmentNo) {
this.installmentNo = installmentNo;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
}
Now I have an array of this bulkBean type in my program, this is my program.
import java.util.Arrays;
public class test {
public static boolean scan_bulkList(bulkBean[] bulkList, int i) {
int[] arr = new int[bulkList.length];
for(int x=0;x<bulkList.length;x++){
arr[x] = bulkList[x].getInstallmentNo();
}
for(int j = 0; j< arr.length ;j++){
System.out.println("INFO: array "+j+" = "+arr[j]);
}
if (Arrays.asList(arr).contains(i) == true) {
return true;
} else {
return false;
}
}
public static void main(String[] arg){
bulkBean bb1 = new bulkBean();
bb1.setInstallmentNo(1);
bb1.setAmount(5500);
bulkBean bb2 = new bulkBean();
bb2.setInstallmentNo(2);
bb2.setAmount(4520);
bulkBean[] bulkArray = new bulkBean[2];
bulkArray[0] = bb1;
bulkArray[1] = bb2;
boolean a = scan_bulkList(bulkArray,1);
System.out.println("val = "+a);
}
}
I create 2 instances of bulk bean and I set values to them. Then I added those two instances to an array. Then I pass that array to the method to check for a value(also given as a parameter. In this case it is 1.). If the array contains that value, it should return true, otherwise false.
whatever value I enter, it return false.
Why do I get this issue?
Arrays.asList() returns a List which has a single element - an array. So, you are actually comparing against an array. You need to compare against each value in the array.
As TheListMind told, Arrays.asList() taken on an int[] gives you a list containing the array.
Personally, I would construct directly the List instead of constructing the array, or even better (no need of array instanciation), test while iterating the bulk array :
for(int x=0;x<bulkList.length;x++){
if (bulkList[x].getInstallmentNo() == i){
return true;
}
}
return false;
The mistake you made here is , you created the int array which must be Integer array because Arrays.asList().contains(Object o); makes the input parameter also Integer(Integer i). int is not an object Integer is the object. Hope it will work.
int[] arr = new int[bulkList.length];
change to:
Integer[] arr = new Integer[bulkList.length];
Change the method as below to avoid complications:
public static boolean scan_bulkList(bulkBean[] bulkList, int i) {
int[] arr = new int[bulkList.length];
for(int x=0;x<bulkList.length;x++){
arr[x] = bulkList[x].getInstallmentNo();
if (bulkList[x].getInstallmentNo()==i) {
return true;
}
}
return false;
}
I have been working on a project and I have been facing an issue with Arraylist in java.
Problem is prim's algorithm
1. Randomly generating graph
2. Making an arraylist of neighbours for every vertex
3. passing the arraylist to the 2 different functions
Problem :- when i make changes in Arraylist in one class it is reflecting is other class as well. How to fix it ? Thanks in advance.Here when i call mst.java g.getneighbourlist() , it works fine. But now when i call in mstFheap.java with same g.getbeighbourlist() its differnt neibourlist i mean all the edges selected by first removed from second .
//main.java
public class main{
GenGraph g = new GenGraph(size, density);
g.makeGraph();
g.print();
// calling for finding mst
mst m= new mst(g.getNeighbourlist(),size);
mstFheap m1= new mstFheap(g.getNeighbourlist(), size);
m.start(); // starts the algo
m.print(); // print mst
m1.print(); // In second class just printing the neibhour list
}
//mst.java
public class mst {
private List<LinkedList<edge>> neighbour =null;
private LinkedList<edge> mst = new LinkedList<edge>();
private int [] traker = null;
private int totalCost =0;
private int size=0;
private boolean path=false;
public mst(List<LinkedList<edge>> list,int x)
{
this.neighbour=new ArrayList<LinkedList<edge>>(list);;
this.size=x;
this.traker= new int[size];
for(int i=0;i<size;i++){traker[i]=0;}
}
public void start() {
List<Integer> subGroup = new ArrayList<Integer>();
Random ran= new Random();
int val= ran.nextInt(size);
subGroup.add(val);
traker[val]=1;
while(!path){
edge e= minCost(subGroup);
totalCost+= e.weight;
subGroup.add(e.v2);
neighbour.get(e.v1).remove(e);
edge temp = new edge(e.v2,e.v1,e.weight);
neighbour.get(e.v2).remove(temp);
traker[e.v1]=1;
traker[e.v2]=1;
mst.add(e);
if(subGroup.size()==size) path=true;
}
}
//mstFheap.java
public class mstFheap {
private fHeap f;
private double totalCost =0;
private double [] keyList= null;
//Graph elements
private int size=0;
private List<LinkedList<edge>> neighbour =null;
public double cost(){return totalCost;}
public mstFheap(List<LinkedList<edge>> list,int size){
f=new fHeap();
neighbour=new ArrayList<LinkedList<edge>>(list);
this.size=size;
keyList=new double[size];
for(int i=0;i<size;i++){
keyList[i]= Double.POSITIVE_INFINITY;
fHeapNode temp= new fHeapNode(i, keyList[i]);
f.insert(temp, keyList[i]);
}
}
public void print(){
System.out.print(" Keylist:- ");
for(int i=0;i<neighbour.size();i++){
System.out.print(neighbour.get(i).size()+" ");
}
}
Try:
mst m= new mst(new ArrayList(g.getNeighbourlist()),size);
mstFheap m1= new mstFheap(new ArrayList(g.getNeighbourlist()), size);
That will make a copy of the list for each algorithm.
SideNote: Please name classes starting with a capital letter. And consider using human readable names. "g" is Graph, so why not call it "graph"?
EDIT: I just saw, that it is a "List of Lists". So you may adjust your getNeighbourlist() Method, so it returns a "deep copy". That means: Instead of a copy of the list, you'll have to return a new list of copies of the entry-lists.
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