如何对自己进行递归回溯?

时间:2018-04-24 15:41:49

标签: java user-interface recursion maze

我遇到了问题,而且我不确定它是否基于递归。我创建了一个自我解决的GUI迷宫,但是光标跳过任何递归传播的方块而不是重新移动方块。虽然它最终找到了目标,但我想展示它的整个路径,但我无法阻止诅咒跳转。

我使用Runnable实时跟踪迷宫,所以我可以看到它反弹但没有递归 - 保持绑定,递归功能停止工作(它只是来回反弹,再次,我不太明白。)我大约三个月前在一个加速程序中启动了java,所以我不确定这个问题是我对递归的理解,还是对方法的简单补充,或者我是不是#39;我必须重写大部分代码。

我包含了整个代码以防万一,但实际上它是旅行方法或访问方法中的一个问题。答案是写一个全新的方法,重新传播已经改变的#34;访问过的"串迷宫?我一直在努力解决这个问题,我只需要一些方向来回答。

import java.awt.*;
import javax.swing.*;

class extraCreditMaze extends JPanel implements Runnable {        //uses Runnable to execute jPanel

   private String [][] ratMaze =                         //string maze
   {{"blocked","blocked","blocked","blocked","blocked","blocked","blocked","blocked"},
    {"blocked","open","blocked","blocked","blocked","blocked","blocked","blocked"},
    {"blocked","open","open","open","open","open","open","blocked"},
    {"blocked","blocked","open","blocked","open","blocked","open","blocked"},
    {"blocked","blocked","open","blocked","open","blocked","open","goal"},
    {"blocked","open","open","open","blocked","open","open","blocked"},
    {"blocked","blocked","blocked","open","open","open","blocked","blocked"},
    {"blocked","blocked","blocked","blocked","blocked","blocked","blocked","blocked"}};

   final private int SquareSize = 15;
   final private int BoardSize = 17;
   private boolean free = false;
   int axisX = 1, axisY = 1;

   public void paintComponent(Graphics color)            //paint components for char
   {
      super.paintComponent(color);
        for(int row = 0;  row < ratMaze.length; row++)
      {
         for(int col = 0; col< ratMaze.length; col++)
         {
            if(row==axisX && col==axisY)                 //traveling curser = blue
            {
               color.setColor(Color.blue);
               color.fillOval(col*15,row*15,15,15);
                }
            else if(ratMaze[row][col]=="blocked")              //empty = black
            {
               color.setColor(Color.black);
               color.fillRect(col*SquareSize,row*SquareSize,BoardSize,BoardSize);
            }
           else if(ratMaze[row][col]=="goal")
            {
               color.setColor(Color.red);               //goal = red
               color.fillOval(col*15,row*15,15,15);
            }
            else if(ratMaze[row][col]=="visited")
            {
               color.setColor(Color.green);              //path traveled = green
               color.fillOval(col*15,row*15,15,15);
            }
            else
            {
                color.setColor(Color.white);              //empty space = white
                color.fillRect(col*SquareSize,row*SquareSize,BoardSize,BoardSize);
            }
        }
      }
   }

   public void run ()                                    //starts run at (1,1)
   {
      travel(1,1);
   }

   public boolean goal(int x, int y){                    //method to check goal (true/false)
        if(ratMaze[x][y]=="goal")
            return true;
        else 
            return false;
   }

   public void changedVisited(int x, int y)              //method to change traveled
   {
            ratMaze[x][y] = "visited";
            axisX = x;
            axisY = y;
   }

   public boolean boundaries(int x, int y)               //check boundaries
   {
        if(ratMaze[x][y]=="blocked")
            return true;
        else 
            return false;
   }

   public boolean visited(int x, int y)                  //check if visited
   {
        if(ratMaze[x][y]=="visited")
                return true;
            else 
                return false;
   }

   private void travel(int x, int y)
   {
      if(boundaries(x,y))                                //makes sure it's within bounds
         return;

      if(visited(x,y))                                   //makes sure it hasn't already been visited
         return;

      if(goal(x,y))                                      //checks if it's the goal/changes boolean
      {
         free = true;
        JOptionPane.showMessageDialog(this, "You did it, Dr. Cui!");      //fun message!
      }

      if(!free)                                           //all recursion functions if free=false
      {
        changedVisited(x,y);                             //changes traveled block to "visited"
        repaint();                                       //repaints visited
        try {Thread.sleep(300); } catch (Exception e) { }//slows down the traveling curser
                                                          //I do not understand catch (Exception e)

            travel(x-1,y);                                 //recursive travel functions
            travel(x+1,y);
            travel(x,y-1);
            travel(x,y+1);
        }       
   }
}

public class runExtraCreditMaze {
   public static void main (String [] args) {       //JFrame panel and perimeters
      JFrame output = new JFrame();
      output.setSize(115, 150);
      output.setTitle("The Rat Maze");
      output.setLocationRelativeTo(null);
      extraCreditMaze Maze = new extraCreditMaze();
      output.setContentPane(Maze);
      output.setVisible(true);

      Thread runnable = new Thread(Maze);           //Creates Runnable thread for Maze object
      runnable.start();                             //Starts Runnable thread of Maze object
   }
}

1 个答案:

答案 0 :(得分:1)

问题是,正如你用“访问过”写的那样。当没有有效的移动且你没有进入目标时,你错过了一个关于该做什么的决策树。你需要让你的老鼠回溯自己。从无效移动返回时,您可能需要“释放”访问过的单元格。 我到IDE时会尝试添加一些代码示例:)

更新:写得非常糟糕,而且有点滞后。但它应该工作。它需要一些清理和验证...我重用你的布尔变量,这是坏的.. :)并切换真/假。我明天会做一些清理只是为了留下一个更好的答案,但我想你会设法理解发生了什么。

update2:我已经清理了一下。这里的重要课程如下:

1)当所有4个步骤都失败时,需要进行回溯。当你的老鼠无处可去时,你需要从最短路径取消细胞(ratMaze [x] [y] =“open”)) 2)当您从递归呼叫返回时,但在继续下一步之前,您需要改变老鼠的位置。您还需要让程序知道您从递归返回(因此isBacktracking)

private void repaintMaze(int x, int y) {
  changedVisited(x, y); //changes traveled block to "visited"
  repaint(); //repaints visited
  isBacktracking = false;
  try {
      Thread.sleep(500);
  } catch (Exception e) {
  }
}

private boolean travel(int x, int y) {
  if (goal(x, y)) //checks if it's the goal/changes boolean
  {
      JOptionPane.showMessageDialog(this, "You did it, Dr. Cui!");//fun message!
      return true;
  }

  if (boundaries(x, y) || visited(x, y))  //makes sure it's within bounds
        return false;

  repaintMaze(x, y);
  boolean result; //recursive travel functions
  result = travel(x - 1, y);
  if (result) {
      return true;
  }
  if (isBacktracking) {
      repaintMaze(x, y);
  }
  result = travel(x + 1, y);
  if (result) {
      return true;
  }
  if (isBacktracking) {
      repaintMaze(x, y);
  }
  result = travel(x, y - 1);
  if (result) {
      return true;
  }
  if (isBacktracking) {
      repaintMaze(x, y);
  }
  result = travel(x, y + 1);
  if (result) {
      return true;
  }
  if (isBacktracking) {
      repaintMaze(x, y);
  }

  ratMaze[x][y] = "open";
  isBacktracking = true;
  return false;
}

你还应该在你的JFrame附近添加exit :)它会在你点击窗口本身的X按钮后停止应用程序

output.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);