Advertisement
PIBogdanov

The Labyrinth

Feb 12th, 2023
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.01 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4. #include <Windows.h>
  5. #include <ctype.h>
  6. #include <random>
  7. #include <chrono>
  8. #include <thread>
  9. #include <conio.h>
  10.  
  11. using namespace std;
  12.  
  13. string player = "O";
  14.  
  15. int playerX = 1;
  16.  
  17. int playerY = 0;
  18.  
  19. int originalPlayerX = playerX;
  20.  
  21. int originalPlayerY = playerY;
  22.  
  23. int mainMenu();
  24.  
  25. void gameStart();
  26.  
  27. void customGame();
  28.  
  29. void gameControls();
  30.  
  31. void gameCredits();
  32.  
  33. void exitProgram();
  34.  
  35. int difficultyMenu();
  36.  
  37. void easyDifficulty();
  38.  
  39. void normalDifficulty();
  40.  
  41. void hardDifficulty();
  42.  
  43. void backToMenu();
  44.  
  45. void characterMove(string**, int&, int&, int, int);
  46.  
  47. void playerMove(string**);
  48.  
  49. void display(string**, int, int, int, string);
  50.  
  51. void loadMap(string, int, string);
  52.  
  53. void levels(string);
  54.  
  55. void ShowConsoleCursor(bool showFlag);
  56.  
  57. int main()
  58. {
  59.     system("color 04");
  60.  
  61.     ShowWindow(GetConsoleWindow(), SW_MAXIMIZE);
  62.  
  63.     SendMessage(GetConsoleWindow(), WM_SYSKEYDOWN, VK_RETURN, 0x2000000);
  64.  
  65.     ShowConsoleCursor(false);
  66.  
  67.     mainMenu();
  68.  
  69.     return 0;
  70. }
  71.  
  72. typedef void(*menuOptions)();
  73.  
  74. menuOptions mainMenuOptions[] = { gameStart, customGame, gameControls, gameCredits, exitProgram };
  75.  
  76. int mainMenu()
  77. {
  78.     string menu[5] = { "Start Game", "Create a Custom Game", "Controls", "Credits", "Exit" };
  79.  
  80.     int pointer = 0;
  81.  
  82.     bool lastUpKeyState = false;
  83.  
  84.     bool lastDownKeyState = false;
  85.  
  86.     bool lastReturnKeyState = false;
  87.  
  88.     bool arrowVisible = true;
  89.  
  90.     while (true)
  91.     {
  92.         system("cls");
  93.  
  94.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  95.  
  96.         cout << "The Labyrinth" << "\n" << "\n";
  97.  
  98.         cout << "Main Menu" << "\n" << "\n";
  99.  
  100.         for (int i = 0; i < 5; i++)
  101.         {
  102.             if (i == pointer)
  103.             {
  104.                 if (arrowVisible)
  105.                 {
  106.                     cout << "-> ";
  107.  
  108.                     arrowVisible = false;
  109.                 }
  110.  
  111.                 else
  112.                 {
  113.                     cout << "    "; // Prints 4 spaces to cover the previous "-> "
  114.  
  115.                     arrowVisible = true;
  116.                 }
  117.  
  118.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  119.  
  120.                 cout << menu[i] << endl;
  121.             }
  122.  
  123.             else
  124.             {
  125.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  126.  
  127.                 cout << menu[i] << endl;
  128.             }
  129.         }
  130.  
  131.         bool upKeyState = GetAsyncKeyState(VK_UP);
  132.  
  133.         if (upKeyState && !lastUpKeyState)
  134.         {
  135.             pointer -= 1;
  136.  
  137.             if (pointer == -1)
  138.             {
  139.                 pointer = 4;
  140.             }
  141.         }
  142.  
  143.         lastUpKeyState = upKeyState;
  144.  
  145.         bool downKeyState = GetAsyncKeyState(VK_DOWN);
  146.  
  147.         if (downKeyState && !lastDownKeyState)
  148.         {
  149.             pointer += 1;
  150.  
  151.             if (pointer == 5)
  152.             {
  153.                 pointer = 0;
  154.             }
  155.         }
  156.  
  157.         lastDownKeyState = downKeyState;
  158.  
  159.         bool returnKeyState = GetAsyncKeyState(VK_RETURN);
  160.  
  161.         if (returnKeyState && !lastReturnKeyState)
  162.         {
  163.             mainMenuOptions[pointer]();
  164.         }
  165.  
  166.         lastReturnKeyState = returnKeyState;
  167.  
  168.         this_thread::sleep_for(chrono::milliseconds(200));
  169.     }
  170. }
  171.  
  172. void gameStart()
  173. {
  174.     difficultyMenu();
  175. }
  176.  
  177. void customGame()
  178. {
  179.     system("cls");
  180. }
  181.  
  182. void gameControls()
  183. {
  184.     system("cls");
  185.  
  186.     cout << "\n";
  187.  
  188.     cout << "  --------------CONTROLS---------------" << "\n";
  189.     cout << "  |                                   |" << "\n";
  190.     cout << "  |                                   |" << "\n";
  191.     cout << "  |   ^ --> Up Arrow to move up       |" << "\n";
  192.     cout << "  |   < --> Left Arrow to move left   |" << "\n";
  193.     cout << "  |   > --> Right Arrow to move right |" << "\n";
  194.     cout << "  |   v --> Down Arrow to move down   |" << "\n";
  195.     cout << "  |                                   |" << "\n";
  196.     cout << "  |   Enter / Return --> Enter        |" << "\n";
  197.     cout << "  |   Escape --> Back                 |" << "\n";
  198.     cout << "  |                                   |" << "\n";
  199.     cout << "  |                                   |" << "\n";
  200.     cout << "  -------------------------------------" << "\n";
  201.  
  202.     while (true)
  203.     {
  204.         backToMenu();
  205.     }
  206.  
  207.     this_thread::sleep_for(chrono::seconds(1));
  208. }
  209.  
  210. void gameCredits()
  211. {
  212.     system("cls");
  213.  
  214.     cout << "Thanks for playing!" << "\n";
  215.  
  216.     cout << "\n";
  217.  
  218.     cout << "Creator: Petar Bogdanov" << "\n";
  219.  
  220.     cout << "The people who helped me with this project: eng. Stoyan Filipov and eng. Monika Gencheva" << "\n";
  221.  
  222.     while (true)
  223.     {
  224.         backToMenu();
  225.     }
  226.  
  227.     this_thread::sleep_for(chrono::seconds(1));
  228. }
  229.  
  230. void exitProgram()
  231. {
  232.     exit(0);
  233. }
  234.  
  235. menuOptions difficultyMenuOptions[] = { easyDifficulty, normalDifficulty, hardDifficulty };
  236.  
  237. int difficultyMenu()
  238. {
  239.     string difficulty[3] = { "Easy", "Normal", "Hard" };
  240.  
  241.     int pointer = 0;
  242.  
  243.     bool lastUpKeyState = false;
  244.  
  245.     bool lastDownKeyState = false;
  246.  
  247.     bool lastReturnKeyState = false;
  248.  
  249.     bool arrowVisible = true;
  250.  
  251.     while (true)
  252.     {
  253.         system("cls");
  254.  
  255.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  256.  
  257.         cout << "Choose difficulty" << "\n" << "\n";
  258.  
  259.         for (int i = 0; i < 3; i++)
  260.         {
  261.             if (i == pointer)
  262.             {
  263.                 if (arrowVisible)
  264.                 {
  265.                     cout << "-> ";
  266.  
  267.                     arrowVisible = false;
  268.                 }
  269.                 else
  270.                 {
  271.                     cout << "    "; // Prints 4 spaces to cover the previous "-> "
  272.  
  273.                     arrowVisible = true;
  274.                 }
  275.  
  276.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  277.  
  278.                 cout << difficulty[i] << endl;
  279.             }
  280.  
  281.             else
  282.             {
  283.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  284.  
  285.                 cout << difficulty[i] << endl;
  286.             }
  287.         }
  288.  
  289.         bool upKeyState = GetAsyncKeyState(VK_UP);
  290.  
  291.         if (upKeyState && !lastUpKeyState)
  292.         {
  293.             pointer -= 1;
  294.  
  295.             if (pointer == -1)
  296.             {
  297.                 pointer = 2;
  298.             }
  299.         }
  300.  
  301.         lastUpKeyState = upKeyState;
  302.  
  303.         bool downKeyState = GetAsyncKeyState(VK_DOWN);
  304.  
  305.         if (downKeyState && !lastDownKeyState)
  306.         {
  307.             pointer += 1;
  308.  
  309.             if (pointer == 3)
  310.             {
  311.                 pointer = 0;
  312.             }
  313.         }
  314.  
  315.         lastDownKeyState = downKeyState;
  316.  
  317.         bool returnKeyState = GetAsyncKeyState(VK_RETURN);
  318.  
  319.         if (returnKeyState && !lastReturnKeyState)
  320.         {
  321.             difficultyMenuOptions[pointer]();
  322.         }
  323.  
  324.         backToMenu();
  325.  
  326.         lastReturnKeyState = returnKeyState;
  327.  
  328.         this_thread::sleep_for(chrono::milliseconds(200));
  329.     }
  330. }
  331.  
  332. void easyDifficulty()
  333. {
  334.     levels("easy");
  335. }
  336.  
  337. void normalDifficulty()
  338. {
  339.     levels("normal");
  340. }
  341.  
  342. void hardDifficulty()
  343. {
  344.     levels("hard");
  345. }
  346.  
  347. void backToMenu()
  348. {
  349.     if (GetAsyncKeyState(VK_ESCAPE))
  350.     {
  351.         main();
  352.     }
  353. }
  354.  
  355. void characterMove(string** labyrinth, int& x, int& y, int dx, int dy)
  356. {
  357.     if (labyrinth[x + dx][y + dy] == "S" || labyrinth[x + dx][y + dy] == " " || labyrinth[x + dx][y + dy] == "E")
  358.     {
  359.         x += dx;
  360.         y += dy;
  361.     }
  362. }
  363.  
  364. void playerMove(string** labyrinth)
  365. {
  366.     char key = _getch();
  367.  
  368.     if (key == 72) // The ASCII CODE FOR THE UP ARROW KEY
  369.     {
  370.         characterMove(labyrinth, playerX, playerY, -1, 0);
  371.     }
  372.  
  373.     else if (key == 75) // The ASCII CODE FOR THE LEFT ARROW KEY
  374.     {
  375.         characterMove(labyrinth, playerX, playerY, 0, -1);
  376.     }
  377.  
  378.     else if (key == 80) // The ASCII CODE FOR THE DOWN ARROW KEY
  379.     {
  380.         characterMove(labyrinth, playerX, playerY, 1, 0);
  381.     }
  382.  
  383.     else if (key == 77) // The ASCII CODE FOR THE RIGHT ARROW KEY
  384.     {
  385.         characterMove(labyrinth, playerX, playerY, 0, 1);
  386.     }
  387. }
  388.  
  389. void display(string** labyrinth, int rowsCount, int columnsCount, int level, string levelType)
  390. {
  391.     bool breakAfterRender = false;
  392.  
  393.     while (true)
  394.     {
  395.         system("cls");
  396.  
  397.         cout << "Difficulty: " << levelType << "\n";
  398.         cout << "Level: " << level << " / 10" << "\n" << "\n";
  399.  
  400.         int colour = rand() % 15 + 1;
  401.  
  402.         for (int i = 0; i < rowsCount; i++)
  403.         {
  404.             for (int j = 0; j < columnsCount; j++)
  405.             {
  406.                 if ((i == playerX) && (j == playerY))
  407.                 {
  408.                     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colour);
  409.  
  410.                     cout << player;
  411.  
  412.                     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
  413.                 }
  414.  
  415.                 else
  416.                 {
  417.                     cout << labyrinth[i][j];
  418.                 }
  419.             }
  420.  
  421.             cout << "\n";
  422.         }
  423.  
  424.         if (breakAfterRender)
  425.         {
  426.             cout << "\n";
  427.  
  428.             cout << "Congratulations! You have reached the end of the level!" << "\n";
  429.  
  430.             playerX = originalPlayerX;
  431.  
  432.             playerY = originalPlayerY;
  433.  
  434.             cout << "\n" << "\n";
  435.  
  436.             cout << "Press \"ENTER\" to continue" << "\n";
  437.  
  438.             while (true)
  439.             {
  440.                 if (_getch() == 13) // The ASCII CODE FOR THE ENTER / RETURN KEY
  441.                 {
  442.                     break;
  443.                 }
  444.             }
  445.  
  446.             break;
  447.         }
  448.  
  449.         labyrinth[playerX][playerY] = " ";
  450.  
  451.         playerMove(labyrinth);
  452.  
  453.         if (labyrinth[playerX][playerY] == "E")
  454.         {
  455.             breakAfterRender = true;
  456.         }
  457.  
  458.         labyrinth[playerX][playerY] = player;
  459.  
  460.         this_thread::sleep_for(chrono::milliseconds(10));
  461.     }
  462. }
  463.  
  464. void loadMap(string fileName, int level, string levelType)
  465. {
  466.     int rowsCount = 1;
  467.  
  468.     int columnsCount = 0;
  469.  
  470.     int startAt = 0;
  471.  
  472.     int endAt = 0;
  473.  
  474.     ifstream mapFile;
  475.     mapFile.open(fileName);
  476.  
  477.     if (mapFile.is_open())
  478.     {
  479.         char mychar;
  480.  
  481.         while (mapFile)
  482.         {
  483.             mychar = mapFile.get();
  484.  
  485.             if (mychar == '\n')
  486.             {
  487.                 rowsCount++;
  488.             }
  489.  
  490.             else if ( (mychar != '\n') && (rowsCount == 1) )
  491.             {
  492.                 columnsCount++;
  493.             }
  494.  
  495.             else if (mychar == 'S')
  496.             {
  497.                 startAt = rowsCount - 1;
  498.             }
  499.  
  500.             else if (mychar == 'E')
  501.             {
  502.                 endAt = rowsCount - 1;
  503.             }
  504.         }
  505.     }
  506.  
  507.     else
  508.     {
  509.         cout << "Error: Unable to open file " << fileName << "." << "\n";
  510.  
  511.         cout << "Press \"ENTER\" to continue" << "\n";
  512.  
  513.         while (true)
  514.         {
  515.             if (_getch() == 13) // The ASCII CODE FOR THE ENTER / RETURN KEY
  516.             {
  517.                 backToMenu();
  518.             }
  519.         }
  520.     }
  521.  
  522.     mapFile.close();
  523.  
  524.     // Dynamically allocating row space in the heap
  525.     string** labyrinth = new string * [rowsCount];
  526.  
  527.     // Dynamically allocating column space in the heap
  528.     for (int i = 0; i < rowsCount; i++)
  529.     {
  530.         labyrinth[i] = new string[columnsCount];
  531.     }
  532.  
  533.     int currentRow = 0;
  534.  
  535.     int currentColumn = 0;
  536.  
  537.     mapFile.open(fileName);
  538.  
  539.     if (mapFile.is_open())
  540.     {
  541.         char mychar;
  542.  
  543.         while (mapFile.get(mychar))
  544.         {
  545.             if ((currentRow < rowsCount) && (currentColumn < columnsCount))
  546.             {
  547.                 labyrinth[currentRow][currentColumn] = mychar;
  548.             }
  549.  
  550.             if (mychar == '\n')
  551.             {
  552.                 currentRow++;
  553.  
  554.                 currentColumn = 0;
  555.             }
  556.  
  557.             else
  558.             {
  559.                 currentColumn++;
  560.             }
  561.         }
  562.     }
  563.  
  564.     mapFile.close();
  565.  
  566.     // Displaying the labyrinth
  567.     display(labyrinth, rowsCount, columnsCount, level, levelType);
  568.  
  569.     // Free up the space after the use of the array
  570.     for (int i = 0; i < rowsCount; i++)
  571.     {
  572.         delete[] labyrinth[i];
  573.     }
  574.  
  575.     delete[] labyrinth;
  576. }
  577.  
  578. void levels(string levelType)
  579. {
  580.     int level = 1;
  581.  
  582.     if ((levelType != "easy") && (levelType != "normal") && (levelType != "hard"))
  583.     {
  584.         cout << "Invalid level!" << "\n";
  585.  
  586.         return;
  587.     }
  588.  
  589.     while (level < 11)
  590.     {
  591.         system("cls");
  592.  
  593.         string mapFile = "maps/" + levelType;
  594.  
  595.         mapFile += "/map_" + to_string(level);
  596.  
  597.         mapFile += "_s.txt";
  598.  
  599.         // Opening the text file
  600.         loadMap(mapFile, level, levelType);
  601.  
  602.         level++;
  603.     }
  604. }
  605.  
  606. void ShowConsoleCursor(bool showFlag)
  607. {
  608.     HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
  609.  
  610.     CONSOLE_CURSOR_INFO     cursorInfo;
  611.  
  612.     GetConsoleCursorInfo(out, &cursorInfo);
  613.     cursorInfo.bVisible = showFlag; // set the cursor visibility
  614.     SetConsoleCursorInfo(out, &cursorInfo);
  615. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement