我遇到了问题,而且我不确定它是否基于递归。我创建了一个自我解决的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
}
}
答案 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);