-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMazeSolver.java
More file actions
293 lines (237 loc) · 9.54 KB
/
MazeSolver.java
File metadata and controls
293 lines (237 loc) · 9.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/*-----------------------------------------------------------------------------------------
ANSWER THE QUESTIONS FROM THE DOCUMENT HERE
(1) Which graph representation did you choose, and why?
I chose Adjacency Matrix, because we do not remove or add any new vertices to our Graph
(which would probably be more efficient with Adjacency list).
Instead we are updating edges which take less big-O time with
adjacency matrix implementation.
(2) Which search algorithm did you choose, and why?
----------------------------------------------------------------------------------------*/
import java.io.*;
import java.lang.Math;
import java.util.Stack;
import java.util.Vector;
public class MazeSolver {
public Node[] solve(Graph _mazeGraph)
{
//the nodes that will be in the path
Node[] pathNodes = new Node[_mazeGraph.numNodes];
int inSolutionCtr = 0;
Stack<Node> foundNodes = new Stack<Node>();
//find the top left node and add it to foundNodes
foundNodes.push(_mazeGraph.nodes[0]);
//while the foundNodes list is not empty
while (!foundNodes.isEmpty())
{
//remove the last added Node from foundNodes list
Node removedNode = foundNodes.pop();
//if this removedNode has not been visited
if(!removedNode.visited)
{
//mark it as visited
removedNode.visited = true;
//adding the node to patthNodes list (inSolution)
//some will be removed later
pathNodes[inSolutionCtr] = removedNode;
inSolutionCtr++;
//stops if reaches the exit
if(removedNode.index == _mazeGraph.numNodes - 1)
{
break;
}
//if node just removed from stack has no neighbors
Node lastStep = removedNode;
while(findUnvisitedNeighbors(lastStep, _mazeGraph).isEmpty())
{
pathNodes[inSolutionCtr - 1] = null;
inSolutionCtr--;
lastStep = pathNodes[inSolutionCtr - 1];
}
//add its unvisited neighbors to the foundList
for (Node _neighbor : findUnvisitedNeighbors(removedNode, _mazeGraph)) {
foundNodes.push(_neighbor);
}
}
}
return pathNodes;
}
//returns a vector of neighbors of a provided node
private Vector<Node> findUnvisitedNeighbors(Node _removedNode, Graph _mazeGraph)
{
Vector<Node> edgedNeighbors = new Vector<Node>();
int graphSize = (int) Math.sqrt(_mazeGraph.numNodes);
//check whether the left neighbor has an edge with removedNode
if ( _mazeGraph.edgeExists(_removedNode.index - 1, _removedNode.index) )
{
if (!_mazeGraph.nodes[_removedNode.index - 1].visited)
{
edgedNeighbors.add(_mazeGraph.nodes[_removedNode.index - 1]);
}
}
//right neighbor
if ( _mazeGraph.edgeExists(_removedNode.index + 1, _removedNode.index) )
{
if (!_mazeGraph.nodes[_removedNode.index + 1].visited)
{
edgedNeighbors.add(_mazeGraph.nodes[_removedNode.index + 1]);
}
}
//top neighbor
if ( _mazeGraph.edgeExists(_removedNode.index - graphSize, _removedNode.index) )
{
if (!_mazeGraph.nodes[_removedNode.index - graphSize].visited)
{
edgedNeighbors.add(_mazeGraph.nodes[_removedNode.index - graphSize]);
}
}
//bottom neighbor
if ( _mazeGraph.edgeExists(_removedNode.index + graphSize, _removedNode.index) )
{
if (!_mazeGraph.nodes[_removedNode.index + graphSize].visited)
{
edgedNeighbors.add(_mazeGraph.nodes[_removedNode.index + graphSize]);
}
}
return edgedNeighbors;
}
public void run(String filename) throws IOException {
// read the input file to extract relevant information about the maze
String[] readFile = parse(filename);
int mazeSize = Integer.parseInt(readFile[0]);
int numNodes = mazeSize*mazeSize;
String mazeData = readFile[1];
// construct a maze based on the information read from the file
Graph mazeGraph = buildGraph(mazeData, numNodes);
// do something here to solve the maze
Node[] inSolutionNodes = solve(mazeGraph);
int i = 0;
while ( !(inSolutionNodes[i] == null) )
{
inSolutionNodes[i].inSolution = true;
i++;
}
// print out the final maze with the solution path
printMaze(mazeGraph.nodes, mazeData, mazeSize);
}
// prints out the maze in the format used for HW8
// includes the final path from entrance to exit, if one has been recorded,
// and which cells have been visited, if this has been recorded
public void printMaze(Node[] mazeCells, String mazeData, int mazeSize) {
int ind = 0;
int inputCtr = 0;
System.out.print("+");
for(int i = 0; i < mazeSize; i++) {
System.out.print("--+");
}
System.out.println();
for(int i = 0; i < mazeSize; i++) {
if(i == 0) System.out.print(" ");
else System.out.print("|");
for(int j = 0; j < mazeSize; j++) {
System.out.print(mazeCells[ind] + "" + mazeCells[ind] + mazeData.charAt(inputCtr));
inputCtr++;
ind++;
}
System.out.println();
System.out.print("+");
for(int j = 0; j < mazeSize; j++) {
System.out.print(mazeData.charAt(inputCtr) + "" + mazeData.charAt(inputCtr) + "+");
inputCtr++;
}
System.out.println();
}
}
// reads in a maze from an appropriately formatted file (this matches the format of the
// mazes you generated in HW8)
// returns an array of Strings, where position 0 stores the size of the maze grid (i.e., the
// length/width of the grid) and position 1 minimal information about which walls exist
public String[] parse(String filename) throws IOException {
FileReader fr = new FileReader(filename);
// determine size of maze
int size = 0;
int nextChar = fr.read();
while(nextChar >= 48 && nextChar <= 57) {
size = 10*size + nextChar - 48;
nextChar = fr.read();
}
String[] result = new String[2];
result[0] = size + "";
result[1] = "";
// skip over up walls on first row
for(int j = 0; j < size; j++) {
fr.read();
fr.read();
fr.read();
}
fr.read();
fr.read();
for(int i = 0; i < size; i++) {
// skip over left wall on each row
fr.read();
for(int j = 0; j < size; j++) {
// skip over two spaces for the cell
fr.read();
fr.read();
// read wall character
nextChar = fr.read();
result[1] = result[1] + (char)nextChar;
}
// clear newline character at the end of the row
fr.read();
// read down walls on next row of input file
for(int j = 0; j < size; j++) {
// skip over corner
fr.read();
//skip over next space, then handle wall
fr.read();
nextChar = fr.read();
result[1] = result[1] + (char)nextChar;
}
// clear last wall and newline character at the end of the row
fr.read();
fr.read();
}
return result;
}
public Graph buildGraph(String maze, int numNodes) {
Graph mazeGraph = new Graph(numNodes);
int size = (int)Math.sqrt(numNodes);
int mazeInd = 0;
for(int i = 0; i < size; i++) {
// create edges for right walls in row i
for(int j = 0; j < size; j++) {
char nextChar = maze.charAt(mazeInd);
mazeInd++;
if(nextChar == ' ') {
// add an edge corresponding to a right wall, using the indexing convention
// for nodes
mazeGraph.addEdge(size*i + j, size*i + j + 1);
}
}
// create edges for down walls below row i
for(int j = 0; j < size; j++) {
char nextChar = maze.charAt(mazeInd);
mazeInd++;
if(nextChar == ' ') {
// add an edge corresponding to a down wall, using the indexing convention
// for nodes
mazeGraph.addEdge(size*i + j, size*(i+1) + j);
}
}
}
return mazeGraph;
}
public static void main(String [] args) {
if(args.length < 1) {
System.out.println("USAGE: java MazeSolver <filename>");
}
else{
try{
new MazeSolver().run(args[0]);
}
catch(IOException e) {
e.printStackTrace();
}
}
}
}