0

I try to create a Nim game with max min method. Then this is the code i create to build tree. Why this list can only store the last element? Please help

list.add(array);

This is my class

class Node {
    public static int jml = 0;
    public List<int[]> list; //only one list is needed (to insure)
    Node n; //not needed also (can be removed)
    public void mulai(int[] arg, String tipe){
        int sisa, index = 0, o = 0;
        boolean cek=false;        
        int array[] = new int[arg.length+1];
        list=new ArrayList<int[]>();
        n=new Node();
        int[] arrayCloned = null;
        for(int nilai : arg)
        { //Looping untuk tiap nilai pada array
            for(int i = 1; i<nilai/2+1;i++)
            { //Looping untuk pengurangan
                sisa = nilai - i;
                if(sisa!=i){
                    for(int n = 0; n<array.length ;n++)
                    { //Looping untuk membuat turunan
                        try{
                        if(n == index){
                            array[n]=sisa;
                            array[n+1]=i;
                            n++;
                            cek=true;
                        }else{
                            if(cek)
                                array[n]=arg[n-1];
                            else
                                array[n]=arg[n];
                        }
                        }catch(ArrayIndexOutOfBoundsException e){
                        }
                    } //Akhir looping turunan
                    System.out.printf("i = %d\n",i);
                    System.out.println("Befor add");
                    printListOfArray();
                    list.add(array); /*This  code can only store the last element*/
                    System.out.println("After add");
                    printListOfArray();
                    System.out.println("======================");
                    if(tipe.equals("min"))
                        n.mulai(array, "max"); 
                    else
                        n.mulai(array, "min");               
                }

            } //Akrir looping pengurangan
            index++;
        } //Akhir looping nilai array
    }

    void printListOfArray(){
        for(int[] ins:list){
            System.out.print("Elements: ");
            for(int i:ins)
                System.out.print(" "+i);
            System.out.println();
        } 
    }
    public void print(){
        for(int[] nilai : n.list){
                System.out.println(Arrays.toString(nilai));
            }
    }
}

I have trouble here

list.add(array);

Please Help. I dont know whats wrong with my code This is output i have

i = 1 Befor add After add Elements: 4 1


i = 1 Befor add After add Elements: 3 1 1


i = 1 Befor add After add Elements: 2 1 1 1


i = 2 Befor add Elements: 3 2

After add Elements: 3 2 Elements: 3 2


i = 1 Befor add After add Elements: 2 1 2


