Advertisement
Guest User

Graph

a guest
Apr 25th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.48 KB | None | 0 0
  1. import java.util.ArrayList;
  2. import java.util.LinkedList;
  3. import java.util.Queue;
  4. import java.util.Random;
  5. import java.util.Stack;
  6.  
  7. /**
  8. * Maze Generator and Solver
  9. *
  10. * This program generates and solves mazes. It will generate a new random maze
  11. * and solve it. It solves it using depth-first search and breadth-first search
  12. *
  13. * @author Marietta Asemwota
  14. * @author Monsi Magal
  15. *
  16. */
  17.  
  18. public class Graph {
  19.  
  20. class Vertex {
  21. public int label; // to hold the name / number of the vertex
  22. Vertex[] neighbors; // array of neighbors, adjacency list
  23. int[] walls; //array of walls, -1 edge of maze, 0 broken wall, 1 intact wall, 4 entry/exit
  24. int color; // white 0, grey 1, black 2
  25. Vertex pi; // parent
  26. int startTime; // found time when it turns grey
  27. int endTime; // when it turns black
  28. int distance; // ADDED
  29. boolean inPath; //true if the Vertex is in the solution path and false if it is not
  30. int traverseOrder; //the order in which the vertex is traversed while solving
  31.  
  32.  
  33. public Vertex(int lab) {
  34. label = lab;
  35. /*
  36. * index correspondence for neighbors 0 = up 1 = right 2 = down 3 = left
  37. */
  38. neighbors = new Vertex[4];
  39. walls = new int[4];
  40. /*
  41. * index correspondence for walls 0 = up wall; 1 = right wall;
  42. * 2 = down wall; 3 = left wall
  43. */
  44. setAllWallsIntact();
  45. startTime = Integer.MAX_VALUE; //start time = infinity
  46. endTime = Integer.MAX_VALUE; //end time = infinity
  47. pi = null;
  48. distance = 0;
  49. inPath = false;
  50. traverseOrder = 0;
  51. }
  52.  
  53. /*
  54. * checks if all walls intact
  55. */
  56. public boolean allWallsIntact() {
  57. for (int i = 0; i < walls.length; i++) {
  58. if (walls[i] == 0) {
  59. return false;
  60. }
  61. }
  62. return true;
  63. }
  64.  
  65. /*
  66. * sets all walls intact
  67. */
  68. public void setAllWallsIntact() {
  69. for (int i = 0; i < walls.length; i++) {
  70. walls[i] = 1;
  71. }
  72. }
  73.  
  74.  
  75. /*
  76. * Methods to break walls
  77. */
  78. public void breakUpWall() {
  79. if (walls[0] != -1)
  80. walls[0] = 0;
  81. }
  82.  
  83. public void breakRightWall() {
  84. if (walls[1] != -1)
  85. walls[1] = 0;
  86. }
  87.  
  88. public void breakDownWall() {
  89. if (walls[2] != -1)
  90. walls[2] = 0;
  91. }
  92.  
  93. public void breakLeftWall() {
  94. if (walls[3] != -1)
  95. walls[3] = 0;
  96. }
  97.  
  98.  
  99. /*
  100. * Methods to set neighbors
  101. */
  102. public void setLeft(Vertex v) {
  103. neighbors[3] = v;
  104. }
  105.  
  106. public void setRight(Vertex v) {
  107. neighbors[1] = v;
  108. }
  109.  
  110. public void setUp(Vertex v) {
  111. neighbors[0] = v;
  112. }
  113.  
  114. public void setDown(Vertex v) {
  115. neighbors[2] = v;
  116. }
  117.  
  118.  
  119. /*
  120. * Methods to get neighbors
  121. */
  122. public Vertex getLeft() {
  123. return this.neighbors[3];
  124. }
  125.  
  126. public Vertex getRight() {
  127. return this.neighbors[1];
  128. }
  129.  
  130. public Vertex getUp() {
  131. return this.neighbors[0];
  132. }
  133.  
  134. public Vertex getDown() {
  135. return this.neighbors[2];
  136. }
  137.  
  138. /*
  139. * finds the relationship between this vertex and vertex v
  140. */
  141. public int vertexRelationship(Vertex v) {
  142. if (getUp() != null && getUp().equals(v)) {
  143. return 0;
  144. } else if (getRight() != null && getRight().equals(v)) {
  145. return 1;
  146. } else if (getDown() != null && getDown().equals(v)) {
  147. return 2;
  148. } else { // if (getLeft().equals(v)){
  149. return 3;
  150. }
  151. }
  152. }
  153.  
  154. Vertex vertexList[][]; //2d array of the vertices
  155. int amountVertices; //total vertices in maze
  156. int dimension; // dimension of maze
  157. private Random myRandGen; // random number generator
  158. private Vertex startVertex; //start of maze
  159. private Vertex endVertex; //end of maze
  160. int time; //time used for dfs
  161. int[] traversed; //array either 0 or 1. 0 means that order # hasn't been selected and 1 means it has been
  162.  
  163. /**
  164. * Constructor for this program takes in the dimensions of the maze It also
  165. * makes the seed of the random generator 0 for easier testing
  166. *
  167. * *** calls method to fill the graph with n*n rooms
  168. *
  169. * @param dimension_in as number of rows and columns
  170. */
  171.  
  172. public Graph(int dimension_in) {
  173. vertexList = new Vertex[dimension_in][dimension_in];
  174. // for simplicity of naming vertices, r keeps track of what "row" the
  175. // vertex is being created in
  176. int r = 1;
  177. for (int i = 0; i < dimension_in; i++) {
  178. for (int j = 0; j < dimension_in; j++) {
  179. vertexList[i][j] = new Vertex(i + r + j);
  180. }
  181. // r increases by a function of the length of the column
  182. r += dimension_in - 1;
  183. }
  184.  
  185. dimension = dimension_in;
  186. amountVertices = dimension * dimension;
  187. myRandGen = new java.util.Random(0); // seed is 0
  188. startVertex = vertexList[0][0]; // set startVertex to top left
  189. endVertex = vertexList[dimension - 1][dimension - 1]; // set endVertex to bottom right
  190. traversed = new int[dimension*dimension];
  191. }
  192.  
  193.  
  194. /*
  195. * sets the path of the solution using the parent and working backwards
  196. * useful for printing the DFS and BFS
  197. */
  198. public void setPath(){
  199. Vertex current = vertexList[dimension-1][dimension-1];
  200. while (current != null){
  201. current.inPath = true;
  202. current = current.pi;
  203. }
  204. }
  205.  
  206.  
  207. /*
  208. * resets graph
  209. * makes all vertices in vertex list to white, changes start and end times back to infinity, distance from source to 0
  210. */
  211. public void graphReset() {
  212. for (int i = 0; i < dimension; i++) {
  213. for (int j = 0; j < dimension; j++) {
  214. vertexList[i][j].color = 0;
  215. vertexList[i][j].pi = null;
  216. vertexList[i][j].startTime = Integer.MAX_VALUE; //infinity
  217. vertexList[i][j].endTime = Integer.MAX_VALUE;
  218. vertexList[i][j].distance = 0;
  219. }
  220. }
  221. startVertex.walls[0] = 4; //sets startVertex up wall as entry point
  222. endVertex.walls[2] = 4; //sets endVertex down wall as exit point
  223. }
  224.  
  225.  
  226. /**
  227. * DFS Solution
  228. * Solves the maze using Depth-first search, and uses a stack.
  229. * @param s - the starting vertex - the root
  230. */
  231. public void DFS(Vertex s) {
  232. int traverseO = 1;
  233. Stack<Vertex> q = new Stack<>();
  234. q.push(s);
  235. while (!q.isEmpty() && !q.peek().equals(endVertex)) { //while we aren't at the end
  236. Vertex u = q.pop();
  237. for (int i = 0; i < u.neighbors.length; i++) {
  238. Vertex v = u.neighbors[i];
  239. int direction = u.vertexRelationship(v);
  240. if ((u.walls[direction] == 0) && v != null && v.color == 0) { //if the wall is broken and it's not null and it hasn't been visited
  241. v.color = 1; //color = grey
  242. if (v.traverseOrder == 0){ //if this is the first time it has been visited
  243. if (traversed[traverseO] == 0){ //if this number hasn't been used
  244. v.traverseOrder = traverseO;
  245. traversed[traverseO] = 1; //set it to used
  246. } else { //if the number has been used
  247. traverseO++;
  248. v.traverseOrder = traverseO;
  249. traversed[traverseO] = 1; //set it to used
  250. }
  251. }
  252. v.distance = u.distance + 1;
  253. v.pi = u;
  254. q.push(v);
  255. }
  256. }
  257. u.color = 2; //color = black
  258. }
  259. }
  260.  
  261.  
  262. /**
  263. * BFS: Breadth-first Search solution to the maze
  264. * uses a queue
  265. *
  266. * @param s - the starting vertex - the root
  267. */
  268. public void BFS(Vertex s) {
  269. int traverseO = 1;
  270. Queue<Vertex> q = new LinkedList<>();
  271. q.add(s);
  272. while (!q.isEmpty() && !q.peek().equals(endVertex)) { //while we aren't at the end
  273. Vertex u = q.remove();
  274. for (int i = 0; i < u.neighbors.length; i++) {
  275. Vertex v = u.neighbors[i];
  276. int direction = u.vertexRelationship(v);
  277. if ((u.walls[direction] == 0) && v != null && v.color == 0) { //if the wall is broken and it's not null and it hasn't been visited
  278. v.color = 1; //color = grey
  279. if (v.traverseOrder == 0){ //if this is the first time it has been visited
  280. if (traversed[traverseO] == 0){ //if this number hasn't been used
  281. v.traverseOrder = traverseO;
  282. traversed[traverseO] = 1; //set it to used
  283. } else { //if the number has been used
  284. traverseO++;
  285. v.traverseOrder = traverseO;
  286. traversed[traverseO] = 1; //set it to used
  287. }
  288. }
  289. v.distance = u.distance + 1;
  290. v.pi = u;
  291. q.add(v);
  292. }
  293. }
  294. u.color = 2; //color = black
  295. }
  296. }
  297.  
  298. /*
  299. * populates graph to the dimension provided in the constructor of graph
  300. * also sets the neighbors and walls of the vertices
  301. */
  302. public void populateGraph() {
  303. for (int i = 0; i < dimension; i++) {
  304. for (int j = 0; j < dimension; j++) {
  305. Vertex mine = vertexList[i][j];
  306.  
  307. if (i == 0) {
  308. mine.setUp(null);
  309. mine.walls[0] = -1; // edge wall
  310. }
  311.  
  312. else {
  313. mine.setUp(vertexList[i - 1][j]); //setting the up wall
  314. mine.neighbors[0] = vertexList[i - 1][j]; //setting up neighbor
  315. }
  316.  
  317. if (j == 0) {
  318. mine.setLeft(null);
  319. mine.walls[3] = -1;
  320. }
  321.  
  322. else {
  323. mine.setLeft(vertexList[i][j - 1]);
  324. mine.neighbors[3] = vertexList[i][j - 1];
  325. }
  326.  
  327. if (i == dimension - 1) {
  328. mine.setDown(null);
  329. mine.walls[2] = -1;
  330. }
  331.  
  332. else {
  333. mine.setDown(vertexList[i + 1][j]);
  334. mine.neighbors[2] = vertexList[i + 1][j];
  335. }
  336.  
  337. if (j == dimension - 1) {
  338. mine.setRight(null);
  339. mine.walls[1] = -1;
  340. }
  341.  
  342. else {
  343. mine.setRight(vertexList[i][j + 1]);
  344. mine.neighbors[1] = vertexList[i][j + 1];
  345. }
  346. }
  347. }
  348. }
  349.  
  350. /**
  351. * Get a random number
  352. *
  353. * @return random double between 0 and 1
  354. */
  355. double myRandom() {
  356. return myRandGen.nextDouble();
  357. }
  358.  
  359.  
  360. /**
  361. * Generates a pseudo-random perfect maze.
  362. */
  363. void generateMaze() {
  364. //the general algorithm
  365. /*
  366. * create a CellStack (LIFO) to hold a list of cell locations set
  367. * TotalCells= number of cells in grid choose the starting cell and call
  368. * it CurrentCell set VisitedCells = 1 while VisitedCells < TotalCells
  369. * find all neighbors of CurrentCell with all walls intact if one or
  370. * more found choose one at random knock down the wall between it and
  371. * CurrentCell push CurrentCell location on the CellStack make the new
  372. * cell CurrentCell add 1 to VisitedCells else pop the most recent cell
  373. * entry off the CellStack make it CurrentCell
  374. */
  375.  
  376. graphReset(); //first reset the graph
  377. populateGraph();
  378.  
  379. //4 is a special designation for starting and ending vertices
  380. startVertex.walls[0] = 4;
  381. endVertex.walls[2] = 4;
  382.  
  383. Stack<Vertex> cellStack = new Stack<>();
  384. int totalCells = amountVertices;
  385. Vertex currentCell = vertexList[0][0];
  386. int visitedCells = 1;
  387. while (visitedCells < totalCells) {
  388. ArrayList<Vertex> neighborsIntact = new ArrayList<Vertex>();
  389. for (int i = 0; i < currentCell.neighbors.length; i++) {
  390. Vertex neighbor = currentCell.neighbors[i];
  391. if (neighbor != null) {
  392. if (neighbor.allWallsIntact()) {
  393. neighborsIntact.add(neighbor);
  394. }
  395. }
  396. }
  397. // if one or more walls
  398. if (neighborsIntact.size() != 0) {
  399. // rand tells you which vertex you are knocking down a wall between
  400. int rand = (int) (myRandom() * neighborsIntact.size());
  401. Vertex knockDown = neighborsIntact.get(rand);
  402. int relationship = currentCell.vertexRelationship(knockDown); // finds relationship between current and knockDown
  403. if (relationship == 0) {// knockDown is above currentCell
  404. currentCell.breakUpWall();
  405. knockDown.breakDownWall();
  406. } else if (relationship == 1) { // knockDown is to the right of currentCell
  407. currentCell.breakRightWall();
  408. knockDown.breakLeftWall();
  409. } else if (relationship == 2) { // knockDown is below currentCell
  410. currentCell.breakDownWall();
  411. knockDown.breakUpWall();
  412. } else { // knockDown is to the left of currentCell
  413. currentCell.breakLeftWall();
  414. knockDown.breakRightWall();
  415. }
  416. // push CurrentCell location on the CellStack
  417. cellStack.push(currentCell);
  418. // make the new cell CurrentCell
  419. currentCell = knockDown;
  420. // add 1 to VisitedCells
  421. visitedCells++;
  422.  
  423. } else {
  424. currentCell = cellStack.pop();
  425. }
  426. }
  427.  
  428. }
  429.  
  430. /*
  431. * Prints empty grid
  432. * Prints all the top walls, the left and right, and the bottom row for an empty Grid
  433. */
  434. public String printGrid() {
  435. String grid = "";
  436. // first print the top layer
  437.  
  438. int n = 2;
  439. for (int i = 0; i < dimension; i++) {
  440. if (i == dimension - 1)
  441. n = 3;
  442. for (int layer = 1; layer <= n; layer++) {
  443. // layer represents the layers of a cell: up, left/right, and down
  444. // top layer already printed; for the rest, print sides and bottom
  445. // 1 = top
  446. // 2 = left and right
  447. // 3 = bottom
  448.  
  449. if (layer == 1) {
  450. grid += "+"; //first symbol of layer 1
  451. }
  452.  
  453. if (layer == 2) {
  454. grid += "|"; //first symbol of layer 2
  455. }
  456.  
  457. if ((layer == 3) && (i == dimension - 1)) {
  458. grid += "+"; //first symbol of layer three
  459. }
  460.  
  461. for (int j = 0; j < dimension; j++) {
  462. Vertex v = vertexList[i][j];
  463.  
  464. // prints according to the layer
  465. // layer one --> print up
  466. if (layer == 1) {
  467. if ((v.walls[0] != 0) && (v.walls[0] != 4)) // if -1, edge wall; if 1, inner wall, 0 is broken wall
  468. grid += "-";
  469. else
  470. grid += " ";
  471.  
  472. grid += "+";
  473. }
  474.  
  475. // layer two --> print left/right and label
  476. else if (layer == 2) {
  477. grid += " ";
  478.  
  479. if (v.walls[1] != 0) // right wall is 1
  480. grid += "|";
  481. else
  482. grid += " ";
  483. }
  484.  
  485. // layer three --> print bottom layer
  486. else if ((layer == 3) && (i == dimension - 1)) {
  487. // down wall
  488. // if there is an down wall, include symbol
  489.  
  490. if ((v.walls[2] != 0) && (v.walls[2] != 4)) // if -1, edge wall; if 1, inner wall, 0 is broken wall, 4 is entrance/exit
  491. grid += "-";
  492. else
  493. grid += " ";
  494.  
  495. grid += "+";
  496.  
  497. }
  498. }
  499. grid += "\n";
  500. }
  501. }
  502. return grid;
  503. }
  504.  
  505. /*
  506. * Prints the grid for BFS and DFS - displays the numbers and the path
  507. *
  508. */
  509. public String printGrid1() {
  510. String grid = "";
  511. // first print the top layer
  512.  
  513. int n = 2;
  514. for (int i = 0; i < dimension; i++) {
  515. if (i == dimension - 1)
  516. n = 3;
  517. for (int layer = 1; layer <= n; layer++) {
  518. // layer represents the layers of a cell: up, left/right, and
  519. // down
  520. // top layer already printed; for the rest, print sides and
  521. // bottom
  522. // 1 = top
  523. // 2 = left and right
  524. // 3 = bottom
  525.  
  526. if (layer == 1) {
  527. grid += "+";
  528. }
  529.  
  530. if (layer == 2) {
  531. grid += "|";
  532. }
  533.  
  534. if ((layer == 3) && (i == dimension - 1)) {
  535. grid += "+";
  536. }
  537.  
  538. for (int j = 0; j < dimension; j++) {
  539. Vertex v = vertexList[i][j];
  540.  
  541. // prints according to the layer
  542. // layer one --> print up
  543. if (layer == 1) {
  544. if ((v.walls[0] != 0) && (v.walls[0] != 4)) // if -1, edge wall; if 1, inner wall, 0 is broken
  545. grid += "-";
  546. else
  547. grid += " ";
  548.  
  549. grid += "+";
  550. }
  551.  
  552. // layer two --> print left/right and label
  553. else if (layer == 2) {
  554.  
  555. // print label
  556.  
  557. if ((v != null) && v == (vertexList[0][0])){
  558. grid += "0";
  559. } else if (v.pi == null) { // don't print label
  560. grid += " ";
  561. } else {
  562. grid += ((v.traverseOrder)%10);
  563. }
  564.  
  565.  
  566. if (v.walls[1] != 0) // right wall is 1
  567. grid += "|";
  568. else
  569. grid += " ";
  570. }
  571.  
  572. // layer three --> print bottom layer
  573. else if ((layer == 3) && (i == dimension - 1)) {
  574. // down wall
  575. // if there is an down wall, include symbol
  576. if ((v.walls[2] != 0) && (v.walls[2] != 4)) // if -1, edge wall; if 1, inner wall, 0 is broken wall, 4 is entry/exit
  577. grid += "-";
  578. else
  579. grid += " ";
  580.  
  581. grid += "+";
  582.  
  583. }
  584. }
  585. grid += "\n";
  586. }
  587. }
  588.  
  589. return grid;
  590. }
  591.  
  592.  
  593. /*
  594. * Prints the maze with the '#'s and not numbers - for BFS and DFS
  595. */
  596. public String printGrid2() {
  597. String grid = "";
  598. // first print the top layer
  599.  
  600. int n = 2;
  601. for (int i = 0; i < dimension; i++) {
  602. if (i == dimension - 1)
  603. n = 3;
  604. for (int layer = 1; layer <= n; layer++) {
  605. // layer represents the layers of a cell: up, left/right, and
  606. // down
  607. // top layer already printed; for the rest, print sides and
  608. // bottom
  609. // 1 = top
  610. // 2 = left and right
  611. // 3 = bottom
  612.  
  613. if (layer == 1) {
  614. grid += "+";
  615. }
  616.  
  617. if (layer == 2) {
  618. grid += "|";
  619. }
  620.  
  621. if ((layer == 3) && (i == dimension - 1)) {
  622. grid += "+";
  623. }
  624.  
  625. for (int j = 0; j < dimension; j++) {
  626. Vertex v = vertexList[i][j];
  627.  
  628. // prints according to the layer
  629. // layer one --> print up
  630. if (layer == 1) {
  631. if ((v.walls[0] != 0) && (v.walls[0] != 4)) // if -1, edge wall; if 1 inner wall if 0 broken wall // wall
  632. grid += "-";
  633. else if (v.equals(startVertex)){
  634. grid += "#";
  635. }
  636. else if (v.inPath && v.getUp() != null && v.getUp().inPath) //makes sure the one above is in path too
  637. grid += "#";
  638. else {
  639. grid += " ";
  640. }
  641.  
  642. grid += "+";
  643. }
  644.  
  645. // layer two --> print left/right and label
  646. else if (layer == 2) {
  647. if (v == null) { // don't print label
  648. grid += " ";
  649. } else if (v.inPath){
  650. grid += (("#"));
  651. } else {
  652. grid += " ";
  653. }
  654.  
  655. if (v.walls[1] != 0) // right wall is 1
  656. grid += "|";
  657. else
  658. grid += " ";
  659. }
  660.  
  661. // layer three --> print bottom layer
  662. else if ((layer == 3) && (i == dimension - 1)) {
  663. // down wall
  664. // if there is an down wall, include symbol
  665.  
  666. if ((v.walls[2] != 0) && (v.walls[2] != 4)) // if -1, edge wall; if 1, inner wall, 0 is broken wall, 4 is entry/exit
  667. grid += "-";
  668. else if (v.inPath)
  669. grid += "#";
  670. else
  671. grid += " ";
  672.  
  673. grid += "+";
  674.  
  675. }
  676. }
  677. grid += "\n";
  678. }
  679. }
  680.  
  681. return grid;
  682. }
  683.  
  684.  
  685. public static void main(String[] args) {
  686. //Runs the program - generate a maze, and solve it with BFS and DFS for a maze of size 4
  687. Graph g = new Graph(4);
  688. g.generateMaze();
  689. System.out.println("Grid: ");
  690. String grid = g.printGrid();
  691. System.out.println(grid);
  692. g.DFS(g.vertexList[0][0]);
  693. String aGrid = g.printGrid1();
  694. System.out.println();
  695. System.out.println("DFS");
  696. System.out.println(aGrid);
  697. g.setPath();
  698. String dGrid = g.printGrid2();
  699. System.out.println();
  700. System.out.println(dGrid);
  701.  
  702. Graph g1 = new Graph(4);
  703. g1.generateMaze();
  704. g1.BFS(g1.vertexList[0][0]);
  705. String bGrid = g1.printGrid1();
  706. System.out.println();
  707. System.out.println("BFS");
  708. System.out.println(bGrid);
  709. g1.setPath();
  710. String cGrid = g1.printGrid2();
  711. System.out.println();
  712. System.out.println(cGrid);
  713. }
  714. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement