Advertisement
Guest User

Untitled

a guest
Dec 13th, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.49 KB | None | 0 0
  1. #include <iostream>
  2. using namespace std;
  3. #include <cmath>
  4. #include <vector>
  5. #include <cassert>
  6. #include <fstream>
  7. #include <cstring>
  8.  
  9. /*************************************
  10. * Data structure for Sokuban
  11. *************************************/
  12. const int GAME_WIDTH = 7;
  13. const int GAME_HEIGHT = 6;
  14.  
  15. enum cell {WALL, EMPTY, EMPTY_DEST, WORKER, WORKER_DEST, BOX, BOX_DEST};
  16. const char cellRepresentation[7] = {'*', ' ', '.', 'w', 'W', 'b', 'B'};
  17.  
  18.  
  19. /*tt
  20. @param x an ascii character
  21. @param success bool; set to false if a char occurs that should not
  22. @return cell representation
  23. */
  24. cell ascii2cell(char x, bool& success)
  25. { //preconditie
  26. assert(true);
  27. //postconditie:
  28. //give corrospondig cell representation
  29. for(int i = 0; i < 7; i++)
  30. if(x == cellRepresentation[i])
  31. return static_cast<cell>(i);
  32.  
  33. cout << "An error occurred (2)" << endl;
  34. success = false;
  35. return WALL; // we have to return something
  36. }
  37.  
  38. /*
  39. @param identifier The challenge identifier.
  40. @param game[][] two-dimensional array reference
  41. @return TRUE if loaded succesfully. FALSE elsewise.
  42. */
  43. bool getChallange(string identifier, cell game[GAME_HEIGHT][GAME_WIDTH])
  44. { //preconditie:
  45. assert(true);
  46. //postconditie:
  47. //Load and return challange
  48. string filename = "challenge." + identifier + ".txt";
  49. cout << "Opening " << filename << " ... " << endl;
  50.  
  51. ifstream infile;
  52. infile.open(filename.c_str());
  53.  
  54. if(!infile.is_open())
  55. return false;
  56. cout << "Opening " << filename << " was succesfull. " << endl;
  57.  
  58. // At this point we are sure the file is open.
  59. // Let's read it and fill the game.
  60. string line = "";
  61. bool success = true;
  62. int y = 0;
  63. while(getline(infile, line) && y < GAME_HEIGHT)
  64. {
  65. for(int x = 0; x < GAME_WIDTH; x++)
  66. game[y][x] = ascii2cell(line[x], success);
  67. y++;
  68. }
  69. if(!success)
  70. return false;
  71. return true;
  72. }
  73.  
  74. /*
  75. @param game[][] two-dimensional array reference
  76. */
  77. void displayGame(cell game[GAME_HEIGHT][GAME_WIDTH])
  78. { //preconditie
  79. assert(true);
  80. //postconditie:
  81. //display game
  82. cout << endl << endl;
  83. for(int y = 0; y < GAME_HEIGHT; y++)
  84. {
  85. for(int x = 0; x < GAME_WIDTH; x++)
  86. cout << cellRepresentation[static_cast<int>(game[y][x])];
  87. cout << endl;
  88. }
  89. }
  90.  
  91.  
  92. /*************************************
  93. * Search
  94. *************************************/
  95. struct Pos {
  96. int x;
  97. int y;
  98. };
  99.  
  100. struct state {
  101. int stateNo;
  102. int parentState;
  103. Pos position;
  104. cell game[GAME_HEIGHT][GAME_WIDTH];
  105. };
  106.  
  107. struct sit
  108. {
  109. bool inFrontOfWall;
  110. bool inFrontOfBox;
  111. bool inFrontOfBoxes;
  112. };
  113.  
  114.  
  115. enum actions {LEFT, RIGHT, UP, DOWN};
  116.  
  117. Pos findTheGuy(cell game[GAME_HEIGHT][GAME_WIDTH])
  118. {
  119. for(int y = 0; y < GAME_HEIGHT; y++)
  120. for(int x = 0; x < GAME_WIDTH; x++)
  121. if(game[y][x] == WORKER || game[y][x] == WORKER_DEST)
  122. return {x, y};
  123. }
  124.  
  125. /*
  126. @param a[][] SOURCE two-dimensional array reference
  127. @param b[][] DESTINATION two-dimensional array reference
  128. */
  129. void copyGame(cell a[GAME_HEIGHT][GAME_WIDTH], cell b[GAME_HEIGHT][GAME_WIDTH])
  130. {
  131. for(int y = 0; y < GAME_HEIGHT; y++)
  132. for(int x = 0; x < GAME_WIDTH; x++)
  133. b[y][x] = a[y][x];
  134. }
  135.  
  136. /*
  137. @param game[][] two-dimensional array reference
  138. @return false if not finished, true elsewise
  139. */
  140. bool isFinished(cell game[GAME_HEIGHT][GAME_WIDTH])
  141. {//preconditie
  142. assert(true);
  143. //postconditie:
  144. //true if game is finished
  145. for(int y = 0; y < GAME_HEIGHT; y++)
  146. for(int x = 0; x < GAME_WIDTH; x++)
  147. if(game[y][x] == BOX)
  148. return false;
  149. return true;
  150. }
  151.  
  152. /*
  153. @param currentState
  154. @param action what will we try to do?
  155. */
  156.  
  157.  
  158. bool legalStep(state currentState, actions action)
  159. {
  160. sit situation = {false, false, false};
  161. int x = currentState.position.x;
  162. int y = currentState.position.y;
  163.  
  164. switch(action)
  165. {
  166. case static_cast<int>(LEFT): {
  167.  
  168. int one = max((x - 1) % GAME_WIDTH, 0 );
  169. int two = max((x - 2) % GAME_WIDTH, 0 );
  170.  
  171. if(currentState.game[y][one] == WALL) {
  172. situation.inFrontOfWall = true;
  173.  
  174. }
  175.  
  176. if(currentState.game[y][one] == BOX ||
  177. currentState.game[y][one] == BOX_DEST)
  178. situation.inFrontOfBox = true;
  179.  
  180. if( currentState.game[y][two] == BOX ||
  181. currentState.game[y][two] == BOX_DEST ||
  182. currentState.game[y][two] == WALL
  183. && situation.inFrontOfBox)
  184. situation.inFrontOfBoxes = true;
  185.  
  186.  
  187. } break;
  188.  
  189. case static_cast<int>(RIGHT): {
  190.  
  191. int one = max((x + 1) % GAME_WIDTH, 0 );
  192. int two = max((x + 2) % GAME_WIDTH, 0 );
  193.  
  194. if(currentState.game[y][one] == WALL) {
  195. situation.inFrontOfWall = true;
  196.  
  197. }
  198.  
  199. if(currentState.game[y][one] == BOX ||
  200. currentState.game[y][one] == BOX_DEST)
  201. situation.inFrontOfBox = true;
  202.  
  203. if( currentState.game[y][two] == BOX ||
  204. currentState.game[y][two] == BOX_DEST ||
  205. currentState.game[y][two] == WALL
  206. && situation.inFrontOfBox)
  207. situation.inFrontOfBoxes = true;
  208.  
  209.  
  210. } break;
  211.  
  212. case static_cast<int>(UP): {
  213.  
  214. int one = max((y - 1) % GAME_HEIGHT, 0 );
  215. int two = max((y - 2) % GAME_HEIGHT, 0 );
  216.  
  217. if(currentState.game[one][x] == WALL) {
  218. situation.inFrontOfWall = true;
  219. }
  220.  
  221. if(currentState.game[one][x] == BOX ||
  222. currentState.game[one][x] == BOX_DEST ||
  223. currentState.game[one][x] == BOX_DEST)
  224. situation.inFrontOfBox = true;
  225.  
  226. if( currentState.game[two][x] == BOX ||
  227. currentState.game[two][x] == WALL
  228. && situation.inFrontOfBox)
  229. situation.inFrontOfBoxes = true;
  230.  
  231.  
  232. } break;
  233.  
  234. case static_cast<int>(DOWN): {
  235.  
  236. int one = max((y + 1) % GAME_HEIGHT, 0 );
  237. int two = max((y + 2) % GAME_HEIGHT, 0 );
  238.  
  239. if(currentState.game[one][x] == WALL) {
  240. situation.inFrontOfWall = true;
  241. }
  242.  
  243. if(currentState.game[one][x] == BOX ||
  244. currentState.game[one][x] == BOX_DEST ||
  245. currentState.game[one][x] == BOX_DEST)
  246. situation.inFrontOfBox = true;
  247.  
  248. if( currentState.game[two][x] == BOX ||
  249. currentState.game[two][x] == WALL
  250. && situation.inFrontOfBox)
  251. situation.inFrontOfBoxes = true;
  252.  
  253.  
  254. } break;
  255.  
  256. default: return false; break;
  257. }
  258. if(situation.inFrontOfWall || situation.inFrontOfBoxes)
  259. return false;
  260. return true;
  261. }
  262.  
  263. /*
  264. @remark left, right, down, up are the same functions.
  265. @param game[][] affecting game
  266. @param position the position of the worker
  267. */
  268.  
  269. void left(cell game[GAME_HEIGHT][GAME_WIDTH], Pos position)
  270. {
  271. int x = position.x;
  272. int y = position.y;
  273. cell guy = game[y][x];
  274. cell viewA = game[y][x - 1]; //state 1 left
  275. cell viewB = game[y][x - 2]; //state 2 left
  276.  
  277. if( guy == WORKER_DEST )
  278. game[y][x] = EMPTY_DEST;
  279. else
  280. game[y][x] = EMPTY;
  281.  
  282. if(viewA == BOX_DEST || viewA == EMPTY_DEST)
  283. game[y][x - 1] = WORKER_DEST;
  284. else
  285. game[y][x - 1] = WORKER;
  286.  
  287. if(viewA == BOX || viewA == BOX_DEST)
  288. {
  289. if(viewB == EMPTY_DEST)
  290. game[y][x - 2] = BOX_DEST;
  291. else
  292. game[y][x - 2] = BOX;
  293. }
  294. }
  295.  
  296. void right(cell game[GAME_HEIGHT][GAME_WIDTH], Pos position)
  297. {
  298. int x = position.x;
  299. int y = position.y;
  300. cell guy = game[y][x];
  301. cell viewA = game[y][x + 1]; //state 1 left
  302. cell viewB = game[y][x + 2]; //state 2 left
  303.  
  304. if( guy == WORKER_DEST )
  305. game[y][x] = EMPTY_DEST;
  306. else
  307. game[y][x] = EMPTY;
  308.  
  309. if(viewA == BOX_DEST || viewA == EMPTY_DEST)
  310. game[y][x + 1] = WORKER_DEST;
  311. else
  312. game[y][x + 1] = WORKER;
  313.  
  314. if(viewA == BOX || viewA == BOX_DEST)
  315. {
  316. if(viewB == EMPTY_DEST)
  317. game[y][x + 2] = BOX_DEST;
  318. else
  319. game[y][x + 2] = BOX;
  320. }
  321. }
  322.  
  323. void down(cell game[GAME_HEIGHT][GAME_WIDTH], Pos position)
  324. {
  325. int x = position.x;
  326. int y = position.y;
  327. cell guy = game[y][x];
  328. cell viewA = game[y + 1][x]; //state 1 left
  329. cell viewB = game[y + 2][x]; //state 2 left
  330.  
  331. if( guy == WORKER_DEST )
  332. game[y][x] = EMPTY_DEST;
  333. else
  334. game[y][x] = EMPTY;
  335.  
  336. if(viewA == BOX_DEST || viewA == EMPTY_DEST)
  337. game[y + 1][x] = WORKER_DEST;
  338. else
  339. game[y + 1][x] = WORKER;
  340.  
  341. if(viewA == BOX || viewA == BOX_DEST)
  342. {
  343. if(viewB == EMPTY_DEST)
  344. game[y + 2][x] = BOX_DEST;
  345. else
  346. game[y + 2][x] = BOX;
  347. }
  348. }
  349.  
  350. void up(cell game[GAME_HEIGHT][GAME_WIDTH], Pos position)
  351. {
  352. int x = position.x;
  353. int y = position.y;
  354. cell guy = game[y][x];
  355. cell viewA = game[y - 1][x]; //state 1 left
  356. cell viewB = game[y - 2][x]; //state 2 left
  357.  
  358. if( guy == WORKER_DEST )
  359. game[y][x] = EMPTY_DEST;
  360. else
  361. game[y][x] = EMPTY;
  362.  
  363. if(viewA == BOX_DEST || viewA == EMPTY_DEST)
  364. game[y - 1][x] = WORKER_DEST;
  365. else
  366. game[y - 1][x] = WORKER;
  367.  
  368. if(viewA == BOX || viewA == BOX_DEST)
  369. {
  370. if(viewB == EMPTY_DEST)
  371. game[y - 2][x] = BOX_DEST;
  372. else
  373. game[y - 2][x] = BOX;
  374. }
  375. }
  376.  
  377. /*
  378. @WARNING Only call this function after legalStep()
  379. @param frontier frontier stack;
  380. @param states a reference to the state history
  381. @param actions direction
  382. @return
  383. */
  384. bool tries(vector<int>& frontier, vector<state>& states, actions action)
  385. {//preconditie:
  386. assert(true);
  387. //postconditie:
  388. //try and evaluate step. Update frontier and state history
  389. state newState = states[frontier.front()];
  390. newState.parentState = frontier.front();
  391. newState.stateNo = states.size();
  392.  
  393. switch(action)
  394. {
  395. case LEFT: left (newState.game, newState.position); break;
  396. case RIGHT: right(newState.game, newState.position); break;
  397. case UP: up (newState.game, newState.position); break;
  398. case DOWN: down (newState.game, newState.position); break;
  399. default: break;
  400. }
  401.  
  402. newState.position = findTheGuy(newState.game);
  403.  
  404. states.push_back(newState);
  405. //displayGame(newState.game);
  406.  
  407.  
  408. frontier.push_back( newState.stateNo );
  409.  
  410. if(isFinished(newState.game))
  411. return true;
  412. return false;
  413. }
  414.  
  415.  
  416. void trace () {
  417. //preconditie:
  418. assert(true);
  419. //postconditie does nothing but make the interface readable.
  420. do
  421. {
  422. cout << '\n' << "Press a key to continue...";
  423. } while (cin.get() != '\n');
  424. }
  425.  
  426. /*
  427. @param frontier
  428. */
  429. void dumpFrontier (vector<int> frontier) {
  430. //preconditie:
  431. assert(true);
  432. //postconditie:
  433. //print the integer vector.
  434. cout << '(';
  435. for(int i = 0; i < frontier.size(); i++)
  436. cout << frontier[i] << ',';
  437. cout << ')';
  438. }
  439.  
  440. /*
  441. @param states
  442. @param lastNO The stateNo of the solution state.
  443. */
  444. void traceBack (vector<state>& states, int lastNO)
  445. { //preconditie
  446. assert(lastNO > 0);
  447. //postconditie:
  448. //Inform the player about what strategy we found
  449.  
  450. vector<int> sequence;
  451. sequence.push_back(lastNO);
  452.  
  453. while(lastNO != -1)
  454. {
  455. sequence.push_back(states[lastNO].parentState);
  456. lastNO = states[lastNO].parentState;
  457. }
  458. dumpFrontier(sequence);
  459. for(int i = sequence.size() - 2; i >= 0; i--) {
  460. // -2 because skip -1 (superparent)
  461. displayGame(states[sequence[i]].game);
  462. trace();
  463. }
  464. }
  465.  
  466. void bfsSolve(cell game[GAME_HEIGHT][GAME_WIDTH])
  467. { //preconditie
  468. assert(true);
  469. //postconditie:
  470. //Finds a solution using BFS
  471.  
  472. vector<state> states;
  473. vector<int> frontier;
  474. frontier.push_back(0);
  475. Pos position = findTheGuy(game);
  476. states.push_back( {0, -1, position} );
  477.  
  478. copyGame(game, states[0].game);
  479.  
  480. bool foundSolution = false;
  481. state finishState;
  482. while( !foundSolution && frontier.size() != 0 )
  483. {
  484. //trace();
  485. if(frontier.front() % 10000 == 0)
  486. cout << "StateNO : " << frontier.front() << endl;
  487. //dumpFrontier(frontier);
  488.  
  489. //trace();
  490. if( legalStep(states[frontier.front() ], LEFT) ) {
  491. foundSolution = tries(frontier, states, LEFT);
  492. if(foundSolution)
  493. finishState = states.back();
  494. }
  495.  
  496. if( legalStep(states[frontier.front() ], RIGHT) ) {
  497. foundSolution = tries(frontier, states, RIGHT);
  498. if(foundSolution)
  499. finishState = states.back();
  500. }
  501.  
  502. if( legalStep(states[ frontier.front() ], DOWN) ) {
  503. foundSolution = tries(frontier, states, DOWN);
  504. if(foundSolution)
  505. finishState = states.back();
  506. }
  507.  
  508. if( legalStep(states[ frontier.front() ], UP) ) {
  509. foundSolution = tries(frontier, states, UP);
  510. if(foundSolution)
  511. finishState = states.back();
  512. }
  513.  
  514. frontier.erase(frontier.begin());
  515.  
  516. }
  517.  
  518. cout << "Found a solution! Here is a traceback: " << endl;
  519. trace();
  520. traceBack(states, finishState.stateNo);
  521. }
  522.  
  523.  
  524. /*
  525. @param states
  526. @param lastNO The stateNo of the solution state.
  527. */
  528. int countSteps (vector<state>& states, int lastNO)
  529. { //preconditie
  530. assert(lastNO > 0);
  531. //postconditie:
  532. //Inform the player about what strategy we found
  533.  
  534. vector<int> sequence;
  535. sequence.push_back(lastNO);
  536.  
  537. while(lastNO != -1)
  538. {
  539. sequence.push_back(states[lastNO].parentState);
  540. lastNO = states[lastNO].parentState;
  541. }
  542. return sequence.size();
  543. }
  544.  
  545.  
  546. void dfsSolve(vector<state>& attempt, vector<state>& shortest, int depth);
  547.  
  548. void dump_attempt(vector<state>& attempt)
  549. {
  550. cout << "Trace back:" << endl;
  551. for(int i = 0; i < attempt.size(); i++) {
  552. displayGame(attempt[i].game);
  553. if(isFinished(attempt[i].game))
  554. {
  555. cout << "It took less steps than expected! Finished. " << endl;
  556. return;
  557. }
  558. trace();
  559. }
  560. }
  561.  
  562. void dfsTries(vector<state>& attempt, vector<state>& shortest, int depth, actions action)
  563. {//preconditie:
  564. assert(true);
  565. //postconditie:
  566. //try and evaluate step. Update frontier and state history
  567. state newState = attempt[attempt.size() - 1];
  568. newState.parentState = 1; // not relevant for DFS, but must be set.
  569. newState.stateNo = attempt.size();
  570.  
  571. switch(action)
  572. {
  573. case LEFT: left (newState.game, newState.position); break;
  574. case RIGHT: right(newState.game, newState.position); break;
  575. case UP: up (newState.game, newState.position); break;
  576. case DOWN: down (newState.game, newState.position); break;
  577. default: break;
  578. }
  579. //displayGame(newState.game);
  580.  
  581. newState.position = findTheGuy(newState.game);
  582. attempt.push_back(newState);
  583. dfsSolve(attempt, shortest, depth);
  584.  
  585. //displayGame(newState.game);
  586.  
  587. if (isFinished(newState.game)) {
  588. shortest = attempt;
  589. cout << endl <<
  590. "Found a solution! It takes " << attempt.size() << " steps. " <<
  591. "Type --trace to trace $ ";
  592. string input = "";
  593.  
  594. getline(cin, input);
  595. while(input == "--trace")
  596. {
  597. dump_attempt(shortest);
  598. cout << "Type --trace to trace $ ";
  599.  
  600. getline(cin, input);
  601. }
  602. }
  603. attempt.pop_back();
  604. }
  605.  
  606.  
  607. void dfsSolve(vector<state>& attempt, vector<state>& shortest, int depth)
  608. { //preconditie
  609. assert(depth > 0);
  610.  
  611. const int CURRENT = attempt.size();
  612. const int BEST = shortest.size();
  613.  
  614. if (BEST > 0 && CURRENT >= BEST) return;
  615. else if (CURRENT > depth + 1) return;
  616.  
  617.  
  618.  
  619. state curr = attempt[attempt.size() - 1];
  620.  
  621. if( legalStep(curr, LEFT) )
  622. dfsTries(attempt, shortest, depth, LEFT);
  623.  
  624. curr = attempt[attempt.size() - 1];
  625.  
  626. if( legalStep(curr, RIGHT) )
  627. dfsTries(attempt, shortest, depth, RIGHT);
  628.  
  629. curr = attempt[attempt.size() - 1];
  630.  
  631. if( legalStep(curr, UP) )
  632. dfsTries(attempt, shortest, depth, UP);
  633.  
  634. curr = attempt[attempt.size() - 1];
  635.  
  636. if( legalStep(curr, DOWN) )
  637. dfsTries(attempt, shortest, depth, DOWN);
  638.  
  639.  
  640. }
  641.  
  642. void dfsSolveCATCH(vector<state>& attempt, vector<state>& shortest, int depth)
  643. {
  644. dfsSolve(attempt, shortest, depth);
  645. cout << endl << endl;
  646. cout << "There are not more options to investigate. "
  647. << "Here is the last solution we found:" << endl;
  648. dump_attempt(shortest);
  649. }
  650. /*
  651. struct state {
  652. int stateNo;
  653. int parentState;
  654. Pos position;
  655. cell game[GAME_HEIGHT][GAME_WIDTH];
  656. };*/
  657.  
  658.  
  659. void welcome_screen(cell game[GAME_HEIGHT][GAME_WIDTH],string puzzleNumber)
  660. {
  661. //pre-condition
  662. assert(true);
  663. //postcondition:
  664. //A welcome message is displayed in the console for the user with the selected puzzle
  665. cout << "Welcome to Sokuban solver" << endl << endl;
  666. if(!getChallange(puzzleNumber,game))
  667. {
  668. cout << "An error occurred (1)" << endl;
  669. return;
  670. }
  671.  
  672. displayGame(game);
  673. cout << endl;
  674. }
  675.  
  676. void options_screen(cell game[GAME_HEIGHT][GAME_WIDTH],string input)
  677. {
  678. //pre-condition
  679. assert(true);
  680. //postcondition:
  681. //waits for user input to start the option menu, here the desired search pattern can be selected and executed
  682. cout<< "press any key to open options"<<endl;
  683. while(getline(cin, input))
  684. {
  685. if(input == "bfs")
  686. bfsSolve(game);
  687. if(input == "dfs")
  688. {
  689. cout << "Give an integervalue for the depth-bound $ ";
  690. int depth = 0;
  691. cin >> depth;
  692.  
  693. state initial = {-1, -1, findTheGuy(game)};
  694. copyGame(game, initial.game);
  695. vector<state> states;
  696. states.push_back(initial);
  697.  
  698. vector<state> shortest;
  699.  
  700. dfsSolveCATCH(states, shortest, depth);
  701. }
  702. if(input == "--exit")
  703. return;
  704. cout << "Enter bfs, dfs or --exit to continue $ ";
  705. }
  706. }
  707.  
  708. int main()
  709. {
  710. string input="";
  711. cell game[GAME_HEIGHT][GAME_WIDTH];
  712. welcome_screen(game,"23");
  713. options_screen(game,input);
  714. }
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731. //scrollable
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement