如何使用递归迷宫生成器绘制每一步?

时间:2017-11-26 00:53:30

标签: java swing recursion paintcomponent

我写了一个程序,递归地创建一个迷宫,但是在每一步之后都无法弄清楚如何让它画出迷宫。迷宫的任何更改都会在下一次递归调用之前发生。迷宫被预渲染到JPanel上作为方格网格,我试图让程序渲染每一步,在下一次递归调用之前使用JPanel.repaint(我在{{1}中有评论我之前尝试重新绘制的方法。无论我尝试什么,迷宫只是简单地在最后一次渲染完成的产品(迷宫中包含所有路径,墙壁等)。附件是我的递归{{ 1}}方法。

generate

使用generate类中保存的信息,将每个单元格单独渲染到private static boolean generate(int x, int y) { System.out.println("xcord: " + x + ", ycord: " + y); //panel.repaint(); when i have repaint here, it renders the entire maze at the end a[x][y].visited = true; if (unvisitedCells == 0) { // if you have visited all of the cells, maze is done generating System.out.println("done"); return true; } int movesTried = 0; // keeps track of which directions have been tried int currentMove = (int) (Math.random() * 4); // try moving a random direction first (0 = north, 1 = east, etc.) while (movesTried < 4) { // continue as long as all four moves havent been tried // north move if (a[x][y].northCell != null && a[x][y].northCell.visited != true && currentMove == 0) { a[x][y].northCell.visited = true; a[x][y].northWall = false; a[x][y].northCell.southWall = false; unvisitedCells -= 1; // tried repainting here, but had no effect if (generate(x, y - 1)) { return true; // move successful } } // east move if (a[x][y].eastCell != null && a[x][y].eastCell.visited != true && currentMove == 1) { a[x][y].eastCell.visited = true; a[x][y].eastWall = false; a[x][y].eastCell.westWall = false; unvisitedCells -= 1; // tried repainting here, but had no effect if (generate(x + 1, y)) { return true; // move successful } } // south move if (a[x][y].southCell != null && a[x][y].southCell.visited != true && currentMove == 2) { a[x][y].southCell.visited = true; a[x][y].southWall = false; a[x][y].southCell.northWall = false; unvisitedCells -= 1; // tried repainting here, but had no effect if (generate(x, y + 1)) { return true; // move successful } } // west move if (a[x][y].westCell != null && a[x][y].westCell.visited != true && currentMove == 3) { a[x][y].westCell.visited = true; a[x][y].westWall = false; a[x][y].westCell.eastWall = false; unvisitedCells -= 1; // tried repainting here, but had no effect if (generate(x - 1, y)) { return true; // move successful } } movesTried++; // another move has been tried if (currentMove == 3 && movesTried < 4) { currentMove = 0; // wraps back to north move if maze started at a move greater than 0, and you // have more moves to try } else { currentMove++; } } // at this point, all 4 moves have been tried, and there are no possible moves // from the current maze cell return false; } 上。

JPanel

在这里,我设置了一个MazeCell,根据4个方向中是否有一个墙,单独绘制每个单元格。

public class MazeCell {

public boolean northWall = true;
public boolean eastWall = true;
public boolean southWall = true;
public boolean westWall = true;

public MazeCell northCell = null;
public MazeCell eastCell = null;
public MazeCell southCell = null;
public MazeCell westCell = null;

public boolean visited = false;

}

1 个答案:

答案 0 :(得分:3)

使用SwingWorker扭曲长进程(generate(int x, int y)),并让它更新GUI。这是一个例子:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;

public class RecursiveGuiUpdate extends JFrame {

    private final int SIZE = 4;
    JLabel[][] grid = new JLabel[SIZE][SIZE];

    RecursiveGuiUpdate()    {

        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        add(getGrid(), BorderLayout.NORTH);
        JButton paint = new JButton("Paint");
        paint.addActionListener(a -> updateGui());
        add(paint, BorderLayout.SOUTH);
        pack();
        setVisible(true);
    }

    private void updateGui() {
        new Task().execute();
    }

    private Component getGrid() {
        JPanel panel = new JPanel(new GridLayout(SIZE, SIZE));
        for(int i=0; i<=(SIZE-1); i++) {
            for(int j=0; j<=(SIZE-1); j++) {
                JLabel l = new JLabel(i+"-"+j, JLabel.CENTER);
                l.setOpaque(true);
                panel.add(l);
                grid[i][j] = l;
            }
        }
        return panel;
    }

    class Task extends SwingWorker<Void,Void> {

        @Override
        public Void doInBackground() {
            updateGui(0, 0);
            return null;
        }

        @Override
        public void done() { }

        //recursively set labels background
        void updateGui(int i, int j) {

            System.out.println(i+"-"+j);
            //set random, background color
            grid[i][j].setBackground(new Color((int)(Math.random() * 0x1000000)));

            try {
                Thread.sleep(500); //simulate long process
            } catch (InterruptedException ex) { ex.printStackTrace();}

            if((i==(SIZE-1))&&(j==(SIZE-1))) { return; }

            if(i<(SIZE-1)) {
                updateGui(++i, j);
            }else {
                i=0;
                updateGui(i, ++j);
            }
        }
    }

    public static void main(String[] args)  {
        new RecursiveGuiUpdate();
    }
}

如果需要,您可以覆盖process(java.util.List)以获取和处理期中结果 如果您需要有关此类解决方案的帮助,请使用mcve发布另一个问题。