简体   繁体   中英

How to update Maze grid of labels to show path taken by Solver (highlight the path taken)

Me and a partner were assigned a project where we had to create a GUI that implements a grid of JLabels that can be clicked to create the walls of a maze, and implement a solver class to solve said maze via the click of a solve button. We have the solver and GUI working together, but what we've been having trouble with has been trying to update the GUI after it has been solved. We know its solving the maze correctly because we have it printing an array of the solution but can't for the life of us figure out how to update the GUI to highlight the path of the solver the solve button is clicked. Is there any way to do that?

Solver class:

package lab8;

import java.util.ArrayList;

public class Solver implements MazeSolver {

    private static ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();

    public Solver() {

    }

    @Override
    public String[][] solve(String[][] map) {

        String[][] str =

        new String[map.length][map[0].length];

        boolean done = false;

        for (int row = 0; row < map.length; row++) {

            for (int col = 0; col < map[0].length; col++) {

                str[row][col] = map[row][col];

            }

        }

        Coordinate c1 = findStart(str);

        Coordinate c2 = findFinish(str);

        int x = 0;

        while (done == false) {

            if ((c1.getRow() + 1 == c2.getRow()) && c1.getCol() == c2.getCol()) {
                str[c2.getRow()][c2.getCol()] = "RIP";
                break;

            }

            if (isClear(str, c1.getRow() + 1, c1.getCol())) {

                str[c1.getRow() + 1][c1.getCol()] = "X";
                c1 = new Coordinate(c1.getRow() + 1, c1.getCol());
                coordinates.add(c1);
            } else if (isClear(str, c1.getRow(), c1.getCol() + 1)) {
                str[c1.getRow()][c1.getCol() + 1] = "X";
                c1 = new Coordinate(c1.getRow(), c1.getCol() + 1);
                coordinates.add(c1);
            } else if (isClear(str, c1.getRow(), c1.getCol() - 1)) {
                str[c1.getRow()][c1.getCol() - 1] = "X";
                c1 = new Coordinate(c1.getRow(), c1.getCol() - 1);
                coordinates.add(c1);
            } else if (isClear(str, c1.getRow() - 1, c1.getCol())) {
                str[c1.getRow() - 1][c1.getCol()] = "X";
                c1 = new Coordinate(c1.getRow() - 1, c1.getCol());
                coordinates.add(c1);
            }
            if ((str[c1.getRow() - 1][c1.getCol()].equals("X")
                    || str[c1.getRow() - 1][c1.getCol()].equals("W") || str[c1
                    .getRow() - 1][c1.getCol()].equals("D"))
                    && (str[c1.getRow() + 1][c1.getCol()].equals("X")
                            || str[c1.getRow() + 1][c1.getCol()].equals("W") || str[c1
                            .getRow() + 1][c1.getCol()].equals("D"))
                    && (str[c1.getRow()][c1.getCol() - 1].equals("X")
                            || str[c1.getRow()][c1.getCol() - 1].equals("W") || str[c1
                                .getRow()][c1.getCol() - 1].equals("D"))
                    && (str[c1.getRow()][c1.getCol() + 1].equals("X")
                            || str[c1.getRow()][c1.getCol() + 1].equals("W") || str[c1
                                .getRow()][c1.getCol() + 1].equals("D"))) {

                str[c1.getRow()][c1.getCol()] = "D";
                coordinates.remove(coordinates.size() - 1);
                c1 = coordinates.get(coordinates.size() - 1);
            }
            x++;
            if(x >= 300) {
                c1 = findStart(map);
                break;
            }
        }
        return str;
    }

    public Coordinate findStart(String[][] map) {
        Coordinate start = new Coordinate(0, 0);
        for (int row = 0; row < map.length; row++) {
            for (int col = 0; col < map[0].length; col++) {
                if (map[row][col].equals("S")) {
                    start = new Coordinate(row, col);
                }
            }
        }
        return start;
    }

