Question: The question is to create a class search For Exit which its algorithm is: Create a Labyrinth object reference Try to open a new Labyrinth
The question is to create a class "search For Exit" which its algorithm is:
Create a Labyrinth object reference
Try to open a new Labyrinth from one of the Labyrinth files provided ( The Labyrinth should now be initialized)
Create a Hexagon reference and get the start Hexagon tile from the Labyrinth ( Using an array stack of Hexagons, we will solve the Labyrinth. )
Create the stack and push the starting tile.
Create a boolean variable that we will use to keep track of whether we have found the end
Create a reference for the current Hexagon that we will process
Create a counter to keep track of how many steps it takes us to solve the Labyrinth
Now, while our stack is not empty, and while we have not found the end o pop the top of the stack to get the current hexagon tile o increment the step counter o if the current hexagon tile is an end tile, make the found end boolean variable true o otherwise, for each of the possible six neighbours of the current tile if the neighbour exists and is unvisited push the neighbouring hexagon tile to the Labyrinth solving stack and set the neighbouring hexagon tile to be a pushed tile type o set the current hexagon tile to "processed", now that we are done with it .Note: each time through we need to update the Labyrinth window with a call to repaint()
Once we have searched the Labyrinth using the above algorithm, print out the following using a System.out.println or .format: If the end was found, or if it was not found. The number of steps that it took to finish o How many tiles were still on the stack
Save the labyrinths finished state to a file called processed_ + input file name. o Ex. if laby1.txt were the input file, processed_laby1.txt would be the output name
The Code given are...
Labyrinth.java
import java.io.*;
import java.util.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* The Labyrinth class creates a window that shows a hexagon-tile based Labyrinth.
*
* The Labyrinth is built from a file with the following specifications:
*
*
*
*
*
* (Note: because this Labyrinth is based on hexagons, each alternating row is
* offset from the left side by half a hexagon, indicated by a space in the input file)
*
The first line has the number of rows and cols
Each subsequent line (there will be the same number of lines as rows)
*
* @author CS1027
*
*/
public class Labyrinth extends JFrame {
private static final long serialVersionUID = 1L;
//Characters used by the input and output files
private static final char UNVISITED_CHAR = 'U';
private static final char TREASURE_CHAR = 'T';
private static final char END_CHAR = 'E';
private static final char START_CHAR = 'S';
private static final char WALL_CHAR = 'W';
private static final char END_PROCESSED_CHAR = 'G';
private static final char PROCESSED_CHAR = 'P';
private static final char PUSHED_CHAR = 'H';
private static final String MY_TITLE = "Labyrinth";
//Default time delay when repainting the Labyrinth to reflect hexagon changes
public static final int DEFAULT_TIME_DELAY = 1;
private int timeDelay = DEFAULT_TIME_DELAY;
protected Hexagon start;
private Hexagon[][] hexLabyrinth;
/**
* Constructor to build a Graphical Labyrinth with hexagonal tiles
* from a file containing a Labyrinth specification
* @param inFile
* @throws UnknownLabyrinthCharacterException
* @throws FileNotFoundException
* @throws IOException
*/
public Labyrinth(String inFile) throws UnknownLabyrinthCharacterException, FileNotFoundException, IOException{
// set up GUI aspects of the Labyrinth component
super("Labyrinth");
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
// set up the file reader and read the first line
BufferedReader in;
String line="";
in = new BufferedReader(new FileReader(inFile));
line = in.readLine();
// Tokenize the first line to get the row and column
StringTokenizer lineTokens = new StringTokenizer(line);
// First line is the number of rows then the number of columns
int row = Integer.parseInt(lineTokens.nextToken());
int col = Integer.parseInt(lineTokens.nextToken());
// The hexagons form a linked structure, and we don't
// use the 2D array for anything after building the labyrinth
// .....except to output the result to a file
hexLabyrinth = new Hexagon[row+2][col+2];
// HexLayout will arrange the Hexagons in the window
p.setLayout(new HexLayout(row, col, 4));
// for each row
for (int r = 1; r
line = in.readLine();
lineTokens = new StringTokenizer(line);
// for each token on the line (col in the Labyrinth)
for(int c = 1; c< col+1; c++){
// read the token and generate the hexagon type
char token = lineTokens.nextToken().charAt(0);
switch(token){
case WALL_CHAR:
hexLabyrinth[r][c] = new Hexagon(Hexagon.HexType.WALL);
break;
case START_CHAR:
hexLabyrinth[r][c] = new Hexagon(Hexagon.HexType.START);
this.start = hexLabyrinth[r][c];
break;
case END_CHAR:
hexLabyrinth[r][c] = new Hexagon(Hexagon.HexType.END);
break;
case TREASURE_CHAR:
hexLabyrinth[r][c] = new Hexagon(Hexagon.HexType.TREASURE);
break;
case UNVISITED_CHAR:
hexLabyrinth[r][c] = new Hexagon(Hexagon.HexType.UNVISITED);
break;
default:
// cannot build correct Labyrinth
throw new UnknownLabyrinthCharacterException(token);
}
// add to the GUI layout
p.add(hexLabyrinth[r][c]);
}// end for cols
}// end for rows
//go through the 2D matrix again and build the neighbors
int offset = 0;
for(int r=1;r
for(int c=1;c
// on even rows(inset from left side) need to add one to the upper and lower neighbors
// on odd, do not add anything (offset should be 0)
offset = 1 - r%2;
// set the neighbors for this hexagon in the builder
hexLabyrinth[r][c].setNeighbour(hexLabyrinth[r-1][c+offset], 0);
hexLabyrinth[r][c].setNeighbour(hexLabyrinth[r][c+1], 1);
hexLabyrinth[r][c].setNeighbour(hexLabyrinth[r+1][c+offset], 2);
hexLabyrinth[r][c].setNeighbour(hexLabyrinth[r+1][c-1+offset], 3);
hexLabyrinth[r][c].setNeighbour(hexLabyrinth[r][c-1], 4);
hexLabyrinth[r][c].setNeighbour(hexLabyrinth[r-1][c-1+offset], 5);
} // end for cols
} // end for rows
//close the file
in.close();
//set up the GUI window
this.add(p);
this.pack();
this.setSize(40*row,40*col );
this.setVisible(true);
}
/**
* Method will return a reference to the hexagon that is the
* start of the Labyrinth.
* @return A reference to the hexagon that is the start of the Labyrinth
*/
public Hexagon getStart() {
return this.start;
}
/**
* Get the current time delayed used when repainting the Labyrinth to reflect changes
* made to the hexagon tiles
* @return the timeDelay
*/
public int getTimeDelay() {
return timeDelay;
}
/**
* Set the amount of time to wait when repainting the Labyrinth to reflect changes
* made to the hexagon tiles
* @param timeDelay the timeDelay to set
*/
public void setTimeDelay(int timeDelay) {
this.timeDelay = timeDelay;
}
@Override
public void repaint() {
try {
Thread.sleep(this.timeDelay);
}catch(Exception e){
System.err.println("Error while issuing time delay " + e.getMessage());
}
super.repaint();
}
/**
* Goes through the current state of the labyrinth, and prints the results to
* a file specified in the parameter
*
* @param outFile The name of the file to save the labyrinth to
* @throws IOException
*/
public void saveLabyrith(String outFile) throws FileNotFoundException, IOException {
// set up the file writer and read the first line
BufferedWriter out;
String line="";
out = new BufferedWriter(new FileWriter(outFile));
// for each row
for (int r = 1; r
line = "";
//on even row we inset by a space
if(r%2 == 0)
line +=" ";
// for each col
for(int c = 1; c< this.hexLabyrinth[r].length; c++){
if (this.hexLabyrinth[r][c] !=null) {
switch(this.hexLabyrinth[r][c].getHexagonType()) {
case UNVISITED:
line += UNVISITED_CHAR;
break;
case TREASURE:
line += TREASURE_CHAR;
break;
case END:
line += END_CHAR;
break;
case START:
line += START_CHAR;
break;
case WALL:
line += WALL_CHAR;
break;
case PUSHED:
line += PUSHED_CHAR;
break;
case PROCESSED:
line += PROCESSED_CHAR;
break;
case END_PROCESSED:
line += END_PROCESSED_CHAR;
break;
default:
line += '?';
}
line += ' ';
}
}
out.write(line + " ");
}
out.close();
}
HEXAGON.java
import java.awt.Color;
/**
* This class represents a pointed-top Hexagon tile used to make up a Maze object.
*
* Each tile has a type. It can be a Wall, Start, End, Unvisited, Visited or Pushed tile.
* Each tile type will be a different colour: black, green, red, cyan, blue and magenta respectively.
*
* Hexagon tiles know about their neighbors (if set using setNeighbor method).
*
* The neighbors of a tile are accessed by an index 0-5 inclusive.
*
*
*
The hexagons are pointed-top in orientation, the 0 index is the upper-right side
Indexes for the sides progress incrementally clockwise from the 0 index, to 5 on the upper-left side
*
* Eg.
* 5 / \ 0
* 4 | | 1
* 3 \ / 2
* @author CS1027
*
*/
public class Hexagon extends HexComponent
{
// constants
private static final Color WALL_COLOR = Color.BLACK;
private static final Color START_COLOR = Color.GREEN;
private static final Color END_COLOR = Color.RED;
private static final Color UNVISITED_COLOR = Color.CYAN;
private static final Color PROCESSED_COLOR = Color.BLUE;
private static final Color PUSHED_COLOR = Color.MAGENTA;
private static final Color END_PROCESSED_COLOR = Color.ORANGE;
private static final Color TREASURE_COLOR = Color.YELLOW;
//enum to represent available hexagon types
public static enum HexType{WALL, START, END, UNVISITED, PROCESSED, PUSHED, END_PROCESSED, TREASURE};
// Attributes
private HexType type; // Stores the type of Hexagon this currently is
private boolean isStart; // Is this the start?
private boolean isEnd; // Is this the end?
private Hexagon[] neighbors; // Stores the hexagons which surround this one on each of 6 sides
/**
* Create a Hexagon tile of the specified type
* @param t the HexType to create
*/
public Hexagon(HexType t){
this.type = t;
this.isStart = t==HexType.START;
this.isEnd = t==HexType.END;
//set the initial color based on the initial type
this.setColor(this.type);
//allocate space for the neighbor array
this.neighbors = new Hexagon[6];
}
/**
* Set the neighbor for this hexagon using the neighbor index.
*
* The index for the neighbor indicates which side of the hexagon
* this new neighbor is on. 0-5 inclusive.
*
* @param neighbor The new Hexagon neighbor
* @param i The index specifying which side this neighbor is on (0-5 inclusive)
* @throws InvalidNeighborIndexException When an index is specified that is not 0-5 inclusive.
*/
public void setNeighbour(Hexagon neighbor, int i) throws InvalidNeighbourIndexException{
if (0<=i && i <=5)
this.neighbors[i] = neighbor;
else
throw new InvalidNeighbourIndexException(i);
}
/**
* Returns the neighbor for this hexagon using the neighbor index
*
* The index for the neighbor indicates which side of the hexagon
* the neighbor to get is on. 0-5 inclusive.
*
* @param i The index indicating the side of the hexagon this neighbor is on
* @return The hexagon the is on the i-th side of the current hexagon, or null if no neighbor
* @throws InvalidNeighbourIndexException When an index is specified that is not 0-5 inclusive.
*/
public Hexagon getNeighbour(int i) throws InvalidNeighbourIndexException{
if (0<=i && i <=5)
return this.neighbors[i];
else
throw new InvalidNeighbourIndexException(i);
}
/**
* This method checks if the current hexagon is a Wall tile.
* @return true if this is a Wall tile, false otherwise.
*/
public boolean isWall(){
return type == HexType.WALL;
}
/**
* This method checks if the current hexagon is a Visited tile.
* @return true if this is a Visited tile, false otherwise.
*/
public boolean isProcessed(){
return type == HexType.PROCESSED;
}
/**
* This method checks if the current hexagon is an Unvisited tile.
* @return true if this is an Unvisited tile, false otherwise.
*/
public boolean isUnvisited(){
return type == HexType.UNVISITED || (this.isEnd() && type==HexType.END);
}
/**
* This method checks if the current hexagon is a Start tile.
* @return true if this is a Start tile, false otherwise.
*/
public boolean isStart(){
return this.isStart;
}
/**
* This method checks if the current hexagon is an End tile.
* @return true if this is an End tile, false otherwise.
*/
public boolean isEnd(){
return this.isEnd;
}
/**
* This method gets the hexagon type and returns a HexType
* value, which can be checked against the enum above
* @return HexType value - see the enum
*/
public HexType getHexagonType() {
return this.type;
}
/**
* This method sets the tile to be a Pushed tile
* and updates the tile's colour
*/
public void setPushed(){
this.type = HexType.PUSHED;
this.setColor(this.type);
}
/**
* This method set the tile to be a Visited tile
* and updates the tile's colour
*/
public void setProcessed(){
this.type = HexType.PROCESSED;
if (isEnd){
this.type = HexType.END_PROCESSED;
}
this.setColor(this.type);
}
/**
* Helper method to set the current tile color based on the
* type of tile.
* @param t The type to use to set the color
*/
private void setColor(HexType t){
switch(t){
case WALL:
this.setBackground(WALL_COLOR);
break;
case START:
this.setBackground(START_COLOR);
break;
case END:
this.setBackground(END_COLOR);
break;
case UNVISITED:
this.setBackground(UNVISITED_COLOR);
break;
case PROCESSED:
this.setBackground(PROCESSED_COLOR);
break;
case PUSHED:
this.setBackground(PUSHED_COLOR);
break;
case END_PROCESSED:
this.setBackground(END_PROCESSED_COLOR);
break;
case TREASURE:
this.setBackground(TREASURE_COLOR);
break;
default:
this.setBackground(WALL_COLOR);
break;
}
this.setForeground(Color.black);
}
}
HEXCOMPONENT.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
/**
* A six sided component. This is not guaranteed to be a perfect hexagon, it is just guaranteed to have six sides in
* the form of a hexagon. To be a perfect hexagon the size of this component must have a height to width ratio of
* 1 to 0.866
*
* @author keang
* @date 5 Jun 2009
*
*/
public class HexComponent extends JComponent{
private static final long serialVersionUID = 4865976127980106774L;
private Polygon hexagon = new Polygon();
@Override
public boolean contains(Point p)
{
return hexagon.contains(p);
}
@Override
public boolean contains(int x, int y)
{
return hexagon.contains(x, y);
}
@Override
public void setSize(Dimension d)
{
super.setSize(d);
calculateCoords();
}
@Override
public void setSize(int w, int h)
{
super.setSize(w, h);
calculateCoords();
}
@Override
public void setBounds(int x, int y, int width, int height)
{
super.setBounds(x, y, width, height);
calculateCoords();
}
@Override
public void setBounds(Rectangle r)
{
super.setBounds(r);
calculateCoords();
}
@Override
protected void processMouseEvent(MouseEvent e)
{
if ( contains(e.getPoint()) )
super.processMouseEvent(e);
}
private void calculateCoords()
{
int w = getWidth()-1;
int h = getHeight()-1;
int ratio = (int)(h*.25);
int nPoints = 6;
int[] hexX = new int[nPoints];
int[] hexY = new int[nPoints];
agressiveCoords(w, h, ratio, hexX, hexY);
hexagon = new Polygon(hexX, hexY, nPoints);
}
private void agressiveCoords(int w, int h, int ratio, int[] hexX, int[] hexY) {
hexX[0] = w/2;
hexY[0] = 0;
hexX[1] = w;
hexY[1] = ratio;
hexX[2] = w;
hexY[2] = h - ratio;
hexX[3] = w/2;
hexY[3] = h;
hexX[4] = 0;
hexY[4] = h - ratio;
hexX[5] = 0;
hexY[5] = ratio;
}
@Override
protected void paintComponent(Graphics g)
{
g.setColor(getBackground());
g.fillPolygon(hexagon);
g.setColor(getForeground());
g.drawPolygon(hexagon);
}
@Override
protected void paintBorder(Graphics g)
{
// do not paint a border
}
}
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
