递归创建树

时间:2011-03-07 12:14:59

标签: java recursion tree

我试图以递归方式填充树,但我的代码只填写一个深度长度,然后退出。即每个节点只有一个孩子。有什么东西没有考虑到吗?

public static void populate(Node n, int depth, String player){
    System.out.println("Depth: " + depth);
    if(player.equalsIgnoreCase("X"))
        player = "O";
    else
        player = "X";
    int j = 0;
    System.out.println("empty spots: " + ((Board)n.getData()).noOfEmpty());
    for(int i=0; i<((Board)n.getData()).noOfEmpty(); i++){
        if(((Board)n.getData()).getSquare(j).equalsIgnoreCase("X")
                || ((Board)n.getData()).getSquare(j).equalsIgnoreCase("O"))
            j++;
        else{
            Board tmp = new Board(((Board)n.getData()), j, player);
            Node newNode = new Node(tmp);
            tree.insert(n, newNode);
            populate(newNode, depth-1, player);
        }
    }
}

P.S。我检查noOfEmpty()返回值,该值应确定节点应具有的子节点数。

编辑:@eznme按要求填写完整的代码:

public class MinMax {

    protected static Tree tree;


    public static void createTree(Board b){
        tree = new Tree();
        tree.setRoot(new Node(b));
        populate(tree.getRoot(), 5, "X");
        //System.out.println("printing tree");
        //tree.print(1);
    }

    public static void populate(Node n, int depth, String player){
        System.out.println("Depth: " + depth);
        if(player.equalsIgnoreCase("X"))
            player = "O";
        else
            player = "X";
        int j = 0;
        System.out.println("empty spots: " + ((Board)n.getData()).noOfEmpty());
        for(int i=0; i<((Board)n.getData()).noOfEmpty(); i++){
            if(((Board)n.getData()).getSquare(j).equalsIgnoreCase("X")
                    || ((Board)n.getData()).getSquare(j).equalsIgnoreCase("O"))
                j++;
            else{
                Board tmp = new Board(((Board)n.getData()), j, player);
                Node newNode = new Node(tmp);
                tree.insert(n, newNode);
                populate(newNode, depth-1, player);
            }
        }
    }
}

import java.util.ArrayList;

/**
*
* @author Greg
*/
public class Node {

    protected Object data;
    protected int score; //fields to be used by the MaxMin class
    protected ArrayList<Node> children;

    //constructors
    public Node(){
        children = new ArrayList(0);
        data = null;
    }
    public Node(Object obj){
        children = new ArrayList(0);
        data = obj;
    }


    public void setChild(Node n){
        //EFFECT: set the ith child to node t
        children.add(n);
    }
    public void setChildren(Node[] t){
        //EFFECT: copy the array t, into the array children, effectively
        // setting all the chidern of this node simultaneouly
        int l = children.size();
        for(int i=0; i<t.length; i++){
            children.add(l, t[i]);
        }
    }
    public void setData(Object obj){
        //EFFECT: set the date of this node to obj, and also set the number of
        //  children this node has
        data = obj;
    }
    public Node getChild(int i){
        //EFFECT: returns the child at index i
        return children.get(i);
    }

    public int noOfChildren(){
        //EFFECT: return the length of this node
            return children.size();
    }

    public Object getData(){
        //EFFECT: returns the data of this node
        return data;
    }

    @Override
    public String toString(){
        //EFFECT: returns the string form of this node
        return "" + data.toString() + "\nwith " + noOfChildren()+ "\n";
    }

    public boolean isLeaf(){
        if(children.size()==0)
            return true;
        return false;
    }


    public void setScore(int scr){
        score = scr;
    }

    public int getScore(){
            return score;
    }
}

public class Tree {

    private Node root;

    public Tree(){
        setRoot(null);
    }

    public Tree(Node n){
        setRoot(n);
    }

    public Tree(Object obj){
        setRoot(new Node(obj));
    }

    protected Node getRoot(){
        return root;
    }

    protected void setRoot(Node n){
        root = n;
    }

    public boolean isEmpty(){
        return getRoot() == null;
    }

    public Object getData(){
        if(!isEmpty())
            return getRoot().getData();
        return null;
    }

    public Object getChild(int i){
        return root.getChild(i);
    }

    public void setData(Object obj){
        if(!isEmpty())
            getRoot().setData(obj);
    }

    public void insert(Node p,Node c){
        if(p != null)
            p.setChild(c);
    }

    public void print(int mode){
        if(mode == 1) pretrav();
        else if(mode == 2) postrav();
        else
            System.out.println("yeah... mode 1 or 2...nothing else, try agn");
    }

    public void pretrav(){
        pretrav(getRoot());
    }

    protected void pretrav(Node t){
        if(t == null)
            return;
        System.out.println(t.getData()+" \n");
            for(int i=0; i<t.noOfChildren(); i++)
                pretrav(t.getChild(i));
    }

    public void postrav(){
        postrav(getRoot());
    }

