Java实现UCS算法时,能否在Node构造时将新建对象作为方法参数?
我正在Java中为一款游戏实现UCS算法,目前处于计算各状态成本的阶段。我定义了一个Node类,包含4个字段:Table类型的state、double类型的cost、Node类型的parent以及ArrayList<Node>类型的children。该类中还有一个私有静态方法calculateCost(Node starting, Node next),用于返回从starting节点到next节点的转移成本(无需关注Table类的功能)。我还实现了generateChildren()方法,代码如下:
public void generateChildren(){ ArrayList<Table> allStates = this.state.generateMoves(); for(Table state : allStates){ Node child = new Node(state, calculateCost(this, ???), this); children.add(child); } }
该方法会生成当前状态的所有可能移动,并为每个移动创建子节点。我希望将新建的child对象作为calculateCost方法的第二个参数,使this作为起始节点、child作为目标节点,请问这是否可行?
回答
这不可行,因为child对象在调用calculateCost时还未被创建——你是在构造child的过程中试图把它作为参数传入,此时child的引用根本不存在,编译器会直接报错。
这里有两种可行的解决思路:
方案1:修改calculateCost,基于状态计算成本
转移成本本质是两个状态(当前节点的state和子节点的state)之间的转移消耗,不需要完整的Node对象。直接修改calculateCost的参数类型:
private static double calculateCost(Table startingState, Table nextState) { // 调整原逻辑,基于两个Table实例计算转移成本 }
然后在generateChildren中调用:
public void generateChildren(){ ArrayList<Table> allStates = this.state.generateMoves(); for(Table state : allStates){ double moveCost = calculateCost(this.state, state); Node child = new Node(state, moveCost, this); children.add(child); } }
这种方案逻辑最清晰,也避免了不必要的对象操作,是优先推荐的做法。
方案2:先创建临时节点,再更新成本
如果必须保留calculateCost接收Node参数的设计,可以先创建一个成本占位的临时节点,计算完成后再更新成本值:
public void generateChildren(){ ArrayList<Table> allStates = this.state.generateMoves(); for(Table state : allStates){ // 先创建临时节点,成本用占位值 Node child = new Node(state, 0.0, this); // 计算实际转移成本并赋值 child.cost = calculateCost(this, child); children.add(child); } }
这种方式需要保证Node的cost字段可修改(比如添加setCost方法,或者将字段设为非私有)。
内容的提问来源于stack exchange,提问作者Stelios P.98

