向Maze Solver java程序添加功能
我正在用java编写一个迷宫解算器程序,我在想如何添加某些功能时遇到了困难。现在我用它来处理我硬编码的2D字符数组 我需要可以:向Maze Solver java程序添加功能,java,Java,我正在用java编写一个迷宫解算器程序,我在想如何添加某些功能时遇到了困难。现在我用它来处理我硬编码的2D字符数组 我需要可以: 从文本文件加载迷宫(用户可以选择),并将其放入2D字符数组中 启动迷宫(基本上是启动mazeap.java中solveMaze()方法的按钮) 一个滚动条,可以控制solveMaze方法中Thread.sleep()的值 以及一个文本字段,可以显示迷宫正在(或不正在)进行的操作(即“未加载迷宫”、“已加载迷宫”、“正在进行解决方案”、“找到完成点:”) 处理GUI的M
import java.awt.*;
import javax.swing.*;
public class MazeApp extends JPanel implements Runnable {
final private int cellSize = 20; // how big the cells/squares are
final private int rows = 25; // how many rows are in the array (need to be able to get this info from txt file)
final private int cols = 25; // how many columns are in the array (need to be able to get this info from txt file)
private boolean mazeSolved = false; // boolean to check if maze is solved
private boolean solutionExists = true;
private int startLocX, startLocY; // ints used for '@' start location
int cellLocX, cellLocY; // cell location that moves through the maze
// private char[][] easyMaze = {
// {'#','#', '#', '#', '#'},
// {'#','@', '.', '.', '#'},
// {'#','#', '#', '.', '#'},
// {'#','.', '.', '.', '#'},
// {'#','#', '#', '#', '#'},
// {'-','-', '-', '-', '-'},
// {'#','#', '#', '#', '#'},
// {'#','=', '.', '.', '#'},
// {'#','#', '#', '.', '#'},
// {'#','*', '.', '.', '#'},
// {'#','#', '#', '#', '#'},
// };
//hard coded example 1 level maze with multiple finishes;
private char[][] easyMaze = {
{'#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#'},
{'#','.','#','.','.','.','#','.','.','.','.','.','.','.','#','.','.','.','.','.','.','.','.','.','#'},
{'#','.','#','.','#','.','#','.','#','#','.','#','.','#','#','.','#','#','.','#','#','#','#','.','#'},
{'#','.','#','.','#','.','#','.','#','#','.','#','.','#','#','.','#','.','.','.','.','#','#','.','#'},
{'#','.','.','.','#','.','#','.','#','#','.','#','.','#','#','.','#','.','#','.','.','#','#','.','#'},
{'#','.','#','.','#','.','#','.','.','.','.','#','.','#','#','.','#','.','#','.','.','#','#','.','#'},
{'#','.','#','.','#','.','#','.','#','#','.','#','.','#','#','.','.','.','.','.','.','.','.','.','#'},
{'#','.','#','.','#','.','#','.','#','#','.','#','.','.','.','.','#','.','#','#','#','#','.','.','#'},
{'#','.','.','.','#','.','.','.','#','#','.','#','.','#','#','.','#','.','#','.','#','.','.','.','#'},
{'#','.','#','#','#','#','#','#','#','#','.','#','.','#','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','#','.','.','.','#','.','.','.','.','#','.','#','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','#','.','#','.','#','.','#','#','#','#','.','#','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','#','.','#','.','#','.','#','#','#','#','.','#','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','.','.','#','.','.','.','#','.','.','.','.','#','#','.','.','.','.','.','.','.','.','.','#'},
{'#','#','#','#','#','#','.','#','#','#','#','#','#','#','#','.','#','.','#','#','#','.','#','.','#'},
{'#','.','.','.','.','.','.','.','.','.','#','#','#','#','#','.','#','.','.','.','#','.','#','.','#'},
{'#','.','#','.','#','#','#','#','#','#','#','#','#','#','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','#','.','.','.','.','.','.','.','.','.','.','.','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','#','.','#','#','#','#','#','#','#','#','#','.','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','#','.','#','.','.','.','.','.','.','.','.','.','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','#','.','#','.','#','#','#','#','#','#','#','#','#','.','#','.','#','.','#','.','#','.','#'},
{'#','.','#','.','#','.','.','.','.','.','.','.','.','.','#','.','#','.','#','.','#','.','#','#','#'},
{'#','@','#','.','#','#','.','#','#','#','#','.','.','.','#','.','#','.','#','.','#','.','#','#','#'},
{'#','.','.','.','#','#','.','#','#','#','#','.','.','#','#','.','.','.','.','.','.','.','.','*','#'},
{'#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#','#'}
};
// goes through array and paints cells
public void paintComponent(Graphics myGrfx) {
super.paintComponent(myGrfx);
//for loop to paint the rows
for(int i = 0; i < rows; i++){
//for loop to paint the cols
for(int j = 0; j < cols; j++) {
if (i == cellLocX && j == cellLocY) {
myGrfx.setColor(Color.GREEN);
myGrfx.fillRect(j * cellSize, i * cellSize, cellSize, cellSize);
} else if (easyMaze[i][j] == '#') {
myGrfx.setColor(Color.BLACK);
myGrfx.fillRect(j * cellSize, i * cellSize, cellSize, cellSize);
} else if (easyMaze[i][j] == '*') {
myGrfx.setColor(Color.RED);
myGrfx.fillRect(j * cellSize, i * cellSize, cellSize, cellSize);
} else if (easyMaze[i][j] == '.') {
myGrfx.setColor(Color.WHITE);
myGrfx.fillRect(j * cellSize, i * cellSize, cellSize, cellSize);
} else if (easyMaze[i][j] == 'x') {
myGrfx.setColor(Color.LIGHT_GRAY);
myGrfx.fillRect(j * cellSize, i * cellSize, cellSize, cellSize);
} else if (easyMaze[i][j] == '=') {
myGrfx.setColor(Color.BLUE);
myGrfx.fillRect(j * cellSize, i * cellSize, cellSize, cellSize);
}
}
}
}
// goes through the array to find '@', starts start locations points at i and j
public void getStartPosition() {
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++) {
if (easyMaze[i][j] == '@') {
startLocX = i;
startLocY = j;
}
}
}
}
public void getStairsPosition() {
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++) {
if (easyMaze[i][j] == '=') {
startLocX = i;
startLocY = j;
}
}
}
}
// marks visited paths with an 'x', shaded light gray
public void markPath(int locX, int locY){
easyMaze[locX][locY] = 'x';
cellLocX = locX;
cellLocY = locY;
}
// method you have to use for threads, need to replace with timer stuff
public void run() {
getStartPosition();
solveMaze(startLocX, startLocY);
}
// checks to see if the maze has found an exit
public boolean isFinished(int locX, int locY) {
if (easyMaze[locX][locY] == '*') {
return true;
} else {
return false;
}
}
// boolean that checks for walls
public boolean outOfBounds(int locX, int locY) {
if (easyMaze[locX][locY] == '#') {
return true;
} else {
return false;
}
}
// boolean to check if a cell has been visited
public boolean haveVisited(int locX, int locY) {
if (easyMaze[locX][locY] == 'x') {
return true;
} else {
return false;
}
}
public void noSolution() {
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++) {
if (easyMaze[i][j] == '#' || easyMaze[i][j] == 'x') {
solutionExists = false;
}
}
}
}
// method that calls itself and checks for finish, walls, or already visited paths
private void solveMaze(int locX, int locY) {
if (isFinished(locX, locY)) {
mazeSolved = true;
JOptionPane.showMessageDialog(this, "Yay, we found the finish!");
System.exit(0);
}
if (outOfBounds(locX, locY)) {
return;
}
if (haveVisited(locX, locY)) {
return;
}
if (!mazeSolved) {
markPath(locX, locY);
repaint();
try {Thread.sleep(50); } catch (Exception e) { }
solveMaze(locX, locY+1); // move right
solveMaze(locX + 1,locY); // move down
solveMaze(locX - 1, locY); // move up
solveMaze(locX, locY - 1); // move left
}
} // end solveMaze
} // end class
将以下代码添加到
MazeApp
应该可以做到这一点:
private static final int initialSpeed = 50;
private static final int paddingTop = 30;
private static final int paddingLeft = 30;
private JButton loadMazeBtn = new JButton("Load Maze");
private JButton runMazeBtn = new JButton("Run Maze");
private JScrollBar speedBar = new JScrollBar(JScrollBar.HORIZONTAL);
private JLabel statusLabel = new JLabel("Starting up...");
private void add(JComponent component, int x, int y) {
add(component);
component.setLocation(x, y);
component.setSize(component.getPreferredSize());
}
public MazeApp() {
setLayout(null);
int x = cols * cellSize + paddingLeft;
int y = paddingTop;
add(loadMazeBtn, x, y);
add(runMazeBtn, x, y + 40);
add(speedBar, x, y + 80);
add(statusLabel, x, y + 120);
loadMazeBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Fill in your code to load the maze
}
});
runMazeBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Fill in your code to run the maze
}
});
speedBar.setValue(initialSpeed);
}
// Call this method when you want to change the status text
// (i.e. "no maze loaded", "maze loaded", "solution in progress", "found finish at this point: ")
public void setStatusText(String text) {
statusLabel.setText(text);
}
// Call this function to feed the Thread.sleep
public int getSpeed() {
return speedBar.getValue();
}
您只需填写“加载迷宫”和“运行代码”的代码,并在状态更改时添加对setStatusText
的调用
对于“速度栏”,将线程.sleep
中的代码solveMaze
更改为
Thread.sleep(getSpeed());
你必须更具体地说明你需要的帮助。假设您不希望有人编写代码来添加这些功能,那么您到底在哪里?非常感谢!我想不出如何按照我的设置方式添加JButtons。我遇到了迷宫响应开始按钮的问题。我将solveMaze(startocx,startocy)从run方法中取出,并将其放入start方法中。程序运行并将单元格放置在起始位置并解决迷宫问题,但一旦我点击“开始”,它实际上不会显示动画,也不会让我控制线程滚动。@user2275834这是因为按钮的actionPerformed方法中指定的代码在EventThread中执行。也就是说,您的例程
solveMaze
在EventThread中执行,从而阻塞它,直到迷宫被解决。这样系统就没有机会刷新屏幕,这通常是在EventThread中完成的。要解决此问题,请将solveMaze(startocx,startocy)
保持在run
例程中的原始位置。在开始按钮的actionPerformed
方法中,放入启动迷宫的MazeTest类中的代码(Thread myThread=new Thread(MazeApp.this);…
)
Thread.sleep(getSpeed());