    protected void postrav(Node t){
        if(t == null)
            return;
        System.out.print(t.getData()+" ");
            for(int i=0; i<t.noOfChildren(); i++)
                pretrav(t.getChild(i));
        System.out.print(t.getData()+" ");
    }
}

public class Board {

    boolean isFull = false;         // a check to see if the board is full
    String[] grid = new String[9];  //an array represting the 9 square on a board
    int hV;
    String MIN, MAX;

    public Board(){
        for(int i=0; i<grid.length;i++)
            grid[i] = Integer.toString(i);
        hV = heuristicValue(this);
    }

    public Board(Board b, int x, String player){
        this.grid = b.getBoard();
        if(!(grid[x].equalsIgnoreCase("X")|| grid[x].equalsIgnoreCase("X")))
            grid[x] = player;
    }

    public boolean setSquare(String player, int position){
        /*
        EFFECT:set a square on the board to either a X or a O, debending on the player
        PRECON: square (x,y) is empty
        POATCON: square (x,y) has player 'symbol'
        */

        boolean isValidPlay = false;
        try{
            //as a sanity
            Integer.parseInt(grid[position]);
            grid[position] = player;
            isValidPlay = true;

        }catch(NumberFormatException e){
            System.out.println("positon " + position + "is already occupied");
        }
        return isValidPlay;
    }

    public boolean endGame(){
        /*
        * EFFECT: check to see if the game have been won or drawn
        */
        if(ticTacToe(0,1,2)){
            //System.out.println("Player " + grid[0] + " wins");
            return true;
        }
        else if(ticTacToe(3,4,5)){
            //System.out.println("Player " + grid[3] + " wins");
            return true;
        }
        else if(ticTacToe(6,7,8)){
            //System.out.println("Player " + grid[6] + " wins");
            return true;
        }
        else if(ticTacToe(0,4,8)){
            //System.out.println("Player " + grid[0]+ " wins");
            return true;
        }
        else if(ticTacToe(0,3,6)){
            //System.out.println("Player " + grid[0]+ " wins");
            return true;
        }
        else if(ticTacToe(1,4,7)){
            //System.out.println("Player " + grid[1] + " wins");
            return true;
        }
        else if(ticTacToe(2,5,8)){
            //System.out.println("Player " + grid[2] + " wins");
            return true;
        }else if(ticTacToe(2,4,6)){
            //System.out.println("Player " + grid[2] + " wins");
            return true;
        }
        else
            return isDrawn();
    }

    public boolean ticTacToe(int x, int y, int z){
        /*
        * check is x, y and z has the same value
        */
        try{
            Integer.parseInt(grid[x]);
            return false;
        }catch(NumberFormatException e){
        if( grid[x].equals(grid[y])
                && grid[x].equals(grid[z]))
            return true;
        else
            return false;
        }
    }

    public String getSquare(int i){
        return grid[i];
    }

    @Override
    public String toString(){
        String msg = "";
        for(int i=0; i<grid.length; i++){
            msg = msg + grid[i] + " ";
            if(i==2 || i==5)
                msg = msg+ "\n";
        }
        return msg;
    }

    public boolean isDrawn(){
        /*
        * check to see if there are any 'free' spaces on the board, if there are any
        * return false, else return true
        */
        for(int i=0; i<grid.length; i++){
        try{
            Integer.parseInt(grid[i]);
            return false;
            }catch(NumberFormatException e){
            }
        }
        System.out.println("Game drawn");
        return true;
    }

    public String[] getBoard(){
        return grid;
    }

    public int noOfEmpty(){
        //EFFECT: returns the number of empty squares
        int count = 0;
        for(int i=0; i<grid.length; i++)
            if (!(grid[i].equalsIgnoreCase("X") || grid[i].equalsIgnoreCase("O")))
                count++;
        return count;
    }

