Advertisement
Adumb_Copper

MazeApp

Oct 9th, 2016
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.54 KB | None | 0 0
  1. /**
  2.  * The CSCI 151 Amazing Maze Solver GUI application.
  3.  *
  4.  * Students should not need to modify anything in this file.
  5.  *
  6.  * @author Benjamin Kuperman (Spring 2012)
  7.  *
  8.  */
  9.  
  10. import java.awt.BorderLayout;
  11. import java.awt.Color;
  12. import java.awt.FlowLayout;
  13. import java.awt.Font;
  14. import java.awt.GridLayout;
  15. import java.awt.event.ActionEvent;
  16. import java.awt.event.ActionListener;
  17. import java.io.File;
  18.  
  19. import javax.swing.BorderFactory;
  20. import javax.swing.JButton;
  21. import javax.swing.JFileChooser;
  22. import javax.swing.JFrame;
  23. import javax.swing.JLabel;
  24. import javax.swing.JOptionPane;
  25. import javax.swing.JPanel;
  26. import javax.swing.JScrollPane;
  27. import javax.swing.JTextArea;
  28. import javax.swing.JTextField;
  29. import javax.swing.Timer;
  30. import javax.swing.filechooser.FileFilter;
  31. import javax.swing.text.DefaultCaret;
  32.  
  33. public class MazeApp extends JFrame implements ActionListener {
  34.    
  35.     // Initial font size for the display
  36.     private static int fontSize = 16;
  37.  
  38.     // Initial interval between animation in milliseconds
  39.     private static int timerInterval = 1;
  40.    
  41.     private static final long serialVersionUID = 6228378229836664288L;
  42.  
  43.     // Fields for internal data representation
  44.     Maze maze;
  45.     MazeSolver solver;
  46.     boolean mazeLoaded;
  47.    
  48.     // Fields for GUI interface
  49.     JTextField filename;
  50.     JTextField timerField;
  51.     JTextField fontField;
  52.     JTextArea  mazeDisplay;
  53.     JTextArea  pathDisplay;
  54.     JButton    loadButton;
  55.     JButton    solveButton;
  56.     JButton    stepButton;
  57.     JButton    solverType;
  58.     JButton    resetButton;
  59.     JButton    quitButton;
  60.     Timer      timer;
  61.    
  62.    
  63.     /**
  64.      * Constructor -- does most of the work setting up the GUI.
  65.      */
  66.     public MazeApp() {
  67.     // Set up the frame
  68.     super("Amazing Maze Solver");
  69.     setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
  70.     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  71.    
  72.     // Field for the maze file name
  73.     filename = new JTextField(10);
  74.     filename.setEditable(false);
  75.     filename.setText("<no maze loaded>");
  76.    
  77.     // Timer and font size fields
  78.     timerField = new JTextField(5);
  79.     fontField  = new JTextField(5);
  80.    
  81.     // Glue text and input together
  82.     JPanel filenamePanel = new JPanel(new BorderLayout());
  83.     filenamePanel.add(new JLabel("File: "), "West");
  84.     filenamePanel.add(filename, "Center");
  85.    
  86.     JPanel fontPanel = new JPanel(new BorderLayout());
  87.     fontPanel.add(new JLabel("Font size:"), "West");
  88.     fontPanel.add(fontField, "Center");
  89.    
  90.     JPanel timerPanel = new JPanel(new BorderLayout());
  91.     timerPanel.add(new JLabel("Timer (ms):"), "West");
  92.     timerPanel.add(timerField, "Center");
  93.    
  94.     JPanel controls = new JPanel(new FlowLayout());
  95.     controls.add(timerPanel);
  96.     controls.add(fontPanel);
  97.    
  98.     // Create the buttons
  99.     loadButton = new JButton("load");
  100.     resetButton = new JButton("reset");
  101.     quitButton = new JButton("quit");
  102.     solverType = new JButton("stack");
  103.     solveButton = new JButton("start");
  104.     stepButton = new JButton("step");
  105.  
  106.     // places to put all the top menu items
  107.     JPanel buttons1 = new JPanel(new GridLayout(1, 3));  // top row of buttons
  108.     JPanel buttons2 = new JPanel(new GridLayout(1, 3));  // bottom row of buttons
  109.     JPanel buttonBar = new JPanel(new GridLayout(2, 2)); // combined layout of buttons
  110.                                  // and text
  111.    
  112.     // load up the buttons in L to R order
  113.     buttons1.add(loadButton);
  114.     buttons1.add(resetButton);
  115.     buttons1.add(quitButton);
  116.     buttons2.add(solverType);
  117.     buttons2.add(solveButton);
  118.     buttons2.add(stepButton);
  119.    
  120.     // Glue the components together row by row
  121.     buttonBar.add(filenamePanel); // top left
  122.     buttonBar.add(buttons1);      // top right
  123.     buttonBar.add(controls);      // bottom left
  124.     buttonBar.add(buttons2);      // bottom right
  125.     // add padding from edges
  126.     buttonBar.setBorder(BorderFactory.createEmptyBorder(10,10,0,10));
  127.    
  128.     // Timer for the animations
  129.     timer = new Timer(timerInterval, this);
  130.    
  131.    
  132.     // Set up the bottom area to show the maze and path
  133.     mazeDisplay = new JTextArea(20, 30);
  134.     mazeDisplay.setEditable(false);
  135.     DefaultCaret caret = (DefaultCaret)mazeDisplay.getCaret();
  136.     caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
  137.     pathDisplay = new JTextArea(4, 30);
  138.     pathDisplay.setEditable(false);
  139.     DefaultCaret caret2 = (DefaultCaret)pathDisplay.getCaret();
  140.     caret2.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
  141.     JPanel pane = new JPanel(new BorderLayout());
  142.     pane.setBorder(BorderFactory.createEmptyBorder(
  143.                 10, //top
  144.                 10, //left
  145.                 10, //bottom
  146.                 10) //right
  147.                 );
  148.     pane.add(new JScrollPane(mazeDisplay), "Center"); // let's maze be biggest
  149.     pane.add(new JScrollPane(pathDisplay), "South");
  150.    
  151.     // Create the overall layout (buttons on top, maze info below)
  152.     JPanel panel = new JPanel(new BorderLayout());
  153.     panel.add(buttonBar,"North");
  154.     panel.add(pane);
  155.    
  156.     // add to the frame
  157.     this.getContentPane().add(panel);
  158.    
  159.     // shrink wrap and display
  160.     this.pack();
  161.     this.setLocationRelativeTo(null);   // center
  162.     this.setVisible(true);
  163.  
  164.     // Actionlisteners
  165.     loadButton.addActionListener(this);
  166.     filename.addActionListener(this);
  167.     solveButton.addActionListener(this);
  168.     solverType.addActionListener(this);
  169.     stepButton.addActionListener(this);
  170.     resetButton.addActionListener(this);
  171.     quitButton.addActionListener(this);
  172.    
  173.     timerField.addActionListener(this);
  174.     fontField.addActionListener(this);
  175.    
  176.     // Set up the class variables
  177.     doTimer();
  178.     doFontSize();
  179.     mazeLoaded = false;
  180.     this.maze = new Maze();
  181.     //makeNewSolver();
  182.     }
  183.    
  184.     /*
  185.      * Collection of handlers to deal with GUI events.
  186.      *
  187.      * (non-Javadoc)
  188.      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
  189.      */
  190.     @Override
  191.     public void actionPerformed(ActionEvent e) {
  192.     if ( (e.getSource() == loadButton) || (e.getSource() == filename) ){
  193.         loadFile();
  194.     }
  195.     if (e.getSource() == solveButton) {
  196.         if (mazeLoaded) {
  197.         makeNewSolver();
  198.         solveButton();
  199.         }
  200.     }
  201.     if (e.getSource() == resetButton) {
  202.         reset();
  203.     }
  204.     if (e.getSource() == solverType) {
  205.         toggleSolverType();
  206.         makeNewSolver();
  207.     }
  208.     if (e.getSource() == quitButton) {
  209.         doQuit();
  210.     }
  211.     if (e.getSource() == timerField) {
  212.         doTimer();
  213.     }
  214.     if (e.getSource() == fontField) {
  215.         doFontSize();
  216.     }
  217.     if (e.getSource() == stepButton) {
  218.         if (mazeLoaded)
  219.         doStep();
  220.     }
  221.     if (e.getSource() == timer) {
  222.         // animate a step
  223.         if (mazeLoaded) {
  224.         doStep();
  225.         }
  226.     }
  227.    
  228.     }
  229.  
  230.     /**
  231.      * Allow the user to change the timer interval.
  232.      */
  233.     private void doTimer() {
  234.     int newValue = -1;
  235.     try {
  236.         newValue = Integer.parseInt(timerField.getText());
  237.     } catch (NumberFormatException nfe) {
  238.         // do nothing
  239.     }
  240.     if (newValue>=0)
  241.         timerInterval = newValue;
  242.     timerField.setText(Integer.toString(timerInterval));
  243.     timer.setDelay(timerInterval);
  244.     }
  245.  
  246.  
  247.     /**
  248.      * Allow the user to change the font size.
  249.      */
  250.     private void doFontSize() {
  251.     int newValue = -1;
  252.     try {
  253.         newValue = Integer.parseInt(fontField.getText());
  254.     } catch (NumberFormatException nfe) {
  255.         // do nothing
  256.     }
  257.     if (newValue>0)
  258.         fontSize = newValue;
  259.     fontField.setText(Integer.toString(fontSize));
  260.     mazeDisplay.setFont(new Font("Courier",Font.BOLD, fontSize));
  261.     pathDisplay.setFont(new Font("Courier",Font.BOLD, fontSize));
  262.  
  263.     }
  264.  
  265.     /**
  266.      * Allow the user to quit via button.
  267.      */
  268.     private void doQuit() {
  269.         System.exit(0);
  270.     }
  271.  
  272.     /**
  273.      * Set things back to the ready state.  Called by the "reset" button
  274.      * as well as many other methods.
  275.      */
  276.     private void reset() {
  277.     maze.reset();
  278.     makeNewSolver();
  279.     updateMaze();
  280.     }
  281.  
  282.     /**
  283.      * Performs a single step of the MazeSolver.  Called when the
  284.      * user clicks on "Step" as well as by the interval timer.
  285.      */
  286.     private void doStep() {
  287.     if (mazeLoaded && !solver.isSolved()) {
  288.         solver.step();
  289.         if (solver.isSolved()) {
  290.         solveButton();
  291.         timer.stop();
  292.         }
  293.     }
  294.     updateMaze();
  295.     }
  296.  
  297.     /**
  298.      * Handles the user clicking on the solver type button.
  299.      */
  300.     private void toggleSolverType() {
  301.     String oldType = solverType.getText();
  302.     if (oldType.equalsIgnoreCase("queue")) {
  303.         solverType.setText("stack");
  304.     } else if (oldType.equalsIgnoreCase("stack")) {
  305.         solverType.setText("queue");
  306.     } else
  307.         throw new UnsupportedOperationException("Don't know how to change from a: " + oldType);
  308.     reset();
  309.     }
  310.    
  311.     /**
  312.      * Builds a new MazeSolver of the type displayed on the button.
  313.      */
  314.     private void makeNewSolver() {
  315.     String oldType = solverType.getText();
  316.     if (oldType.equalsIgnoreCase("queue")) {
  317.         solver = new MazeSolverQueue(this.maze);
  318.     } else if (oldType.equalsIgnoreCase("stack")) {
  319.         solver = new MazeSolverStack(this.maze);
  320.     } else if (oldType.equalsIgnoreCase("hash map")) {
  321.         solver = new MazeSolverHashMap(this.maze);
  322.     } else
  323.         throw new UnsupportedOperationException("Don't know how to solve using a: " + oldType);
  324.     }
  325.  
  326.     /**
  327.      * Handles the starting/stopping of the timer.
  328.      */
  329.     private void solveButton() {
  330.     String label = solveButton.getText();
  331.     if (solver.isSolved()) {
  332.         solveButton.setBackground(Color.white);
  333.         solveButton.setText("start");
  334.         return;
  335.     }
  336.     if (label.equalsIgnoreCase("start")) {
  337.         if ( mazeLoaded ) {
  338.         solveButton.setText("stop");
  339.         solveButton.setBackground(Color.red);
  340.         timer.start();
  341.         }
  342.     } else if (label.equalsIgnoreCase("stop")) {
  343.         solveButton.setText("start");
  344.         solveButton.setBackground(Color.green);
  345.         timer.stop();
  346.     }
  347.     }
  348.  
  349.     /**
  350.      * Load a maze file into the solver.
  351.      */
  352.     private void loadFile() {
  353.  
  354.     // Let the user pick from a filtered list of files
  355.     JFileChooser chooser = new JFileChooser(new File("."));
  356.     chooser.setFileFilter(new FileFilter() {
  357.         String description = "Maze files";
  358.  
  359.         @Override
  360.         public boolean accept(File f) {
  361.         if (f.isDirectory()) {
  362.                 return true;
  363.             }
  364.         if (f.getName().startsWith("maze-"))
  365.             return true;
  366.         return false;
  367.         }
  368.  
  369.         @Override
  370.         public String getDescription() {
  371.         return this.description;
  372.         }
  373.        
  374.     });
  375.     File newFile = null;
  376.     String newFileName = null;
  377.         int returnVal = chooser.showOpenDialog(this);
  378.         if(returnVal == JFileChooser.APPROVE_OPTION) {
  379.             newFile = chooser.getSelectedFile();
  380.             newFileName = newFile.getName();
  381.         } else {
  382.             // if they didn't pick a file, cancel the rest of the update
  383.             return;
  384.         }
  385.        
  386.         // Try to load it
  387.         if (! maze.loadMaze(newFile.getPath()) ) {
  388.             JOptionPane.showMessageDialog(this, "Cannot load file: "+newFileName);
  389.         } else {
  390.             // update name without path
  391.             filename.setText(newFileName);
  392.            
  393.             // set things up as ready to go
  394.             solveButton.setText("start");
  395.             solveButton.setBackground(Color.green);
  396.             mazeLoaded=true;
  397.             timer.stop();
  398.             reset();
  399.         }
  400.     }
  401.  
  402.     /**
  403.      * Update both the maze and the path text areas.
  404.      */
  405.     private void updateMaze() {
  406.     if (mazeLoaded) {  // leave blank until first maze is loaded
  407.        
  408.         // update the maze
  409.         mazeDisplay.setText(maze.toString());
  410.  
  411.         // update the path
  412.         if (solver.isSolved()) {
  413.         pathDisplay.setText(solver.getPath());
  414.         } else {
  415.         pathDisplay.setText("Maze is unsolved");
  416.         }
  417.     }
  418.     }
  419.  
  420.     /**
  421.      * @param args
  422.      */
  423.     public static void main(String[] args) {
  424.         new MazeApp();
  425.     }
  426.  
  427. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement