十五数码游戏中Config实例参数被意外修改问题求助
解决十五数码游戏中Config实例被意外修改的问题
这绝对是浅拷贝搞的鬼!你现在的问题本质是:复制Config实例的时候,只是把数组的引用复制给了新实例,并没有创建一个全新的数组对象。所以原来的实例A和新生成的实例B,它们的board数组指向的是内存里同一个区域——改B的数组,自然A的数组也会跟着变,因为根本就是同一个东西!
问题根源确认
先看看你复制Config的代码是不是类似这样(假设是Java语言,毕竟你提到了int数组和类实例):
// 错误的构造函数——浅拷贝数组引用 public class Config { private int[] board; public Config(int[] board) { this.board = board; // 直接赋值引用,两个实例共享同一个数组 } // 你的移动方法 public Config moveUp(Config a) { Config b = new Config(a.board); // 这里还是传引用 // 找到0的位置并交换 int zeroPos = findZero(b.board); if (zeroPos >= 4) { swap(b.board, zeroPos, zeroPos - 4); } return b; } }
这种写法下,A和B的board是同一个数组,不管你改哪一个,另一个都会同步变化。
解决方案:实现数组的深拷贝
因为int是基本数据类型,我们只需要创建一个新的数组,把原数组的元素逐个复制进去就行,这样每个Config实例都拥有独立的数组。
方法1:修改Config的构造函数
让构造函数接收数组时,自动创建数组副本:
import java.util.Arrays; public class Config { private int[] board; public Config(int[] board) { // 使用Arrays.copyOf创建新数组,复制所有元素 this.board = Arrays.copyOf(board, board.length); } // 或者用数组的clone方法,对于基本类型数组,clone是值拷贝 // this.board = board.clone(); }
这样不管你用哪个移动方法创建新实例,新的Config都会拥有自己独立的数组,修改它不会影响原实例。
方法2:在移动方法中显式复制数组
如果不想修改构造函数,也可以在移动方法里先复制数组,再创建新实例:
public Config moveUp(Config a) { // 先复制原实例的数组 int[] newBoard = Arrays.copyOf(a.board, a.board.length); Config b = new Config(newBoard); // 后续操作都针对newBoard,不会影响a的数组 int zeroPos = findZero(newBoard); if (zeroPos >= 4) { swap(newBoard, zeroPos, zeroPos - 4); } return b; }
验证效果
修改后,你再调用移动方法得到B,然后打印A的棋盘状态,就会发现A还是原来的样子,B是移动后的状态,两者互不影响了。
内容的提问来源于stack exchange,提问作者Rodrigo
相关产品推荐
相关产品推荐