    public int heuristicValue(Board b){
        String MAX = "X", MIN = "O";
        /*
        * calculate a value that will be used as a heuristic function
        * the function works for ever X in a row WITHOUT O: 1 point,
        * for two X in a row WITHOUT a O: 5 points
        * and 3 X in a row: 100 points
        */
        //System.out.println("Computing heuristic");
        //System.out.println("Computing horizontals");
        int hCount = 0;
        //sum up the horizontals
        for(int i=0; i<9; i=i+3){
            int tmpMAX = playerCount(b, MAX,i,i+1,i+2);
            int tmpMIN = playerCount(b, MIN,i,i+1,i+2);
            //System.out.println(tmpMAX);
            //System.out.println(tmpMIN);
            if(tmpMIN > 0){
                //System.out.println("Min was zero");
            }
            else if(tmpMAX==1){
                //System.out.println("has one");
                hCount = hCount + 1;
            }
            else if(tmpMAX==2){
                //System.out.println("was tw0");
                hCount = hCount + 5;
            }
            else if(tmpMAX==3){
                //System.out.println("full 100");
                hCount = hCount + 100;
            }
        }
        //System.out.println("Computing verticals");
        //sum up the verticals
        for(int i=0; i<3; i++){
            int tmpMAX = playerCount(b, MAX,i,i+3,i+6);
            int tmpMIN = playerCount(b, MIN,i,i+3,i+6);
            if(tmpMIN > 0){}
            else if(tmpMAX==1){
                hCount = hCount +1;
            }
            else if(tmpMAX==2){
                hCount = hCount + 5;
            }
            else if(tmpMAX==3){
                hCount = hCount + 100;
            }
        }
        //System.out.println("Computing diagonals");
        //sum up diagonals
        if(playerCount(b, MIN,0,4,8)==0){

            if(playerCount(b, MAX,0,4,8)==1){
                hCount = hCount + 1;
            }
            if(playerCount(b, MAX,0,4,8)==2)
                hCount = hCount + 5;
            if(playerCount(b, MAX,0,4,8)==3)
                hCount = hCount + 100;
        }
        if(playerCount(b, MIN,2,4,6)==0){

            if(playerCount(b, MAX,2,4,6)==1){
                hCount = hCount + 1;
            }
            if(playerCount(b, MAX,2,4,6)==2)
                hCount = hCount + 5;
            if(playerCount(b, MAX,2,4,6)==3)
                hCount = hCount + 100;
        }
        //System.out.println("Computing completed");
        int hV = hCount;
        return hV;
    }

    int playerCount(Board b, String player, int x, int y, int z){
        int count = 0;
        if(b.getSquare(x).equals(player))
            count = count + 1;
        if(b.getSquare(y).equals(player))
            count = count + 1;
        if(b.getSquare(z).equals(player))
            count = count + 1;
        //System.out.println("playerCount; " + count);
        return count;
    }
}

import java.io.*;

import java.io.IOException;

public class Main {

public static void main(String[] args) throws IOException{
    BufferedReader  reader = new BufferedReader(new
                                            InputStreamReader(System.in));
    Board thisGame = new Board();
    System.out.println("Start \n" + thisGame.toString());
    MinMax.createTree(thisGame);
    System.exit(0);
}

}

3 个答案:

答案 0 :(得分:3)

为了递归地构建一个n-ary树,我会这样做:

public static void populate(Node n, int height){
    if(height = 0){
        n = new Node();  
    }else{
        n = new Node();
        for(int i = 0; i < n.nbChilds(); i++){
            populate(n.getChildAt(i), height - 1);
        }
    }
}

我希望它有所帮助。

使用此算法创建节点的顺序(在二叉树上):

              1
      2                9
  3       6        10     13
4  5    7   8    11  12 14  15

答案 1 :(得分:2)

所以这就是我在你的情况下会做的事情(minimax tic-tac-toe):

术语:

  • 节点的高度:从此节点到它的距离更远。
  • 节点的深度:从树的根到此节点的距离。

你必须继续尝试所有情况,直到:电路板已满或一名玩家获胜。因此,树的高度为numberOfCells + 1。 如果我们简化问题并且不担心对称重复: 每个节点都有numberOfcells - nodeDepth个孩子。

public static void main(String[] args){
    Tree t = new Tree();
    int nbCells = 9;
    t.setRoot(buildTree(new Board(nbCells), 0, -1));
}

public static Node buildTree(Board b, int player, int positionToPlay){
    if(player != 0){
        b.setCellAt(positionToPlay, player);
    }
    Node n = new Node(b, b.nbEmptyCells());

    int j = 0;
    for(int i = 0; i < b.nbCells(); i++){
        if(b.getCellAt(i) == 0)
            n.setChildAt(j++, buildTree(new Board(b), changePlayer(player), i));
    }

return n;
}

public static int changePlayer(int p){
    switch(p){
    case 0:
        return 1;
    case 1:
        return 2;
    case 2:
        return 1;
    default:
        return 0;
    }
}

节点类:

public class Node {
    private Board board;
    private Node[] childs;

    public Node(Board b, int nbChilds){
        this.board = new Board(b);
        this.childs = new Node[nbChilds];
    }

    public Node getChildAt(int i){
        return childs[i];
    }

    public int nbChilds(){
        return childs.length;
    }

    public void setChildAt(int i, Node n){
        this.childs[i] = n;
    }

    public Board getBoard(){
        return this.board;
    }

答案 2 :(得分:1)

我认为你的做法是错误的。 首先,你正在做一个循环递归,除了使用一个没有意义的depth变量,因为你从来没有检查它的值来结束递归,或者知道一些关于你想做什么。 在循环中使用动态函数本身并不是很好,因为迭代应该从循环的开始很好地定义。 i在您的背景下无用。

因此,如果我理解你的代码,那么有问题的情况是有3个空方块和4个非空方块,因为你会将i从0迭代到3,除了递增{{1}之外什么都不做从0到3然后退出,因为j将达到3。

当然我可能在某些方面有误,因为我不知道i是什么,它来自哪里?它与n有关吗?什么是董事会。

我希望我的贡献可以帮到你,我鼓励你发布更多细节来澄清漏洞并让我能够帮助你。