Визуализация Grid DFS

Привет, ребята, я работаю над проектом, в котором пытаюсь создать генератор лабиринта.
Пока у меня есть сетка, которая представляет собой 2D-массив класса Cell и JPanel, который рисует сетку в JFrame и функцию, которая использует поиск по глубине для посещения каждой ячейки в сетке. Когда ячейка была посещена, цвет ячейки меняется на черный на сетке.
Моя проблема в том, что перерисовка сетки выполняется слишком быстро. В любом случае я могу замедлить время или установить таймер для перерисовки через несколько секунд. Вот код ниже

import java.util.Arrays;
import java.util.Stack;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.security.SecureRandom;

public class Maze extends JPanel implements ActionListener {
    private Cell [][] maze;
    private int dims;
    private Stack<Cell> S = new Stack<Cell>();
    private SecureRandom num = new SecureRandom();
    Timer t;

    public Maze(int din)
    {
        dims = din;
        maze = new Cell[dims][dims];        
    }

    public void generator()
    {
        for(int i = 0; i < maze.length; i++)
        {
            for (int j = 0;j < maze[0].length; j++)
            {
                maze[i][j] = new Cell(i,j);
            }
        }
    }

    public boolean checkAll()
    {
        for(int i = 0; i < maze.length; i++)
        {
            for (int j = 0;j < maze[0].length; j++)
            {
                if (!maze[i][j].visited)
                    return false;
            }
        }
        return true;
    }

    public void adjlist()
    {
        for(int i = 0; i < maze.length; i++)
        {
            for (int j = 0;j < maze[0].length; j++)
            {
                if (i+1 >= 0 && i+1 < dims)
            {
                maze[i][j].neighbor.add(maze[i+1][j]);

            }
            if (i-1 >= 0 && i-1 < dims)
            {
                maze[i][j].neighbor.add(maze[i-1][j]);          
            }
            if (j-1 >= 0 && j-1 < dims)
            {
                maze[i][j].neighbor.add(maze[i][j-1]);          
            }
            if (j+1 >= 0 && j+1 < dims)
            {
                maze[i][j].neighbor.add(maze[i][j+1]);          
            }
            }
        }
    }

    public void DFS(Cell x)
    {
        if (!checkAll() && !maze[x.row][x.column].visited) 
        {
            S.push(x);
            System.out.println(Arrays.toString(S.toArray()));
            maze[x.row][x.column].visited = true;
            int randnum = num.nextInt(maze[x.row][x.column].neighbor.size());
            Cell temp1 = maze[x.row][x.column].neighbor.get(randnum);
            if (!maze[temp1.row][temp1.column].visited) 
            {
                DFS(maze[temp1.row][temp1.column]);
            } 
            else if (maze[x.row][x.column].neighbor.isEmpty()) 
            {
                S.pop();
                maze[S.peek().row][S.peek().column].visited = false;
                DFS(S.pop());
            } 

            else 
            {
                if (S.size()-1 == 0)
                    return;
                Cell temp = null;
                for (Cell c : maze[x.row][x.column].neighbor) 
                {
                    if (!maze[c.row][c.column].visited) 
                    {
                        temp = c;
                        DFS(temp);                  
                    }
                }
                if (temp == null) {
                    S.pop();
                    maze[S.peek().row][S.peek().column].visited = false;
                    DFS(S.pop());
                }
            }
        }
    }

    public void paint(Graphics g)
    {
        super.paint(g);
        for (int row = 0; row < maze.length; row++)
        {
            for (int col = 0; col < maze[0].length; col++)
            {
                g.drawRect(35*row, 35 * col , 35, 35);
                if (maze[row][col].visited)
                {
                    //t.start();
                    g.fillRect(35*row, 35 * col , 35, 35);
                    //t.setDelay(5000);                 
                }
            }
        }
        repaint();
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    }

    public static void main(String[] args)
    {
        Maze p = new Maze(10);
        p.generator();
        p.adjlist();
        System.out.println("------------------------");
        JFrame f = new JFrame();
        f.setTitle("Maze");
        f.add(p);
        f.setVisible(true);
        f.setSize(700, 700);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        p.DFS(new Cell(1,5));
    }


    @Override
    public void actionPerformed(ActionEvent e) {}

    }

Класс ячейки

import java.util.ArrayList;

public class Cell{
    public int row, column;
    boolean visited;
    ArrayList<Cell> neighbor;

