当前位置: 首页 > 知识库问答 >
问题:

Java——无法摆脱这种递归方法

姚洲
2023-03-14

我正在尝试实现一个depht first search alogrithm(我的代码可能很糟糕,对不起)。现在我想让这成为一个递归方法,但一旦满足结束条件,我似乎就无法打破它。您在方法中看到的第一个if-条件应该会跳出该方法。当我调试项目时,它到达了返回语句,然后立即跳转到方法的末尾。但是它没有停止整个事情,而是回到了while(! allNeighboursVisual)html" target="_blank">循环并以无限循环进行。

我试图自己解决这个问题,但没有成功,于是我开始在网上搜索,但我找不到任何解决问题的方法。

编辑:决定在我的github上分享这个项目的链接,让你们来试试:https://github.com/Equiphract/Maze

编辑2:更新了代码;我把它拼成了一起,所以请不要指望任何令人愉快的东西:)

这是递归方法:

public void depthFirstSearch(int x, int y, Tile[][] maze) {
    // Return method after every Tile is visited.
    if (this.visitedCounter == maze.length * maze[0].length) {
        this.stack.clear();
        return;
    }

    Tile currentTile = maze[x][y];
    Random r = new Random();
    int neighbourAmount = currentTile.getNeighbourAmount();
    boolean allNeighboursVisited = false;
    int stopCounter = 0;

    // If it is a new Tile, mark it as visited
    if (!currentTile.isVisited()) {
        currentTile.setVisited(true);
        this.visitedCounter++;
        stack.add(currentTile);
    }

    // Check if neighbours are not yet visited and "visit" one of them.
    while (!allNeighboursVisited) {
        int random;
        do {
            random = r.nextInt(neighbourAmount);
        } while (this.excludeList.contains(random));

        Tile neighbour = currentTile.getNeighbours().get(random);
        if (!neighbour.isVisited()) {
            if (neighbour.getX() == currentTile.getX() - 1) {
                currentTile.getWall(4).setOpen(true);
                neighbour.getWall(2).setOpen(true);
            } else if (neighbour.getX() == currentTile.getX() + 1) {
                currentTile.getWall(2).setOpen(true);
                neighbour.getWall(4).setOpen(true);
            } else if (neighbour.getY() == currentTile.getY() - 1) {
                currentTile.getWall(1).setOpen(true);
                neighbour.getWall(3).setOpen(true);
            } else if (neighbour.getY() == currentTile.getY() + 1) {
                currentTile.getWall(3).setOpen(true);
                neighbour.getWall(1).setOpen(true);
            }
            this.excludeList.clear();
            depthFirstSearch(neighbour.getX(), neighbour.getY(), maze);
            if (this.visitedCounter == maze.length * maze[0].length) {
                this.stack.clear();
                return;
            }
        } else {
            this.excludeList.add(random);
            stopCounter++;
        }

        if (stopCounter == neighbourAmount) {
            allNeighboursVisited = true;
        }
    }

    // If every neighbour has already been visited, go back one Tile.
    if (!this.stack.isEmpty()) {
        this.stack.remove(this.stack.size() - 1);
        if (!this.stack.isEmpty()) {
            Tile backtrackTile = this.stack.get(this.stack.size() - 1);
            this.excludeList.clear();
            depthFirstSearch(backtrackTile.getX(), backtrackTile.getY(), maze);
            if (this.visitedCounter == maze.length * 3) {
                this.stack.clear();
                return;
            }
        }
        this.excludeList.clear();
    }
}

你知道吗,这里是Tile-Object(抱歉在这短时间内进行了大量编辑):

public class Tile {
    private ArrayList<Wall> walls;
    private ArrayList<Tile> neighbours;
    private int x;
    private int y;
    private boolean visited;

    /*
     * Constructor of the Tile class.
     */
    public Tile(int x, int y) {
        this.walls = new ArrayList<Wall>();
        this.neighbours = new ArrayList<Tile>();

        this.walls.add(new Wall(1));
        this.walls.add(new Wall(2));
        this.walls.add(new Wall(3));
        this.walls.add(new Wall(4));

        this.x = x;
        this.y = y;
        this.visited = false;
    }

    /*
     * Returns the ArrayList walls.
     */
    public ArrayList<Wall> getWalls() {
        return walls;
    }

    /*
     * Returns the value of visited.
     */
    public boolean isVisited() {
        return visited;
    }

    /*
     * Sets the value of visited to a specified value.
     * 
     * @param visited a boolean value
     */
    public void setVisited(boolean visited) {
        this.visited = visited;
    }

    /*
     * Returns a wall with the specified position.
     * 
     * @param position the position of the wall
     */
    public Wall getWall(int position) {
        for(Wall w : this.walls) {
            if(w.getPosition() == position) {
                return w;
            }
        }
        return null;
    }

    public int getNeighbourAmount() {
        return this.neighbours.size();
    }

    public ArrayList<Tile> getNeighbours(){
        return this.neighbours;
    }


    /*
     * Adds a Tile to the ArrayList neighbours-
     * 
     * @param t a Tile
     */
    public void addNeighbour(Tile t) {
        this.neighbours.add(t);
    }

    /**
     * @return the x
     */
    public int getX() {
        return x;
    }