    public Coordinate findFinish(String[][] map) {
        Coordinate finish = new Coordinate(0, 0);
        for (int row = 0; row < map.length; row++) {
            for (int col = 0; col < map[0].length; col++) {
                if (map[row][col].equals("F")) {
                    finish = new Coordinate(row, col);
                }
            }
        }
        return finish;
    }

    public boolean isClear(String[][] map, int x, int y) {
        if (x >= map.length) {
            return false;
        }
        if (x >= map[0].length) {
            return false;
        }
        if (map[x][y].equals("S")) {
            return false;
        }
        if (map[x][y].equals("D")) {
            return false;
        }
        if (map[x][y].equals("W")) {
            return false;
        }
        return true;
    }

    public static void main(String[] args) {
        Solver s1 = new Solver();

        String[][] map = {
                { "W", "S", "W", "W", "W", "W", "W", "W", "W", "" , "W"},
                { "W", "", "W", "", "", "", "", "", "", "" , "W"},
                { "W", "", "W", "", "W", "W", "W", "W", "", "", "W" },
                { "W", "", "W", "", "W", "", "W", "W", "", "" , "W"},
                { "W", "", "W", "", "W", "W", "", "W", "", "", "W" },
                { "W", "", "W", "", "W", "", "", "W", "", "" , "W"},
                { "W", "", "W", "", "", "", "W", "W", "", "" , "W"},
                { "W", "", "W", "", "W", "W", "W", "W", "", "" , "W"},
                { "W", "", "", "", "W", "", "", "", "", "" , "W"},
                { "W", "W", "W", "W", "W", "W", "W", "W", "W", "F" , "W"} };
        for (int i = 0; i < s1.solve(map).length; i++) {
            for (int j = 0; j < s1.solve(map)[0].length; j++) {
                System.out.printf("%3s", s1.solve(map)[i][j]);
            }
            System.out.println();
        }
    }
}

Coordinate Class

    package lab8;

public class Coordinate {

    private int row;
    private int col;

    public Coordinate(int row, int col) {
        this.row = row;
        this.col = col;
    }

    public int getRow() {
        return row;
    }

    public int getCol() {
        return col;
    }
     public String toString() {
            return "Coordinate [row=" + row + ", col=" + col + "]";
        }

}

Partner's GUI class

    package lab8;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

 import javax.swing.*;

public class MazeGUI {
    String[][] map = new String[12][12];
    JPanel labelPanel,startPanel;
    JLabel labs;


    private void createMaze() {
        // creates the maze
        JFrame frame = new JFrame("Zombie Run");
         frame.setLayout(new BorderLayout());
        final JPanel labelPanel = new JPanel();
        labelPanel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
        labelPanel.setLayout(new GridLayout(12, 12));

        for (int row = 0; row < 12; row++) {
            for (int cols = 0; cols < 12; cols++) {
                final int i = row;
                final int j = cols;
                final JLabel labs = new JLabel();

                // create and set the labels
                labs.setSize(new Dimension(50, 50));
                labs.setBorder(BorderFactory.createLineBorder(Color.blue));

                labs.setBackground(Color.black);
                map[row][cols]="";


                mapArray(row, cols, labs);
                labs.addMouseListener(new MouseListener() {
                    boolean clicked = false;

                    @Override
                    public void mouseClicked(MouseEvent arg0) {
                         // the color changes when clicked

                        if (clicked == true) {
                            clicked = false;
                            labs.setBackground(Color.black);
                             map[i][j] = "";

                        }
                        else {
                            clicked = true;
                            labs.setBackground(Color.cyan);
                             map[i][j] = "W";

                        }

                    }

                    @Override
                    public void mouseEntered(MouseEvent e) {
                         // TODO Auto-generated method stub

                    }

                    @Override
                    public void mouseExited(MouseEvent e) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void mousePressed(MouseEvent e) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void mouseReleased(MouseEvent e) {
                        // TODO Auto-generated method stub

                    }
                });
                if(map[i][j].equals("X") || map[i][j].equals("D")){
                    labs.setBackground(Color.RED);
                }

                if(row==0 || row==11){
                     labs.setBackground(Color.cyan);
                    map[row][cols]="W";
                }

                if(cols==0 || cols==11){
                    labs.setBackground(Color.cyan);
                   map[row][cols]="W";
               }

                if(row==0 && cols==1){
                    labs.setBackground(Color.black);
                     map[row][cols]="S";
                }
                if(row==11 && cols==10){
                    labs.setBackground(Color.black);
                    map[row][cols]="F";
                 }
                labs.setOpaque(true);
                labelPanel.add(labs);

            }

        }

        startPanel = new JPanel();
        JButton runMaze = new JButton("Feed the Zombie");
         runMaze.addActionListener(new ActionListener() {
            boolean clicked = false;

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // Makes the zombie find the brain
                 if (clicked == false) {
                    clicked = true;
                    Solver solver;
                    solver= new Solver();
                    solver.solve(map);
                    for(int i = 0; i < map.length; i++){
                        for(int j = 0; j < map[0].length; j++){
                            System.out.printf("%3s", solver.solve(map)[i][j]);
                        }
                        System.out.println();
                    }
                 }

            }
        });
        runMaze.setBackground(Color.green);
        startPanel.add(runMaze);
        runMaze.add(labelPanel);
        frame.add(labelPanel, BorderLayout.NORTH);
         frame.add(startPanel, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        for(int i = 0; i < map.length; i++){
            for(int j = 0; j < map[0].length; j++){
                System.out.printf("%3s", map[i][j]);
            }
            System.out.println();
        }
    }