    public Cell(int i, int j)
    {
        row = i;
        column = j;
        visited = false;
        neighbor = new ArrayList<Cell>();
    }

    public int getRow()
    {
        return this.row;
    }

    public int getCol()
    {
        return this.column;
    }

    public String toString()
    {
        return this.row + " " + this.column;
    } 
  }

Что не так с Thread.sleep(ms)?

Jim Garrison 10.06.2018 06:13

где именно я бы поставил, что я уже пробовал, но это ничего не изменило @JimGarrison

smith 10.06.2018 06:15

Очевидно, что либо указанное вами значение (в миллисекунды) слишком мало, либо вы поместили вызов sleep() не в то место. Покажи, что ты сделал. В опубликованном вами коде нет вызова sleep().

Jim Garrison 10.06.2018 06:16

эй, извините, я отредактировал это, я поставил Thread.sleep сразу после того, как перерисовка называется @JimGarrison

smith 10.06.2018 06:22

эй, я получил ответ, ты был прав, у меня была ветка не в том месте, спасибо @JimGarrison

smith 10.06.2018 06:41

Пожалуйста, возьмите тур и посмотрите Как мне задать хороший вопрос?. Для быстрой и эффективной помощи отправьте сообщение минимальный воспроизводимый пример. Ваш вопрос в основном сводится к добавлению задержки для замедления обновлений графического интерфейса Swing, поэтому вся информация о DFS не требуется.

c0der 10.06.2018 09:44
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
419
1

Ответы 1

Следующий код демонстрирует использование SwingWorker для демонстрации выполнения длинных задач (в вашем случае поиск dfs), которые обновляют графический интерфейс.
Конкретная информация о dfs была удалена, так как не имеет отношения к делу:

import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;

public class Maze extends JPanel {

    private final Cell [][] maze;
    private final int dims;
    private static final int SIZE = 35;

    public Maze(int dim) {
        setPreferredSize(new Dimension( dim*SIZE,dim*SIZE));
        dims = dim;
        maze = new Cell[dims][dims];
    }

    public void generator()
    {
        for(int i = 0; i < maze.length; i++)
        {
            for (int j = 0;j < maze[0].length; j++)
            {
                maze[i][j] = new Cell(i,j);
                //set some arbitrary initial date
                if (i%2 ==0 && j%2 ==0) {
                    maze[i][j].setVisited(true);
                }
            }
        }
    }

    public void DFS()
    {
        new DFSTask().execute();
    }

    @Override
    public void paintComponent(Graphics g) //override paintComponent not paint
    {
        super.paintComponent(g);
        for (int row = 0; row < maze.length; row++)
        {
            for (int col = 0; col < maze[0].length; col++)
            {
                g.drawRect(SIZE*row, SIZE * col , SIZE, SIZE);
                if (maze[row][col].visited)
                {
                    g.fillRect(SIZE*row, SIZE * col , SIZE, SIZE);
                }
            }
        }
    }

    public static void main(String[] args)
    {
        Maze p = new Maze(10);
        p.generator();
        JFrame f = new JFrame();
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(p);
        f.pack();
        f.setVisible(true);
        p.DFS();
    }

    //use swing worker perform long task
    class DFSTask extends SwingWorker<Void,Void> {

        private static final long DELAY = 1000;
        private final Random rand = new Random();

        @Override
        public Void doInBackground() {
            dfs();
            return null;
        }

        @Override
        public void done() { }

        void dfs() { //simulates long process that repeatedly updates gui

            while (true){ //endless loop, just for demonstration
                //update info
                int row = rand.nextInt(dims);
                int col = rand.nextInt(dims);
                maze[row][col].setVisited(! maze[row][col].isVisited());
                repaint(); //update jpanel
                try {
                    Thread.sleep(DELAY); //simulate long process
                } catch (InterruptedException ex) { ex.printStackTrace();}
            }
        }
    }
}

class Cell{

    private final int row, column;
    boolean visited;

    public Cell(int i, int j)
    {
        row = i;
        column = j;
        visited = false;
    }

    int getRow() {  return row; }

    int getColumn() {return column; }

    boolean isVisited() { return visited; }

    void setVisited(boolean visited) {  this.visited = visited;}

    @Override
    public String toString()
    {
        return row + " " + column;
    }
}

Для получения дополнительной информации об использовании SwingWorker см. док


Другие вопросы по теме