GUI class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.io.*;
import java.util.Scanner;
public class GUI implements ActionListener {
private JButton northButton = new JButton("North");
private JButton southButton = new JButton("South");
private JButton eastButton = new JButton("East");
private JButton westButton = new JButton("West");
private JButton solveButton = new JButton("Solve");
private JButton saveButton = new JButton("Save");
private MazeCrawler maze;
private final String SAVE_FILE_NAME = "maze.txt";
public static void pause() {
try {
Thread.sleep(25); // wait 1/40 s
} catch (Exception e) {
e.printStackTrace();
}
} // end method pause
private static ArrayList<String> getTextMaze(String filename) {
ArrayList<String> textMaze = new ArrayList<String>();
File handle = new File(filename);
try {
Scanner mazeFile = new Scanner(handle);
while (mazeFile.hasNext()) {
textMaze.add(mazeFile.nextLine());
}
} catch (Exception e) {
System.out.println("Error reading file");
System.exit(1);
}
return textMaze;
} // end getTextMaze
public void go() {
JFrame frame = new JFrame();
frame.setTitle("CS241 Maze Crawl");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
maze = new MazeCrawler(15, 32);
//maze = new MazeCrawler(getTextMaze(SAVE_FILE_NAME));
int xSize = Math.max(MazeCell.size * (maze.getColumns() + 1), 400);
frame.setSize(xSize, MazeCell.size * (maze.getRows() + 1) + 60);
frame.setLocation(300, 50);
frame.getContentPane().add(BorderLayout.CENTER, maze);
JPanel buttonPanel = new JPanel();
buttonPanel.add(westButton);
westButton.addActionListener(this);
buttonPanel.add(northButton);
northButton.addActionListener(this);
buttonPanel.add(southButton);
southButton.addActionListener(this);
buttonPanel.add(eastButton);
eastButton.addActionListener(this);
buttonPanel.add(solveButton);
solveButton.addActionListener(this);
buttonPanel.add(saveButton);
saveButton.addActionListener(this);
frame.getContentPane().add(BorderLayout.SOUTH, buttonPanel);
frame.setVisible(true);
} // end method main
public static void win() {
JOptionPane.showMessageDialog(null, "Path Found!");
System.exit(0);
} // end method
public static void lose() {
JOptionPane.showMessageDialog(null, "Nowhere to go from here!");
System.exit(1);
} // end method lose
@Override
public void actionPerformed(ActionEvent event) {
if (event.getSource() == northButton) {
maze.moveNorth();
}
if (event.getSource() == southButton) {
maze.moveSouth();
}
if (event.getSource() == eastButton) {
maze.moveEast();
}
if (event.getSource() == westButton) {
maze.moveWest();
}
if (event.getSource() == saveButton) {
maze.saveToFile(SAVE_FILE_NAME);
}
if (event.getSource() == solveButton) {
maze.solveMaze();
}
if (maze.isWin()) {
win();
}
if (maze.isNoMove()) {
lose();
}
} // end actionPerformed
} // end class GUI
Maze class
package
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JPanel;
/**
* Maze: This class represents a rectangular 2D maze suitable for
* display using the Java SWING Library.
* @author doom 2008
*/
public class Maze extends JPanel {
public MazeCell[][] maze;
private int rows; // vertical dimention of the maze, in cells
private int columns; // horizontal dimention of the maze, in cells
/**
* This constructor creates a 2D maze from a formatted List of Strings.
* @param textMaze Each String in the ArrayList represents one row of
* the maze. Each character/symbol in a String represents one cell in the maze
* (Preconditions) This routine assumes that all Strings are of the same
* length (all rows must be of the same length in a rectangular maze).
* This routine assumes all characters in the string are legal symbols for
* MazeCell. Violation of either of these conditions will result in a
* run-time error/crash.
*/
public Maze(ArrayList<String> textMaze) {
this.rows = textMaze.size();
this.columns = textMaze.get(0).length();
maze = new MazeCell[rows][columns];
buildEmptyMaze();
fillMazeFromFile(textMaze);
} // end constructor
/**
* This constructor creates a random 2D maze of the given size.
* @param rows The vertical dimention of the maze, in cells
* @param columns The horizontal dimention of the maze, in cells
* Note: Walls, Start, and Exit for the maze are randomly determined.
* There is no guarantee that a path exists between the Start and
* Exit.
*/
public Maze(int rows, int columns) {
this.rows = rows;
this.columns = columns;
maze = new MazeCell[rows][columns];
buildEmptyMaze();
fillMaze(0, 0, rows - 1, columns - 1);
getRandomEmptyCell().setType(MazeCell.Type.TRAIL_HEAD);
getRandomEmptyCell().setType(MazeCell.Type.EXIT);
} // end constructor
/**
* Graphically displays the maze as required for a JPanel
* This routine is called implictitly by this.refresh() or
* (for immediate redraw) this.paint(this.getGraphics())
*/
@Override
public void paintComponent(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
MazeCell cell = maze[row][column];
g.setColor(cell.getColor());
g.fillRect(cell.getX(), cell.getY(), MazeCell.size, MazeCell.size);
} // end for each column
} // end for each row
} // method paintComponent
/**
* @return The vertical dimention of the rectangular maze, in cells
*/
public int getRows() {
return rows;
}
/**
* @return The horizontal dimention of the rectangular maze, in cells
*/
public int getColumns() {
return columns;
}
/**
* @return Returns a copy of a MazeCell from the indicated row,
* column coordinates of the maze. The returned value is a copy
* only, to protect the privacy of the data.
*/
public MazeCell getCell(int row, int column) {
return new MazeCell(maze[row][column]);
} // end method getCell
/**
* setCell: This method updates the type information for a MazeCell. It
* does not allow the user to directly access the actual MazeCell objects
* to protect the maze from tinkering (such as replacing a mazeCell with a
* mazeCell that has the incorrect x,y,row,column information, etc.
* @param copyCell A mazeCell that contains the information to be updated
* in the actual maze's mazeCells. Most likely, this mazeCell will be a
* copy of an actual MazeCell object produced via a call to getCell() or
* getTrailHead().
*/
public void setCell(MazeCell copyCell) {
MazeCell realCell = maze[copyCell.getRow()][copyCell.getColumn()];
realCell.setType(copyCell.getType());
} // end method setCell
/**
* @return A copy of the current position of the path through the maze.
*/
public MazeCell getTrailHead() {
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
MazeCell cell = maze[row][column];
if (cell.getType() == MazeCell.Type.TRAIL_HEAD) {
return new MazeCell(cell);
}
} // end for each column
} // end for each row
return null;
} // end method getTrailHead
/**
* Populates a 2D array with empty MazeCells
*/
private void buildEmptyMaze() {
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
MazeCell cell = new MazeCell(row, column);
maze[row][column] = cell;
} // end for each column
} // end for each row
} // end method buildEmptyMaze
/**
* fillMaze: Fills a grid of empty MazeCells (maze) with randomly
* placed walls to form a maze. Parameters indicate the coordinates
* of the subgrid (to fill) within a potentially larger 2D array
* of MazeCells.
*/
private void fillMaze(int minRow, int minCol, int maxRow, int maxCol) {
// Base case: If grid of empty cells is smaller than 3x3 then we
// do not have space to add further walls
if ( ((maxRow - minRow) < 2) || ((maxCol - minCol) < 2)){
return;
}
// Recursive case: Add a vertical and horizontal wall at random
// interior positions
int wallRow = minRow + 1 + (int) (Math.random() * (maxRow - minRow - 1));
int wallCol = minCol + 1 + (int) (Math.random() * (maxCol - minCol - 1));
// Randomly place one vertical and one horizontal wall in maze
for (int row = minRow; row <= maxRow; row++) {
maze[row][wallCol].setType(MazeCell.Type.WALL);
}
for (int col = minCol; col <= maxCol; col++) {
maze[wallRow][col].setType(MazeCell.Type.WALL);
}
// Put a random hole in each of the four walls
int northPosition = minRow + (int) (Math.random() * (wallRow - minRow));
int southPosition = wallRow + 1 + (int) (Math.random() * (maxRow - wallRow - 1));
int westPosition = minCol + (int) (Math.random() * (wallCol - minCol));
int eastPosition = wallCol + 1 + (int) (Math.random() * (maxCol - wallCol - 1));
maze[northPosition][wallCol].setType(MazeCell.Type.EMPTY);
maze[southPosition][wallCol].setType(MazeCell.Type.EMPTY);
maze[wallRow][eastPosition].setType(MazeCell.Type.EMPTY);
maze[wallRow][westPosition].setType(MazeCell.Type.EMPTY);
// Recursive step: The two walls divide the current grid of empty cells
// into four (smaller) grids of empty cells. Recursively fill each
// of these four areas!
fillMaze(minRow, minCol, wallRow - 1, wallCol - 1); // NW cell
fillMaze(minRow, wallCol + 1, wallRow - 1, maxCol); // NE cell
fillMaze(wallRow + 1, minCol, maxRow, wallCol - 1); // SW cell
fillMaze(wallRow + 1, wallCol + 1, maxRow, maxCol); // SE cell
} // end method fillMaze
/**
* This method creates a maze from a text/character description.
* @param textMaze Each character in the arrayList of Strings is a
* symbol that represents the type (Wall, Empty, etc) of the mazeCell
* in the coresponding (row,column) position in the maze.
*/
private void fillMazeFromFile(ArrayList<String> textMaze) {
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
maze[row][column].setType(textMaze.get(row).charAt(column));
} // end for each column
} // end for each row
} // end method buildMaze
/**
* @return Returns a random traversable cell in the existing maze.
*/
private MazeCell getRandomEmptyCell() {
MazeCell cell = null;
do {
int row = (int) (Math.random() * rows);
int col = (int) (Math.random() * columns);
cell = maze[row][col];
} while (cell.getType() != MazeCell.Type.EMPTY);
return cell;
} // end method getRandomEmptyCell
} // end class Maze
MazeCell class
package CadenheadProject4;
import java.awt.*;
/**
* MazeCell objects represent a cell for use in 2-dimentional maze
* Each MazeCell may be traversable (e.g. Type.EMPTY), or
* non-traversable (e.g. Type.WALL). One traversable cell must be the
* "start" of the maze (Type.TRAIL_HEAD). At least one traversable cell
* must be an "exit" from the maze (Type.EXIT).
* Maze cells are labeled by table row and column, with origin (0,0) being
* the upper-left corner.
* @author doom 2008
*/
public class MazeCell {
public enum Type { EMPTY, WALL, TRAIL, TRAIL_HEAD, EXIT };
public final char WALL = '#';
public final char EMPTY = '.';
public final char START = 's';
public final char EXIT = 'x';
public static final int size = 15;
private Type cellType ;
private int row;
private int column;
/**
* Creates an empty cell for use in an n by m rectangular maze.
* @param row position in the overall maze for this maze cell
* @param column position in the overall maze for this maze cell
*/
public MazeCell(int row, int column) {
this.column = column;
this.row = row;
setType(Type.EMPTY);
} // end constructor
public MazeCell (MazeCell original) {
this.row = original.getRow();
this.column = original.getColumn();
setType(original.getType());
} // end copy constructor
/**
* Set the maze cell's cellType (wall, empty, etc) by setting it from
* options in MazeCell.Type
* @param The maze cell's cellType (e.g. Type.EMPTY, Type.WALL, etc).
*/
public void setType(Type type) {
this.cellType = type;
} // end method setType
/**
* Set the maze cell's cellType (wall, empty, etc) by using a one
* character text symbol. Useful for creating a maze from a text format.
* @param 'x' (wall), ' ' (empty), 'e' (exit), or 's' (start)
*/
public void setType(char typeChar) {
switch (typeChar) {
case EMPTY:
setType(Type.EMPTY);
break;
case WALL:
setType(Type.WALL);
break;
case START:
setType(Type.TRAIL_HEAD);
break;
case EXIT:
setType(Type.EXIT);
break;
default:
System.out.println("Error creating Maze");
System.exit(1);
} // end switch
// System.out.println(cellType);
} // end method setType
/**
* @return The cellType of mazecell (Type.WALL, Type.EXIT, etc).
*/
public Type getType() {
return cellType;
} // end method getType
/**
* @return The one character symbol used to represent the maze
* cell in text representation (e.g. # for Wall, . for empty, etc.)
*/
public char getTypeChar() {
char symbol = '*';
switch (cellType) {
case EMPTY: return EMPTY;
case WALL: return WALL;
case TRAIL_HEAD: return START;
case EXIT: return EXIT;
}
return symbol;
} // end method getTypeChar
/**
* @return The appropriate display color for this maze
* cell (by cellType: Wall, Empty, etc.). Returns PINK if
* cell is of non-standard cellType, likely due to an error
* elsewhere.
*/
public Color getColor() {
Color color = Color.PINK;
if (cellType == Type.EMPTY) {
color = Color.WHITE;
}
if (cellType == Type.WALL) {
color = Color.BLACK;
}
if (cellType == Type.TRAIL) {
color = Color.LIGHT_GRAY;
}
if (cellType == Type.TRAIL_HEAD) {
color = Color.BLUE;
}
if (cellType == Type.EXIT) {
color = Color.RED;
}
return color;
} // end method getColor
/**
* @return This maze cell's horizontal display position on the canvas
*/
public int getX() {
return column * size;
} // end method getX
/**
* @return This maze cell's vertical display position on the canvas
*/
public int getY() {
return row * size;
} // end method getY
/**
* @return This maze cell's row position in the overall maze
*/
public int getRow() {
return row;
} // end method getRow
/**
* @return This maze cell's column position in the overall maze
*/
public int getColumn() {
return column;
} // end method getColumn
} // end class MazeCell
Main class
package CadenheadProject4;
public class Main {
public static void main(String[] args) {
GUI mazeWindow = new GUI();
mazewindow.go();
} // end method main
} // end class Main
Then here is the start of my MazeCrawler class. If someone could help me with just one of the move methods i have i will be able to write the rest. Then I can get the recursive solver to work also. Thank you in advance if anyone wants to help
package
import java.awt.event.ActionEvent;
import java.util.ArrayList;
/**
*
* @author Brians
*/
public class MazeCrawler extends Maze {
private Object event;
public MazeCrawler(int rows, int columns) {
super(rows, columns);
}
public MazeCrawler(ArrayList<String> textMaze) {
super(textMaze);
}
public boolean isWin() {
return true;
}
public boolean isNoMove() {
return true;
}
public void moveNorth() {
int xPosition = getTrailHead().getX();
int yPosition = getTrailHead().getY();
if (xPosition == 0 && yPosition == 0) {
moveNorth();
}
}
public void moveSouth() {
}
public void moveEast() {
}
public void moveWest() {
}
public void saveToFile(String filename) {
}
public void solveMaze() {
}
}

New Topic/Question
Reply



MultiQuote



|