我的功能似乎是编辑多个对象

时间:2015-02-18 04:13:15

标签: java android object

在我的Sudoku Android应用程序中,我有一个求解Sudoku难题的解决函数(一个CellField对象)。但是出于某种原因,当我克隆一个CellField对象并且我在克隆对象上调用solve方法时,solve方法解决了两个CellField对象,但我只希望它解决克隆的CellField对象而不是原始对象。有什么建议?感谢

这里我克隆了CellField对象(克隆名为temp),并且还调用了solve方法

CellField temp = null;
try {
   temp = board.cf.clone();
} catch (CloneNotSupportedException e) {
   e.printStackTrace();
}
   int x = randInt(0,8);
   int y = randInt(0,8);
while (!temp.getCell(y,x).isEditable && board.cf.getCell(y,x).getValue() == 0) {
   x = randInt(0,8);
   y = randInt(0,8);
}
SudokuSolver solver = new SudokuSolver();
solver.solve(temp);

这是我的求解方法和SudokuSolver类

package com.example.czhou.myapplication2;

import java.util.*;

public class SudokuSolver {

    static boolean retry;

    public static int randInt(ArrayList<Integer> candidates) {
        int min = 0;
        int max = candidates.size() - 1;

        //inclusive
        Random rand = new Random();


        int randomNum = rand.nextInt((max - min) + 1) + min;
        int result = candidates.get(randomNum);
        candidates.remove(randomNum);

        return result;

    }

    public boolean solve(CellField field) {
        // write your code here



        boolean isValid = true;

        Set<Integer> toRemove = new HashSet<>();
        int i;
        int j;
        for (int k = 0; k < 9; k++) {
            for (int l = 0; l < 9; l++) {
                field.getCell(k, l).restAlt();
                if (field.getCell(k, l).alt.indexOf(field.getCell(k, l).getValue()) != -1) {
                    field.getCell(k, l).alt.remove(field.getCell(k, l).alt.indexOf(field.getCell(k, l).getValue()));
                }
            }
        }

        for (i = 0; i < 9; i++) {
            for (j = 0; j < 9; j++) {

                if (field.getCell(i,j).getValue() == 0 && field.getCell(i,j).alt.size() == 0){
                    field.getCell(i,j).restAlt();
                }
                if (field.getCell(i, j).isEditable) {
                    toRemove.clear();
                    for (int k = 0; k < 9; k++) {
                        toRemove.add(field.getCell(k, j).getValue());
                    }
                    toRemove.addAll(field.getSectorCandidates(i, j));
                    for (int k = 0; k < 9; k++) {
                        toRemove.add(field.getCell(i, k).getValue());
                    }

                    toRemove.removeAll(Collections.singleton(0));


                    field.getCell(i, j).alt.removeAll(toRemove);
                    if (toRemove.size() == 9 || field.getCell(i, j).alt.size() == 0) {
                        //When there no candidates are available
                        //in the current cell, come here

                        //toRemove.clear();
                        Cell cell;
                        boolean stop = false;
                        backtrack:

                        for (int k = j; !stop; k--) {
                            if (k == -1) {
                                if (i != 0) {
                                    --i;
                                } else {
                                    break;
                                }
                                k = 8;
                            }
                            j = k;
                            // Scan for previous cells have alternative candidates

                            cell = field.getCell(i, k);
                            if (cell.alt.size() > 0 && cell.isEditable) {
                                //bookmark the original cell
                                //int nextCell = k+1;

                                // If found a cell set value as first alternative
                                cell.setValue(cell.alt.get(0));

                                break backtrack;


                            } else if (cell.isEditable){
                                // if no alternatives set cell to 0 and continue backwards
                                cell.setValue(0);
                            }
                        }

                    } else {
                        field.getCell(i, j).setValue(randInt(field.getCell(i, j).alt));
                    }


                }
            }
        }

//        for (int m = 0; m < 9; m++) {
//            for (int l = 0; l < 9; l++) {
//                if (l == 0) {
//                    System.out.println();
//                }
//                System.out.print(field.getCell(m, l).getValue());
//            }
//        }
//        System.out.println();
//        System.out.println("================");


        return isValid;
    }
}

这是我的CellField类

package com.example.czhou.myapplication2;

import android.util.Log;

import java.io.Serializable;
import java.util.*;
import java.util.regex.Matcher;

public class CellField implements Cloneable{
    protected Cell[][] field = new Cell[9][9];
    public CharSequence timeElapsed = "00:00";


    public CellField() {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                field[i][j] = new Cell();
            }
        }
    }

    public CellField(CellField another) {
        List<Cell[]> cellfield = Arrays.asList(another.field);
        this.field = (Cell[][]) cellfield.toArray();
    }

    public CellField clone() throws CloneNotSupportedException {
        return (CellField)super.clone();
    }



}

2 个答案:

答案 0 :(得分:0)

问题在于克隆方法,正如@ρяσѕρєя所说,你应该做一个深层复制。因为现在你返回相同的参考。尝试这样的事情:

public CellField clone() throws CloneNotSupportedException {
    CellField clone = new CellField();
    clone.field = this.field;
    clone.timeElapsed = this.timeElapsed;

    return clone;
}

答案 1 :(得分:0)

这是浅拷贝与深拷贝的问题。

class SomeClass implements Cloneable {

    // This is the problematic field. It doesn't get cloned the way you think it is.
    public Integer[] field = new Integer[5];

    public SomeClass clone() throws CloneNotSupportedException {
        return (SomeClass) super.clone();
    }

}

public class HelloWorld {

     public static void main(String []args){

        SomeClass first = new SomeClass();

        SomeClass second = null;
        try {
           second = first.clone();
        } catch (CloneNotSupportedException e) {
           e.printStackTrace();
        }

        System.out.println(first.field);
        System.out.println(second.field);
        // Their addresses in memory are the same
        // Modifying one would modify the other
        // first.field == second.field -> true
     }
}

在上面的例子中,我将该类的一个实例克隆到另一个实例中,然而,它们共享相同的字段。变量类的第一个实例的字段将直接影响该类的第二个实例中的字段,因为它们都拥有对它的引用。

您可以定义复制构造函数并自行执行克隆,而不是使用Cloneable。

可在How to properly override clone method?

上找到更多高级详情