    private void mapArray(int row, int cols, JLabel labs) {
         // checks the space and inserts string

        if (row == 0 || row == 11) {
            map[row][cols] = "W";
            map[row][cols] = "W";
        }
        if (cols == 0 || cols == 11) {
             map[row][cols] = "W";
            map[row][cols] = "W";
        }
        if (row == 0 && cols == 1) {
            map[0][1] = "S";
            labs.setText("Start");
         }
        if (row == 11 && cols == 10) {
            map[row][10] = "F";
            labs.setText("End");
        } else {
            map[row][cols] = "";
        }        
     }

    public static void main(String[] args) {
        // runs the program
        MazeGUI c = new MazeGUI();
        c.createMaze();
    }
};

A simple and straightforward approach would be to store the labels in the same way as the maze itself - namely, as an instance variable (an array of labels, in this case).

Roughly like this:

public class MazeGUI {
    String[][] map = new String[12][12];
    JLabel[][] labels = new JLabel[12][12]; // -----------  Add this
    ...

    private void createMaze() {
        ...
        for (int row = 0; row < 12; row++) {
            for (int cols = 0; cols < 12; cols++) {
                final int i = row;
                final int j = cols;
                final JLabel labs = new JLabel();

                labels[row][cols] = labs; // ----------- Store it here
                ...
            }
            ...
        }
        ...
    }

    // After the solution has been found, apply it to the labels roughly (!) like this:
    private void applySolutionToLabels(String solution[][]) {
        for (int row = 0; row < 12; row++) {
            for (int cols = 0; cols < 12; cols++) {
                labels[row][cols].setText(solution[rows][cols]); 
            }
        }
    }

But note that there are some issues with your code. (That's the polite form of "It's a mess")

  • The GUI should be created from the event dispatch thread
  • You should avoid fixed-size arrays and all the size constants. What if you want to change the size of the maze from 12x12 to 13x13? Imagine how many places you have to change right now. You should at least (!) create two variables int mazeSizeX=12 and int mazeSizeY=12 and use them everywhere instead of the constant 12 , so that you can change this easily later
  • You could extend MouseAdapter instead of implementing MouseListener . Then you won't need all the empty methods
  • You should avoid a large nesting depth and "inlined" anonymous inner classes with lots of (deeply nested) code in them. Consider extracting some of this code into methods
  • The coordinates list should not be static. Instead, use a private List<Coordinate> coordinates = ...
  • Some further (minor) simplifications of the if -statements, but one would have to understand what they are doing in order to give profound suggestsions

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM