Java 高尔夫纸牌游戏状态树

Java 高尔夫纸牌游戏状态树,java,recursion,tree,Java,Recursion,Tree,我正在做一个家庭作业项目,我们需要为高尔夫纸牌游戏生成一个状态树。为了做到这一点,我决定创建一个Move类,它表示从一堆卡片到另一堆卡片的移动——简单地说,它包含一次移动中涉及的两堆卡片的引用。树中的每个节点都知道它的移动是什么 我目前的问题是我的树太大了,比如OutOfMemoryError太大了编辑-我应该注意,当我为一个非常小的游戏制作一棵树时,我没有得到一个错误,但我的树仍然比它应该的大得多 对于那些不熟悉游戏的人:。注:我们不需要实施在国王之后扮演王后的限制 public void m

我正在做一个家庭作业项目,我们需要为高尔夫纸牌游戏生成一个状态树。为了做到这一点,我决定创建一个
Move
类,它表示从一堆卡片到另一堆卡片的移动——简单地说,它包含一次移动中涉及的两堆卡片的引用。树中的每个节点都知道它的移动是什么

我目前的问题是我的树太大了,比如
OutOfMemoryError
太大了编辑-我应该注意,当我为一个非常小的游戏制作一棵树时,我没有得到一个错误,但我的树仍然比它应该的大得多

对于那些不熟悉游戏的人:。注:我们不需要实施在国王之后扮演王后的限制

public void makeTree()
{
  _root = makeNode( null, null, 0 );
}

private Node makeNode( Node parent, Move m, int depth )
{
  Node node = new Node( parent, m, depth );
  ArrayList<Move> moves = findAllMoves();
  if( moves.size() == 0 )
    node.setScore( getScore() );
  else {
    for( Move mv : moves ) {
      mv.makeMove();
      Node child = makeNode( node, mv, depth++ );
      node.addChild( child );
      mv.undoMove();
    }
  }
  return node;
}

private ArrayList<Move> findAllMoves()
{
  ArrayList<Move> moves = new ArrayList<Move>();

  for( int i = 0; i < numPlayPiles; i++ ) {
    if( _play[i].size() != 0 ) {
       if( Math.abs( _play[i].top().getRank().ordinal() - 
          discard.getRank().ordinal() ) == 1 ) {
          moves.add( new Move( _play[i], _discard ) );
       }
    }
  }

  if( _draw.size() != 0 )
    moves.add( new Move( _draw, _discard ) );

  return moves;
}
public void makeTree()
{
_root=makeNode(null,null,0);
}
私有节点makeNode(节点父节点、移动m、整数深度)
{
节点=新节点(父节点,m,深度);
ArrayList moves=findAllMoves();
if(moves.size()==0)
node.setScore(getScore());
否则{
用于(移动mv:移动){
mv.makeMove();
Node-child=makeNode(Node,mv,depth++);
node.addChild(child);
mv.undoMove();
}
}
返回节点;
}
私人ArrayList findAllMoves()
{
ArrayList移动=新建ArrayList();
对于(int i=0;i
\u play[i]
只是指游戏中的一堆牌


我意识到在一个问题中要发布的代码有点多,但我的问题只是关于我的逻辑。我怀疑我的错误在于如何返回
makeNode
,但我完全被困在这里。有人能证实我的怀疑和/或给我一些指导吗

对于任何好奇的人来说,我的问题是没有正确阅读作业。具体来说,我的
findAllMoves
方法就是问题所在。一个节点应该有一个从绘制堆移动的动作,或者所有可能的从游戏堆移动的动作,但不能两者都有。我上面的代码允许每个子节点,即使在相同的深度,也可以创建一个
Move
,从draw-pile移动到discard-pile,从而产生大量重复节点


它也从不检查游戏结束的条件。因此,每个叶节点要么是一个失分,要么是0(即使玩家已经赢了,该方法将递归直到抽签堆为空)。

你是否必须生成所有可能的移动组合,因为我认为这就是要做的?如果您只需要生成一个移动组合,只需使用您得到的第一个移动组合。如果你必须制定一个成功的战略,这将更加复杂,但你可以做一些类似于深度优先搜索成功战略的事情(基本上沿着给定的路径继续,直到你无法获胜,然后返回到最后做出的决定,选择另一条路径,并继续搜索,直到你找到一条成功的路径)。其主要思想是,您必须删除未使用的移动以避免内存不足。我们应该为每个可能的移动组合生成一个树,然后报告节点总数、叶节点总数(游戏结束)以及可能的最高和最低分数。虽然我从问题中删除了一些代码,但每个内部节点的分数都设置为其子节点的最高分数,因此我们可以沿着树向下搜索到可能的最佳分数。好的,我建议的一件事是确保没有循环。使用调试器,看看是否可以生成树中存在循环的情况。如果有,那就意味着出了问题。