I dont know why this is keep change. i = 1 there save 4 1, when i = 2 it change to 3 2

  • 4
    Empty catch block is a bad idea. – khelwood Apr 13 '19 at 05:54
  • See at your method, you are creating object many times... – Jaja Apr 13 '19 at 07:51
  • @Michael, I think that space, tab, comment ... sometimes is everyone's style: There is no worst or best!!!!!!!!! – Jaja Apr 13 '19 at 08:09
  • @khelwood ya i know, but i no idea whats going on. Its keep catch nullpointer – Agung Wicaksono Apr 13 '19 at 09:49
  • Possible duplicate of [Is Java "pass-by-reference" or "pass-by-value"?](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value) – Progman Apr 13 '19 at 22:30
  • There is a better dup for this question that explains the two common reasons for this kind of problem: adding the same object multiple times, or object fields declared as statics. But I cannot find it :-( – Stephen C Apr 14 '19 at 03:22
  • @khelwood: Apologies, braino - that was meant to be addressed to the OP. Will delete and recomment without aiming it at you... – Jon Skeet Apr 14 '19 at 08:22
  • When a NullPointerException is being thrown, you should almost never catch it - instead, work out why you're getting it and fix the cause. See stackoverflow.com/questions/218384 – Jon Skeet Apr 14 '19 at 08:23
  • Yes, i know what wrong with this code now. Thank you – Agung Wicaksono Apr 14 '19 at 11:26

2 Answers2

0

Fixed your issue: In the recursion you were creating new list and new class Node (instance), which caused that you result is the last one because others were no more there. See also comment in code and some doc. e.g. use of this. (I added a method to print answers also ....).

class Node {
    public static int jml = 0;
    List<int[]> list=new ArrayList<int[]>(); //only one list is needed (to insure)
    int array[]=null;
    Node n; //not needed also (can be removed)
    public void mulai(int[] arg, String tipe){
        int sisa, index = 0, o = 0;
        boolean cek=false;        
        array = new int[arg.length+1];
        //        list=new ArrayList<int[]>();
        //        n=new Node();
        for(int nilai : arg)
        { //Looping untuk tiap nilai pada array
            for(int i = 1; i<nilai/2+1;i++)
            { //Looping untuk pengurangan
                sisa = nilai - i;
                if(sisa!=i){
                    for(int n = 0; n<array.length ;n++)
                    { //Looping untuk membuat turunan
                        try{
                        if(n == index){
                            array[n]=sisa;
                            array[n+1]=i;
                            n++;
                            cek=true;
                        }else{
                            if(cek)
                                array[n]=arg[n-1];
                            else
                                array[n]=arg[n];
                        }
                        }catch(ArrayIndexOutOfBoundsException e){
                        }
                    } //Akhir looping turunan

                    //System.out.println("Befor add");
                    //printListOfArray();
                    list.add(array); /*This  code can only store the last element*/
                    //System.out.println("After add");
                    //printListOfArray();
                    //System.out.println("======================");
                    if(tipe.equals("min"))
                        this.mulai(array, "max"); //and not n.mulai(...) 
                    else
                        this.mulai(array, "min");  //and not n.mulai(...)                
                }

            } //Akrir looping pengurangan
            index++;
        } //Akhir looping nilai array
    }

    void printListOfArray(){
        for(int[] ins:list){
            System.out.print("Elements: ");
            for(int i:ins)
                System.out.print(" "+i);
            System.out.println();
        } 
    }
    printListOfArray();
}
Jaja
  • 662
  • 7
  • 15
  • in that case, i need to take one level child only. I have test your code, i test with input 5. Then i must store the first child, there are [4,1] and [3,2] but it cant. Using this make that store all child right? – Agung Wicaksono Apr 13 '19 at 09:48
  • Give an example of input and what you expect, please... (I do not get your question) – Jaja Apr 13 '19 at 12:52
  • Input 5 . List = {[4,1], [3,2]}. Input 7, List = {[6,1], [5,2], [4,3]}. Input 9, List = {[8,1], [7,2], [6,3], [5,4]} – Agung Wicaksono Apr 13 '19 at 18:10
  • Not sure whether recursion applied here is a good solution in this case. By the way this is not the question you asked (your problem is fixed). – Jaja Apr 13 '19 at 20:08
  • But in your code there, still overwrite the first value. It can print 4,1 but not saved in list – Agung Wicaksono Apr 13 '19 at 23:56
  • This is not the correct diagnosis for the problem - why all the arrays in the list are the same. – Stephen C Apr 14 '19 at 03:25
  • I fixed it by taking array[] outside of class(but this was other problem also) – Jaja Apr 14 '19 at 05:55
0

Let me reduce you code to the essentials that are relevant to your problem:

class Node {
    public List<int[]> list; 

    public void mulai(int[] arg, String tipe){
        int array[] = new int[arg.length + 1];
        list = new ArrayList<int[]>();
        for(...) {
            for(...) {
                if(...){
                    for(...) { 
                       // assign stuff to elements of 'array'
                    }
                    list.add(array);             
                }
            } 
        }
    }
}

The problem is that there is one and only one int[] object in this code. You create the object with this line:

   int array[] = new int[arg.length + 1];

and then you reuse the object over and over again.

So when you do this:

   list.add(array);

you are actually adding the same array (reference!) to the list, over and over again.

And in the code where you "assign stuff to the elements of 'array'" (see comments in code above), you are actually just changing the array that you have already added to the list.

Solution: you need to use new (or equivalent) to create a new array and assign it so array before the innermost loop. Or ... simply move the declaration and initialization of array to before the innermost loop.

(You seemed to have an inkling that you need to do this:

   int[] arrayCloned = null;

but you didn't actually use this declaration. And looking at the code, I don't think that copying or cloning the array is the best approach ...)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216