Je reçois un débordement de pile en essayant de remplir ma liste liée 3D. Je ne comprends pas pourquoi cela ne s'arrête pas aux limites spécifiées, cela fonctionne pour toujours. C'est probablement une simple erreur, je ne comprends tout simplement pas.

EDIT: OK, j'ai maintenant mis à jour le code et supprimé cette erreur stupide, mais cela ne fonctionne toujours pas exactement comme prévu. Il semble générer la liste 10x10x10, mais son exécution à l'infini. Initialisé avec (10, 10, 10), il devrait créer 10000 objets et s'arrêter. J'essaie juste de créer une liste pour représenter un plan de coordonnées 3D et chaque coordonnée entière est un nœud, accessible par le pointeur de direction nord, sud, est, ouest, haut ou bas.

Toute aide appréciée

public class Main {


    public static void main(String[] args) {
        NodeController3D con = new NodeController3D(6,6, 6);

    }

}
public class Node3D {

//    public Node3D(Node3D... nodes) {
//        if (nodes.length != 5) {
//            throw new RuntimeException();
//        }
//        this.nodes = nodes;
//    }

    public Node3D[] nodes;
    public int x, y, z;


    public Node3D north() {
        return nodes[0];
    }

    public Node3D south() {
        return nodes[1];
    }

    public Node3D east() {
        return nodes[2];
    }

    public Node3D west() {
        return nodes[3];
    }

    public Node3D up() {
        return nodes[4];
    }

    public Node3D down() {
        return nodes[5];
    }
}

public class NodeController3D {

    public NodeController3D(int length, int width, int height) {
        HEAD = new Node3D();
        pnc(HEAD, length, width, height);
    }

    private void pnc(Node3D node, int xMax, int yMax, int zMax) {
        if(node.nodes == null) {
            node.nodes = new Node3D[5];
        }

        if (node.x < xMax) {
            Node3D newNode = node.nodes[2] = new Node3D();
            newNode.x = node.x + 1;
            newNode.y = node.y;
            newNode.z = node.z;
            System.out.println(newNode.x + ", " + newNode.y + ", " + newNode.z);

            pnc(newNode, xMax, yMax, zMax);
        }
        if (node.y < yMax) {
            Node3D newNode = node.nodes[0] = new Node3D();
            newNode.x = node.x;
            newNode.y = node.y + 1;
            newNode.z = node.z;

            pnc(newNode, xMax, yMax, zMax);
        }
        if (node.z < zMax) {
            Node3D newNode = node.nodes[4] = new Node3D();
            newNode.x = node.x;
            newNode.y = node.y;
            newNode.z = node.z + 1;

            pnc(newNode, xMax, yMax, zMax);
        }
    }

//    public NodeController3D(int radius) {
//
//    }

    public final Node3D HEAD;
}

EDIT: OK, j'ai maintenant mis à jour le code et supprimé cette erreur stupide, mais cela ne fonctionne toujours pas exactement comme prévu. Il semble générer la liste 10x10x10, mais son exécution à l'infini. Initialisé avec (10, 10, 10), il devrait créer 10000 objets et s'arrêter. J'essaie juste de créer une liste pour représenter un plan de coordonnées 3D et chaque coordonnée entière est un nœud, accessible par un pointeur de direction.

1
Colby 4 janv. 2016 à 13:13

3 réponses

Meilleure réponse

Vous rencontrez une récursion infinie.

Alors qu'est-ce qui se passe.

Vous créez un nouveau Array.

if(node.nodes == null) {
   node.nodes = new Node3D[5];
}

Vous continuez en utilisant un Node3D comme variable newNode. Cela se produit parce que node.x<xMax sera vrai. - & gt; Node3D newNode = node.nodes[2] = new Node3D();.

Vous appelez récursivement pnc maintenant, avec ce newNode.

Alors ce qui se passe maintenant, node.y<yMax sera vrai. Vous réaffectez maintenant le newNode. Node3D newNode = node.nodes[0] = new Node3D();. et appelez à nouveau pnc de manière récursive. Mais vous rencontrez un problème maintenant. puisqu'il s'agit d'un nouveau Node3D, votre node.x<xMax sera de nouveau vrai et ces deux étapes se reproduisent et se répètent jusqu'à ce que vous obteniez l'erreur mentionnée.

Pour corriger cette erreur, vous souhaiterez peut-être copier node.x et node.y dans votre variable nouvellement créée.

En modifiant l'affectation, vous pourriez sortir de la récursivité infinie.

if (node.x < xMax) {
    if (node.nodes[2] == null) {
        node.nodes[2] = new Node3D();
    }
    Node3D newNode = node.nodes[2];
    newNode.x = node.x + 1;
    newNode.y = node.y;
    newNode.z = node.z;

    pnc(newNode, xMax, yMax, zMax);
}
if (node.y < yMax) {
    if (node.nodes[0] == null) {
        node.nodes[0] = new Node3D();
    }
    Node3D newNode = node.nodes[0];
    newNode.x = node.x;
    newNode.y = node.y + 1;
    newNode.z = node.z;

    pnc(newNode, xMax, yMax, zMax);
}
if (node.z < zMax) {
    if (node.nodes[4] == null) {
        node.nodes[4] = new Node3D();
    }
    Node3D newNode = node.nodes[4];
    newNode.x = node.x;
    newNode.y = node.y;
    newNode.z = node.z + 1;

    pnc(newNode, xMax, yMax, zMax);
}

Mais comme je ne sais pas ce que vous essayez de réaliser avec ces éléments spécifiques à ces index spécifiques dans votre tableau, cela pourrait être une mauvaise solution pour vous.

1
SomeJavaGuy 4 janv. 2016 à 10:28

Chaque fois que vous créez un nouveau Node3D, les variables x, y et z ne sont pas initialisées, donc elles seront évaluées à 0 en cas d'accès.

Dans la méthode pnc, il y aura toujours des cas où x

Une bonne pratique consiste à rendre les variables privées et définitives lorsque cela est possible:

class Node3D {
    private final Node3D[] nodes;
    private final int x;
    private final int y;
    private final int z;

    public Node3D(int x, int y, int z) {
        this.nodes = new Node3D[6];
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

Cela évitera ce genre d'erreurs à l'avenir. Vous pouvez créer des méthodes getter pour les variables. Si vous avez vraiment besoin de réaffecter les valeurs pour x, y ou z, vous pouvez à la place créer un nouveau Node3D afin que l'objet puisse rester immuable.

1
Boris van Katwijk 4 janv. 2016 à 10:40

Vous naviguiez vers les nœuds de la grille 3D de plusieurs manières. Par exemple, vous êtes allé à (1,1,0) à la fois à partir de (1,0,0) et (0,1,0), créant des doublons pour la même coordonnée. De cette façon, vous créez un nombre de nœuds égal à la somme totale des chemins de cube pour chaque nœud.

Une autre approche consiste à peupler un cube de nœuds et à donner à chaque nœud une référence au cube dans lequel il se trouve. Ensuite, lorsque vous devez aller au nord, vous laissez simplement le cube renvoyer le nœud droit, en utilisant les coordonnées du nœud actuel . Vous pouvez utiliser la MultiKeyMap sous forme de grille:

class Node3D {
    private static int instances = 0;
    public final int x;
    public final int y;
    public final int z;
    public final int number;
    public final MultiKeyMap<Integer, Node3D> gridMap;

    public Node3D(MultiKeyMap<Integer, Node3D> gridMap, int x, int y, int z) {
        this.gridMap = gridMap;
        this.x = x;
        this.y = y;
        this.z = z;
        this.number = instances++;
    }

    //Add/alter these methods according to your orientation
    //Returns null if no value is present, you might want to handle this
    public Node3D getNorthNode() {
        return gridMap.get(this.x + 1, this.y, this.z);
    }

    //Other getters omitted

    @Override
    public String toString() {
        return "Node3D#" + number + "[" + x + ", " + y + ", " + z + "]";
    }
}

Maintenant, l'initialisation peut être effectuée comme suit:

    MultiKeyMap<Integer, Node3D> gridMap = new MultiKeyMap<>();
    for(int x = 0; x < xMax; x++) {
        for(int y = 0; y < yMax; y++) {
            for(int z = 0; z < zMax; z++) {
                gridMap.put(x, y, z, new Node3D(gridMap, x, y, z));
            }
        }
    }

    System.out.println(gridMap.get(4, 4, 4).getNorthNode());
1
Boris van Katwijk 5 janv. 2016 à 07:59