如我先前的问题here中所述,我正在尝试编写游戏AI。当前,我有一个循环遍历单元的邻居,生成可能的动作列表。在此循环的某个点(高度递归),我声明了一个新的DotMove对象,该对象存储该特定移动的信息。然后,此举将添加到不断增长的举动列表中。

每个动作都有一个点的有序列表,这些点被认为是“路径”。

不幸的是,这些DotMove对象似乎没有正确保存对路径的引用。具体来说,当我打印所生成的DotMove对象的路径时,这些路径仅返回一项。 (路径应为几项,并且随着列表的打印而变化。)

List<Edge> e = getEdgesAt(p, con);
ArrayList<DotMove> moveList = new ArrayList<DotMove>();

for (Edge edge : e) {
    if (visited.add(edge)) {
        Point next = edge.getNextPoint(p);
        path.add(next);
        findMovesAtPointHelper(next, path, connected, visited);
        moveList.add(new DotMove(path, this));
    }
}
path.remove(path.size() - 1);
return moveList;


产生以下输出:

r r b g r g r g
r r b g y r r b
b r b g b r r p
b r b b g r r r
b r b r r r b r
r b b p r p b b
p r y y g g b b
p y r b y p b r

[(0, 0)]
[(0, 1)]
[(1, 0)]
[(1, 1)]
[(1, 2)]
[(1, 2)]
[(1, 2)]


但是,当我用当时打印路径的语句替换moveList.add(...)时,得到以下(正确)输出:

r r b g r g r g
r r b g y r r b
b r b g b r r p
b r b b g r r r
b r b r r r b r
r b b p r p b b
p r y y g g b b
p y r b y p b r

[(0, 0), (0, 1), (1, 1), (1, 0)]
[(0, 0), (0, 1), (1, 1)]
[(0, 0), (0, 1), (1, 1), (1, 2), (1, 3)]
[(0, 0), (0, 1), (1, 1), (1, 2)]
[(0, 0), (0, 1), (1, 1)]
[(0, 0), (0, 1)]
[(0, 0)]


我相信这种差异是由我的DotMove构造函数及其调用的Path构造函数引起的。这两个已包含在此处以供参考。

public DotMove(ArrayList<Point> path, BoardModel boardModel) {
    this.path = new Path(path);
    this.cleared = path;
    this.score = path.size();
}

public Path(List<Point> path){
    this.path = new ArrayList<Point>(path);
}


看来Path()构造函数正在保留对整个列表的引用,而不是对列表进行浅表复制。这可以解释为什么DotMove对象内的列表较短的原因,因为移动查找算法依赖于遍历木板时从列表末尾删除项目。 DotMove对象用于存储此列表的“快照”,而不是对列表本身的引用。

如何正确创建此列表的浅表副本?

最佳答案

辛勤工作后,该错误位于此处:

ArrayList<DotMove> moveList = new ArrayList<DotMove>();


每次moveList方法的递归创建一个新的findMovesAtPointHelper。这导致其他方法在每次迭代时都会丢失。

作为参考,这是一个新的动作列表,按长度排序,然后按得分排序(最后一个数字是标识功能上等效的动作的哈希值):

  0 1 2 3 4 5
0 r r b g b r
1 r r b r r r
2 b r b y y b
3 b g b y b b
4 b y b p b b
5 y b r b y b

Top 5 moves:
 17 Loop [(4, 3), (4, 4), (5, 4), (5, 3), (4, 3)] -86374027
 17 Loop [(4, 4), (4, 3), (5, 3), (5, 4), (4, 4)] -86374027
 17 Loop [(5, 3), (4, 3), (4, 4), (5, 4), (5, 3)] -86374027
 17 Loop [(5, 4), (4, 4), (4, 3), (5, 3), (5, 4)] -86374027
 17 Loop [(5, 2), (5, 3), (4, 3), (4, 4), (5, 4), (5, 3)] -86374027

Bottom 5 moves:
  2      [(5, 5), (5, 4)] -739973680
  2      [(5, 4), (4, 4)] -1399527984
  2      [(5, 3), (4, 3)] 831841744
  2      [(4, 4), (4, 3)] 1423500752
  2      [(5, 2), (5, 3)] 2075715024

Pre-uniquify: 105
Post-uniquify: 105
All 105 moves:
 17 Loop [(4, 3), (4, 4), (5, 4), (5, 3), (4, 3)] -86374027
 17 Loop [(4, 4), (4, 3), (5, 3), (5, 4), (4, 4)] -86374027
 17 Loop [(5, 3), (4, 3), (4, 4), (5, 4), (5, 3)] -86374027
 17 Loop [(5, 4), (4, 4), (4, 3), (5, 3), (5, 4)] -86374027
 17 Loop [(5, 2), (5, 3), (4, 3), (4, 4), (5, 4), (5, 3)] -86374027
 17 Loop [(5, 3), (4, 3), (4, 4), (5, 4), (5, 3), (5, 2)] -86374027
 17 Loop [(5, 4), (4, 4), (4, 3), (5, 3), (5, 4), (5, 5)] -86374027
 17 Loop [(5, 5), (5, 4), (4, 4), (4, 3), (5, 3), (5, 4)] -86374027
 10 Loop [(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)] -834522920
 10 Loop [(0, 1), (0, 0), (1, 0), (1, 1), (0, 1)] -834522920
 10 Loop [(1, 0), (0, 0), (0, 1), (1, 1), (1, 0)] -834522920
 10 Loop [(1, 1), (0, 1), (0, 0), (1, 0), (1, 1)] -834522920
 10 Loop [(1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (1, 2)] -834522920
 10 Loop [(1, 2), (1, 1), (0, 1), (0, 0), (1, 0), (1, 1)] -834522920
  6      [(5, 2), (5, 3), (4, 3), (4, 4), (5, 4), (5, 5)] 1195567956
  6      [(5, 5), (5, 4), (4, 4), (4, 3), (5, 3), (5, 2)] 1195567956
  5      [(0, 1), (0, 0), (1, 0), (1, 1), (1, 2)] -1697404439

...

08-05 05:44