    /**
     * @return the y
     */
    public int getY() {
        return y;
    }
}

共有1个答案

司空镜
2023-03-14

好吧,我想我找到了我的问题的解决方案。它远非完美,需要大量优化,也许你们中的一个人想这样做并将其发布在这里^^。

我的主要错误是没有在每次递归调用方法后添加返回,这导致了一个死循环。

这是我的解决方案:

public void depthFirstSearch(int x, int y, Tile[][] maze) {
    // Return method after every Tile is visited.
    if (this.visitedCounter == maze.length * maze[0].length) {
        this.stack.clear();
        return;
    }

    Tile currentTile = maze[x][y];
    Random r = new Random();
    int neighbourAmount = currentTile.getNeighbourAmount();
    boolean allNeighboursVisited = false;
    int stopCounter = 0;

    // If it is a new Tile, mark it as visited
    if (!currentTile.isVisited()) {
        currentTile.setVisited(true);
        this.visitedCounter++;
        stack.add(currentTile);
    }

    // Check if neighbours are not yet visited and "visit" one of them.
    while (!allNeighboursVisited) {
        int random;
        do {
            random = r.nextInt(neighbourAmount);
        } while (this.excludeList.contains(random));

        Tile neighbour = currentTile.getNeighbours().get(random);
        if (!neighbour.isVisited()) {
            if (neighbour.getX() == currentTile.getX() - 1) {
                currentTile.getWall(4).setOpen(true);
                neighbour.getWall(2).setOpen(true);
            } else if (neighbour.getX() == currentTile.getX() + 1) {
                currentTile.getWall(2).setOpen(true);
                neighbour.getWall(4).setOpen(true);
            } else if (neighbour.getY() == currentTile.getY() - 1) {
                currentTile.getWall(1).setOpen(true);
                neighbour.getWall(3).setOpen(true);
            } else if (neighbour.getY() == currentTile.getY() + 1) {
                currentTile.getWall(3).setOpen(true);
                neighbour.getWall(1).setOpen(true);
            }
            this.excludeList.clear();
            depthFirstSearch(neighbour.getX(), neighbour.getY(), maze);
            return;
        } else {
            this.excludeList.add(random);
            stopCounter++;
        }

        if (stopCounter == neighbourAmount) {
            allNeighboursVisited = true;
        }
    }

    // If every neighbour has already been visited, go back one Tile.
    if (!this.stack.isEmpty()) {
        this.stack.remove(this.stack.size() - 1);
        if (!this.stack.isEmpty()) {
            Tile backtrackTile = this.stack.get(this.stack.size() - 1);
            this.excludeList.clear();
            depthFirstSearch(backtrackTile.getX(), backtrackTile.getY(), maze);
            return;
        }
        this.excludeList.clear();
    }
}
 类似资料:
  • 问题内容: 我正在尝试更新服务器上的用户位置 使用此功能 这是代表 我有Optional(“”)和和变量,不能摆脱它。 任何想法如何做到这一点? 问题答案: 如果您像这样解开纬度和经度值… …然后您可以在函数中完全避免使用可选: 没错…除非您有充分理由强制拆开它们,否则应该养成安全地解开可选内容的习惯。而且,仅尝试摆脱可选内容以使代码可以编译并不是一个很好的理由。

  • 我有一个字符串数组列表,希望将所有可能的组合存储到另一个集合中。 例如: 重复并不重要。我现在拥有的代码是: 我正在尝试让它递归调用自己,以便它可以存储组合。我可以得到任何关于代码中缺少的位置或哪个部分的帮助吗?

  • 问题内容: 我正在使用express在nodejs上运行服务器。我似乎无法摆脱标题: 我想知道是否有任何方法可以摆脱此标头,还是我必须忍受它? 问题答案: 在Express> = 3.0.0rc5中: 这是一个简单的中间件,可以删除早期版本的Express中的标头:

  • 我有JavaWebService代码在我的eclipse。我使用了@WebService@Webmethod,@XmlElements,@XmlType,@XmlAccessorType 现在我正在使用cxf框架中的java2ws命令生成wsdl。这是命令 我的wsdl文件包含agr0作为我不想要的名称,因为当我将其导入SoapUI时。它正在字段周围添加标记。 下面是带有arg0的wsdl部分 下

  • 问题内容: 我在使用Java中的基本递归问题时遇到了很多麻烦;任何指针都很棒。 “写一种静态递归方法来打印出几何序列的第n个项:2、6、18、54。” 据我所知,我应该在代码中的某处递归地将某物乘以3,但我一直在努力寻找方法。我知道我需要终止声明,但是何时发生?我需要帮手方法吗? 问题答案: 一个递归函数是一个函数,它的实现引用自身。以下是一些有趣的示例: 解决问题的方法: 编辑 : 上面的类使用

  • 问题内容: 我正在使用Apache Derby嵌入式数据库在Maven项目中进行单元测试。不幸的是,每当运行测试时,我最终都会在项目根目录中找到该文件。数据库本身是在目录()中创建的,因此这不是问题。在查阅参考指南之后, 我尝试在JDBC url()上设置参数,但这似乎是针对其他日志的,因此仍然会出现。 任何帮助深表感谢。 问题答案: 您可以通过创建以下类来摆脱文件 并设置JVM系统属性,例如,使