Advertisement
Guest User

Untitled

a guest
Dec 7th, 2019
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.19 KB | None | 0 0
  1. // Project 5
  2.  
  3. #include <iostream>
  4. #include <limits.h>
  5. #include "d_except.h"
  6. #include <list>
  7. #include <fstream>
  8. #include "d_matrix.h"
  9. #include "graph.h"
  10. #include <queue>
  11.  
  12. using namespace std;
  13.  
  14. class maze
  15. {
  16. public:
  17. maze(ifstream& fin);
  18. void print(int, int, int, int);
  19. bool isLegal(int i, int j);
  20.  
  21. void setMap(int i, int j, int n);
  22. int getMap(int i, int j) const;
  23. void findEdges(int i, int j, graph& g);
  24. void mapMazeToGraph(graph& g);
  25. void findPathRecursive(graph& g, int nodeID);
  26. bool isSolved(graph& g, int nodeID);
  27. void findPathNonRecursive(graph& g, int startNode);
  28. vector<int> findUnvisitedNeighbors(graph& g, int nodeID);
  29. bool findShortestPath1(graph& g, int startNode);
  30. bool findShortestPath2(graph& g, int startNode, int endNode);
  31. void markAllNodesUnvisited(graph& g);
  32. vector<int> findNodeCoords(graph& g, int nodeID);
  33.  
  34. private:
  35. int rows; // number of rows in the maze
  36. int cols; // number of columns in the maze
  37. bool mazeSolved = false;
  38. matrix<bool> value;
  39. matrix<int> map; // Mapping from maze (i,j) values to node index values
  40. stack<int> nodeStack;
  41. };
  42.  
  43. void maze::markAllNodesUnvisited(graph& g)
  44. {
  45. for (int i = 0; i < g.numNodes(); i++)
  46. g.unVisit(i);
  47. }
  48.  
  49. void maze::setMap(int i, int j, int n)
  50. // Set mapping from maze cell (i,j) to graph node n.
  51. {
  52. map[i][j] = n;
  53. }
  54.  
  55. int maze::getMap(int i, int j) const
  56. // Return mapping of maze cell (i,j) in the graph.
  57. {
  58. return map[i][j];
  59. }
  60.  
  61. bool maze::isSolved(graph& g, int nodeID)
  62. // Returns true if the current nodeID is the exit node
  63. // Exit node is bottom right corner, or total num of nodes - 1
  64. // == rows * cols - 1
  65. {
  66. if (nodeID == g.numNodes() - 1)
  67. {
  68. mazeSolved = true;
  69. return true;
  70. }
  71. else
  72. return false;
  73. }
  74.  
  75. maze::maze(ifstream& fin)
  76. // Initializes a maze by reading values from fin. Assumes that the
  77. // number of rows and columns indicated in the file are correct.
  78. {
  79. fin >> rows;
  80. fin >> cols;
  81.  
  82. char x;
  83.  
  84. value.resize(rows, cols);
  85. for (int i = 0; i <= rows - 1; i++)
  86. for (int j = 0; j <= cols - 1; j++)
  87. {
  88. fin >> x;
  89. if (x == 'O')
  90. value[i][j] = true;
  91. else
  92. value[i][j] = false;
  93. }
  94.  
  95. map.resize(rows, cols);
  96. }
  97.  
  98. void maze::print(int goalI, int goalJ, int currI, int currJ)
  99. // Print out a maze, with the goal and current cells marked on the
  100. // board.
  101. {
  102. std::cout << endl;
  103.  
  104. if (goalI < 0 || goalI > rows || goalJ < 0 || goalJ > cols)
  105. throw rangeError("Bad value in maze::print");
  106.  
  107. if (currI < 0 || currI > rows || currJ < 0 || currJ > cols)
  108. throw rangeError("Bad value in maze::print");
  109.  
  110. for (int i = 0; i <= rows - 1; i++)
  111. {
  112. for (int j = 0; j <= cols - 1; j++)
  113. {
  114. if (i == goalI && j == goalJ)
  115. std::cout << "*";
  116. else
  117. if (i == currI && j == currJ)
  118. std::cout << "+";
  119. else
  120. if (value[i][j])
  121. std::cout << " ";
  122. else
  123. std::cout << "X";
  124. }
  125. std::cout << endl;
  126. }
  127. std::cout << endl;
  128. }
  129.  
  130. bool maze::isLegal(int i, int j)
  131. // Return the value stored at the (i,j) entry in the maze.
  132. {
  133. if (i < 0 || i > rows || j < 0 || j > cols)
  134. throw rangeError("Bad value in maze::isLegal");
  135.  
  136. return value[i][j];
  137. }
  138.  
  139. vector<int> maze::findNodeCoords(graph& g, int nodeID)
  140. // Find corresponding i and j coords of passed nodeID
  141. {
  142. vector<int> coords;
  143.  
  144. for (int i = 0; i < rows; i++)
  145. {
  146. for (int j = 0; j < cols; j++)
  147. {
  148. if (map[i][j] == nodeID)
  149. {
  150. coords.push_back(i);
  151. coords.push_back(j);
  152. return coords;
  153. }
  154. }
  155. }
  156. }
  157.  
  158. void maze::findEdges(int i, int j, graph& g)
  159. // Finds all possible edges.
  160. // Need to check for redundant edge creation (e.g. A->B & B->A)
  161. {
  162. // Up direction
  163. if (i - 1 >= 0 && isLegal(i - 1, j))
  164. g.addEdge(map[i][j], map[i - 1][j], 1);
  165. // Down direction
  166. if (i + 1 < rows && isLegal(i + 1, j))
  167. g.addEdge(map[i][j], map[i + 1][j], 1);
  168. // Left direction
  169. if (j - 1 >= 0 && isLegal(i, j - 1))
  170. g.addEdge(map[i][j], map[i][j - 1], 1);
  171. // Right direction
  172. if (j + 1 < cols && isLegal(i, j + 1))
  173. g.addEdge(map[i][j], map[i][j + 1], 1);
  174. }
  175.  
  176. void maze::mapMazeToGraph(graph& g)
  177. // Create a graph g that represents the legal moves in the maze m.
  178. {
  179. for (int i = 0; i < rows; i++)
  180. {
  181. for (int j = 0; j < cols; j++)
  182. {
  183. if (value[i][j] == true)
  184. setMap(i, j, g.addNode(1));
  185. else
  186. //No route here
  187. map[i][j] = -1;
  188. }
  189. }
  190.  
  191. // All possible nodes added.
  192. // Now add edges between nodes
  193. for (int i = 0; i < rows; i++)
  194. {
  195. for (int j = 0; j < cols; j++)
  196. {
  197. if (map[i][j] != -1)
  198. findEdges(i, j, g);
  199. }
  200. }
  201. }
  202.  
  203. vector<int> maze::findUnvisitedNeighbors(graph& g, int nodeID)
  204. {
  205. vector<int> unvisitedNeighbors;
  206.  
  207. for (int i = 0; i < g.numNodes(); i++)
  208. {
  209. if (!g.isVisited(i) && g.isEdge(nodeID, i))
  210. unvisitedNeighbors.push_back(i);
  211. }
  212.  
  213. return unvisitedNeighbors;
  214. }
  215.  
  216. void maze::findPathRecursive(graph& g, int nodeID)
  217. // Find the correct path recursively
  218. {
  219. vector<int> visitOrder;
  220. vector<int> nodeCoords;
  221.  
  222. g.visit(nodeID);
  223.  
  224. // Base case 1: no path exists
  225. if (!isSolved(g, nodeID) && g.allNodesVisited())
  226. {
  227. std::cout << "No path exists." << endl;
  228. return;
  229. }
  230. // Base case 2: maze solved
  231. else if (isSolved(g, nodeID))
  232. {
  233. std::cout << "Maze is solved!" << endl;
  234. return;
  235. }
  236. else
  237. {
  238. for (int i = 0; i < g.numNodes(); i++)
  239. {
  240. if (g.isEdge(nodeID, i) && !g.isVisited(i) && nodeID != i)
  241. {
  242. if (!isSolved(g, i))
  243. {
  244. findPathRecursive(g, i);
  245. }
  246. }
  247. if (mazeSolved)
  248. {
  249. visitOrder.push_back(i);
  250. // Print travel order
  251. for (int i = visitOrder.size() - 1; i >= 0; i--)
  252. {
  253. nodeCoords = findNodeCoords(g, visitOrder[i]);
  254. print(rows, cols, nodeCoords[0], nodeCoords[1]);
  255. }
  256. return;
  257. }
  258. }
  259. }
  260. }
  261.  
  262. void maze::findPathNonRecursive(graph& g, int startNode)
  263. // Use queue based nonrecursive method
  264. {
  265. int v;
  266. vector<int> unvisitedNeighbors;
  267. vector<int> nodeCoords;
  268. vector<int> visitOrder;
  269. // Mark all vertcies as unvisited
  270. markAllNodesUnvisited(g);
  271.  
  272. //Push start vertex into queue, mark as visited
  273. queue<int> q;
  274. q.push(startNode);
  275. g.visit(startNode);
  276.  
  277. while (!q.empty())
  278. {
  279. v = q.front();
  280. unvisitedNeighbors = findUnvisitedNeighbors(g, v);
  281.  
  282. for (int i = 0; i < unvisitedNeighbors.size(); i++)
  283. {
  284. g.visit(unvisitedNeighbors[i]);
  285. q.push(unvisitedNeighbors[i]); //Visit order
  286. }
  287.  
  288. visitOrder.push_back(q.front());
  289.  
  290. q.pop(); //Finish order
  291.  
  292. }
  293.  
  294. cout << visitOrder.back() << endl;
  295.  
  296. // No path available
  297. if (g.allNodesVisited() && !isSolved(g, visitOrder.back()))
  298. cout << "No path available!" << endl;
  299. else
  300. {
  301. // Print travel order
  302. for (int i = 0; i < visitOrder.size(); i++)
  303. {
  304. nodeCoords = findNodeCoords(g, visitOrder[i]);
  305. print(rows, cols, nodeCoords[0], nodeCoords[1]);
  306. }
  307. }
  308. }
  309.  
  310. bool maze::findShortestPath1(graph& g, int startNode)
  311. // Uses BFS to find shortest path through maze
  312. {
  313. int v;
  314. vector<int> unvisitedNeighbors;
  315. vector<int> nodeCoords;
  316. vector<int> visitOrder;
  317. // Predecessor node vector
  318. vector<int> pred(g.numNodes(), -1);
  319.  
  320. // Mark all vertcies as unvisited
  321. markAllNodesUnvisited(g);
  322.  
  323. // Push start vertex into queue, mark as visited
  324. queue<int> q;
  325. q.push(startNode);
  326. g.visit(startNode);
  327.  
  328. while (!q.empty())
  329. {
  330. v = q.front();
  331. unvisitedNeighbors = findUnvisitedNeighbors(g, v);
  332.  
  333. for (int i = 0; i < unvisitedNeighbors.size(); i++)
  334. {
  335. g.visit(unvisitedNeighbors[i]);
  336. q.push(unvisitedNeighbors[i]); //Visit order
  337. pred[unvisitedNeighbors[i]] = v;
  338. }
  339.  
  340. visitOrder.push_back(q.front());
  341.  
  342. q.pop(); //Finish order
  343.  
  344. }
  345.  
  346. cout << visitOrder.back() << endl;
  347.  
  348. // No path available
  349. if (g.allNodesVisited() && !isSolved(g, visitOrder.back()))
  350. {
  351. cout << "No path available!" << endl;
  352. return false;
  353. }
  354. else
  355. {
  356. //Find shortest path using pred vector
  357.  
  358. int currNode = visitOrder.back(); //necessary???
  359.  
  360. vector<int> shortestPath;
  361. shortestPath.push_back(visitOrder.back());
  362. while (currNode != visitOrder.front())
  363. {
  364. shortestPath.push_back(pred[currNode]);
  365. currNode = pred[currNode];
  366. }
  367.  
  368. // Print shortest path travel order
  369. cout << "The shortest path found using BFS: " << endl;
  370. for (int i = shortestPath.size() - 1; i >= 0; i--)
  371. {
  372. nodeCoords = findNodeCoords(g, shortestPath[i]);
  373. print(rows, cols, nodeCoords[0], nodeCoords[1]);
  374. }
  375.  
  376. return true;
  377. }
  378.  
  379. }
  380.  
  381. bool maze::findShortestPath2(graph& g, int startNode, int endNode)
  382. // Uses Dijkstra's algorithm to find shortest path through maze
  383. {
  384. cout << "Now in Dijkstra function" << endl;
  385. //Vector of nodes of shortest path
  386. vector<int> shortestPath;
  387. //Priority queue for nodes
  388. std::priority_queue<node> pq;
  389. //Set shortest path for all vertices to infinity
  390. //vector<int> shortestPath(g.numNodes(), INT_MAX);
  391. for (int i = 0; i <= endNode; i++)
  392. {
  393. g.setNodeWeight(0, 0);
  394. g.setNodeWeight(i, INT_MAX);
  395. }
  396.  
  397. cout << "all node weights initialized" << endl;
  398. //Mark all nodes unvisited
  399. markAllNodesUnvisited(g);
  400.  
  401. /*
  402. //Push all vertcies into priorityQueue
  403. pq.push
  404.  
  405. //while the pq is not empty and the path is not found
  406. //pop vertex v off the priority queue if v == endvertex
  407. //else for all unvisited neighbors w of v SP(w) = min (SP(w), SP(v) + weight(w,v))
  408. //if newest shortest path, set parent(w) = v
  409.  
  410. */
  411. return true;
  412.  
  413. }
  414.  
  415.  
  416. int main()
  417. {
  418. char x;
  419. ifstream fin;
  420.  
  421. // Read the maze from the file.
  422. string fileName = "maze1.txt";
  423.  
  424. fin.open(fileName.c_str());
  425. if (!fin)
  426. {
  427. cerr << "Cannot open " << fileName << endl;
  428. exit(1);
  429. }
  430.  
  431. try
  432. {
  433. graph g;
  434. while (fin && fin.peek() != 'Z')
  435. {
  436. maze m(fin);
  437. //m.mapMazeToGraph(g);
  438. cout << "Mapping to graph " << endl;
  439.  
  440. /*
  441. // Recursive method
  442. cout << "Recursive method: " << endl;
  443. m.findPathRecursive(g, 0);
  444.  
  445.  
  446. // Nonrecursive method
  447. cout << "NonRecursive method: " << endl;
  448. m.findPathNonRecursive(g, 0);*/
  449.  
  450. /* // Find shortest path 1
  451. cout << "Running BFS!" << endl;
  452. m.findShortestPath1(g, 0);
  453. */
  454. // Find shortest path 2
  455. cout << "Running Dijkstra!" << endl;
  456. m.findShortestPath2(g, 0, 70);
  457. }
  458. }
  459. catch (indexRangeError & ex)
  460. {
  461. cout << ex.what() << endl; exit(1);
  462. }
  463. catch (rangeError & ex)
  464. {
  465. cout << ex.what() << endl; exit(1);
  466. }
  467.  
  468. cin.get();
  469. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement