How to get recursion and for loop work together in Java?
I need create a tree structure recursively. I开发者_高级运维n the tree each node has different amount of children, so I think I need to call the method recursively in a for loop. The for loop loops as many times as the current node has children.
The function first creates the leftmost child in depth d and then returns (or is supposed to return) back to the previous depth and creates another and so on. I believe you know what I mean here. So I'm trying to create the whole tree in this way. I have set a base case so that if the conditions of the base case are met, the method isn't called recursively anymore. The problem is that my program somehow manages to get past those conditions and continues calling the method recursively, though it shouldn't do that.
Here's the code:
private void makeTree(GameState prevState, Vector moves, Node parentNode, int index, int depthLimit) {
if(prevState.getPossibleMoveCount(index) != 0){
for(int i = 0; i < moves.size(); i++){
Move thisMove = (Move)moves.get(i);
GameState newState = prevState.getNewInstance(thisMove);
Node child = new Node(newState, thisMove);
parentNode.addChild(child);
child.setParent(parentNode);
if((child.getDepth() + 1) < depthLimit){
int newIndex = switchIndex(index);
Vector newMoves = newState.getPossibleMoves(newIndex);
makeTree(newState, newMoves, child, newIndex, depthLimit);
}else{
child.setScore(newState.getMarkCount(index));
}
}
}
}
The Node class here isn't the Java default Node class, but instead a class that belongs to this interface. I know one shouldn't create a class with a same name that's already given to some default Java class, but this interface isn't mine. I just have to implement it. The Node class doesn't collide with the Java Node class. So I don't think that causes any problems.
The real problem is that the if((child.getDepth() + 1) < depthLimit) doesn't seem to have any effect on the program. The program continues calling the method recursively every time until it hits the depth 61 at which point memory runs out. The depth limit is set to 5, but like I said, it doesn't seem to matter.
The point is that when the program is in the depth "depthLimit -1" it should stop the recursive call and instead set the scores for the children of the current node and then continue doing all those things for the next element that happens to be in turn. Because this method doesn't return anything (void method), there don't need to be any return calls, right?
I hope you get the idea what I'm trying to do and what goes wrong. Any help is appreciated. And if you need any more information, please just ask and I'll try to explain this more carefully.
Thanks in advance.
E: The depthLimit argument in the method is given before the first call and it doesn't change during the tree creation.
Your problem is not in the part you posted.
I added dummy implementations for all the classes and methods used in your method, and it runs quite fine, stopping at level 6.
package de.fencing_game.paul.examples;
import java.util.*;
public class RecursionAndLoop {
private static class Move {
private String id;
public Move(String type) {
this.id = type;
}
public String toString(){
return "Move(" + id + ")";
}
}
private static class GameState {
private static int nextID;
private int id;
GameState() {
this.id = nextID++;
}
public GameState getNewInstance(Move move) {
return new GameState();
}
public int getPossibleMoveCount(int index) {
return 5;
}
public Vector<Move> getPossibleMoves(int index) {
Vector<Move> v = new Vector<Move>();
for(int i = 0; i < 5; i++) {
v.add(new Move(index + "×" + i));
}
return v;
}
public int getMarkCount(int index) {
return 20 + index;
}
public String toString() {
return "GameState[" + id + "]";
}
}
private static class Node {
private GameState state;
private Move move;
private List<Node> children;
private Node parent;
private int score;
public Node(GameState s, Move m) {
this.children = new ArrayList<Node>();
this.state = s;
this.move = m;
}
public void addChild(Node child) {
children.add(child);
}
public void setParent(Node node) {
parent = node;
}
public void setScore(int neu) {
this.score = neu;
}
public int getDepth() {
if(parent == null) {
return 0;
}
return 1 + parent.getDepth();
}
/**
* prints a simple tree view of this ZipNode and its descendants
* on {@link System.out}.
* @param prefix a prefix string to add before all lines.
* @param self a prefix string to add before the line of this node
* itself (after the general prefix).
* @param sub a prefix string to add before the line of all subnodes
* of this node (after the general prefix).
*/
private void printTree(String prefix,
String self,
String sub) {
System.out.println(prefix + self + state + " - " + move +
" - " + score);
String subPrefix = prefix + sub;
// the prefix strings for the next level.
String nextSelf = " ├─ ";
String nextSub = " │ ";
Iterator<Node> iterator =
this.children.iterator();
while(iterator.hasNext()) {
Node child = iterator.next();
if(!iterator.hasNext() ) {
// last item, without the "|"
nextSelf = " └─ ";
nextSub = " ";
}
child.printTree(subPrefix, nextSelf, nextSub);
}
}
}
int switchIndex(int index) {
return index + 1;
}
private void makeTree(GameState prevState, Vector<Move> moves, Node parentNode, int index, int depthLimit) {
if(prevState.getPossibleMoveCount(index) != 0){
for(int i = 0; i < moves.size(); i++){
Move thisMove = moves.get(i);
GameState newState = prevState.getNewInstance(thisMove);
Node child = new Node(newState, thisMove);
parentNode.addChild(child);
child.setParent(parentNode);
if((child.getDepth() + 1) < depthLimit){
int newIndex = switchIndex(index);
Vector<Move> newMoves = newState.getPossibleMoves(newIndex);
makeTree(newState, newMoves, child, newIndex, depthLimit);
}else{
child.setScore(newState.getMarkCount(index));
}
}
}
}
public static void main(String[] params) {
GameState start = new GameState();
Vector<Move> m = new Vector<Move>();
m.add(new Move("start"));
Node root = new Node(start, null);
int index = 7;
int depthLimit = 6;
new RecursionAndLoop().makeTree(start, m, root, index, depthLimit);
root.printTree("", " ", "");
}
}
(I changed a bit to generic types to avoid compiler warnings.)
Here is the output for depthLimit=4:
GameState[0] - null - 0
└─ GameState[1] - Move(start) - 0
├─ GameState[2] - Move(8×0) - 0
│ ├─ GameState[3] - Move(9×0) - 29
│ ├─ GameState[4] - Move(9×1) - 29
│ ├─ GameState[5] - Move(9×2) - 29
│ ├─ GameState[6] - Move(9×3) - 29
│ └─ GameState[7] - Move(9×4) - 29
├─ GameState[8] - Move(8×1) - 0
│ ├─ GameState[9] - Move(9×0) - 29
│ ├─ GameState[10] - Move(9×1) - 29
│ ├─ GameState[11] - Move(9×2) - 29
│ ├─ GameState[12] - Move(9×3) - 29
│ └─ GameState[13] - Move(9×4) - 29
├─ GameState[14] - Move(8×2) - 0
│ ├─ GameState[15] - Move(9×0) - 29
│ ├─ GameState[16] - Move(9×1) - 29
│ ├─ GameState[17] - Move(9×2) - 29
│ ├─ GameState[18] - Move(9×3) - 29
│ └─ GameState[19] - Move(9×4) - 29
├─ GameState[20] - Move(8×3) - 0
│ ├─ GameState[21] - Move(9×0) - 29
│ ├─ GameState[22] - Move(9×1) - 29
│ ├─ GameState[23] - Move(9×2) - 29
│ ├─ GameState[24] - Move(9×3) - 29
│ └─ GameState[25] - Move(9×4) - 29
└─ GameState[26] - Move(8×4) - 0
├─ GameState[27] - Move(9×0) - 29
├─ GameState[28] - Move(9×1) - 29
├─ GameState[29] - Move(9×2) - 29
├─ GameState[30] - Move(9×3) - 29
└─ GameState[31] - Move(9×4) - 29
When you call
makeTree(newState, newMoves, child, newIndex, depth);
inside of your if statement where are you expecting depth to come from? It looks like you're passing in depth to the makeTree routine, yet expecting it to be the depth of the current node (this.depth maybe?)
精彩评论