Advertisement
PIBogdanov

The Labyrinth

Apr 3rd, 2023
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 49.50 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4. #include <Windows.h>
  5. #include <conio.h>
  6. #include <ctype.h>
  7. #include <random>
  8. #include <chrono>
  9. #include <thread>
  10. #include <mmsystem.h>
  11.  
  12. #pragma comment(lib, "winmm.lib")
  13.  
  14. using namespace std;
  15.  
  16. size_t playerX = 0;
  17.  
  18. size_t playerY = 0;
  19.  
  20. int mainMenu();
  21.  
  22. void gameStart();
  23.  
  24. void customGame();
  25.  
  26. void gameControls();
  27.  
  28. void gameCredits();
  29.  
  30. void customMapInformation();
  31.  
  32. void exitProgram();
  33.  
  34. int customGameMenu();
  35.  
  36. int difficultyMenu();
  37.  
  38. void easyDifficulty();
  39.  
  40. void normalDifficulty();
  41.  
  42. void hardDifficulty();
  43.  
  44. void backToMenu();
  45.  
  46. void playMusic(wstring&);
  47.  
  48. void characterMove(string**, size_t&, size_t&, size_t, size_t);
  49.  
  50. void playerMove(string**);
  51.  
  52. void display(string**, size_t, size_t, size_t, string);
  53.  
  54. void loadMapFromAFolder(string, size_t, string);
  55.  
  56. void loadMap(string**, size_t, size_t);
  57.  
  58. void loadCustomMapFromTheFolder();
  59.  
  60. void createACustomMap();
  61.  
  62. void rowsAndColumnsChoice(size_t&, size_t&);
  63.  
  64. void rowsAndColumnsSetByThePlayer(size_t&, size_t&);
  65.  
  66. void startAndEndChoice(int&, int&);
  67.  
  68. void startAndEndSetByThePlayer(string**&, size_t&, size_t&, size_t&, size_t&, string&, string&);
  69.  
  70. int setWallsCountChoice(int&);
  71.  
  72. void wallsSetByThePlayerWithoutASetWallsCount(string**&, size_t&, size_t&);
  73.  
  74. void chooseAnAction(string**&, size_t&, size_t&, string&);
  75.  
  76. void saveTheMapConfiguration(string**&, size_t&, size_t&, string&);
  77.  
  78. void displayTheConfiguration(string**, size_t, size_t);
  79.  
  80. void displayTheConfigurationWithCoordinates(string**, size_t, size_t);
  81.  
  82. void displayTheConfigurationWithoutSpaces(string**, size_t, size_t);
  83.  
  84. size_t filesInFolderCount(string);
  85.  
  86. void levels(string);
  87.  
  88. void CoutCentered(string);
  89.  
  90. void CoutCenteredWithoutNewLine(string);
  91.  
  92. size_t GetConsoleWidth();
  93.  
  94. void SetVolume(int);
  95.  
  96. void ShowConsoleCursor(bool);
  97.  
  98. int main()
  99. {
  100.     system("color 04");
  101.  
  102.     HWND hWnd = GetConsoleWindow(); // Get the console window handle
  103.  
  104.     ShowWindow(hWnd, SW_MAXIMIZE); // Maximize the window
  105.  
  106.     HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  107.  
  108.     CONSOLE_FONT_INFOEX fontInfo{};
  109.  
  110.     fontInfo.cbSize = sizeof(fontInfo);
  111.  
  112.     GetCurrentConsoleFontEx(consoleHandle, FALSE, &fontInfo);
  113.  
  114.     fontInfo.dwFontSize.X += 2; // Increase the font width
  115.  
  116.     fontInfo.dwFontSize.Y += 2; // Increase the font height
  117.  
  118.     SetCurrentConsoleFontEx(consoleHandle, FALSE, &fontInfo);
  119.  
  120.     ShowConsoleCursor(false);
  121.  
  122.     PlaySound(TEXT("running_home_to_you.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  123.  
  124.     // Set audio volume to 25%
  125.     SetVolume(0xFFFF / 4);
  126.  
  127.     mainMenu();
  128.  
  129.     return 0;
  130. }
  131.  
  132. typedef void(*menuOptions)();
  133.  
  134. menuOptions mainMenuOptions[] = { gameStart, customGame, gameControls, gameCredits, customMapInformation, exitProgram };
  135.  
  136. int mainMenu()
  137. {
  138.     string menu[] = { "Start Game", "Create a Custom Game", "Controls", "Credits", "How to create a custom map?", "Exit"};
  139.  
  140.     size_t pointer = 0;
  141.  
  142.     bool lastUpKeyState = false;
  143.  
  144.     bool lastDownKeyState = false;
  145.  
  146.     bool lastReturnKeyState = false;
  147.  
  148.     bool arrowVisible = true;
  149.  
  150.     while (true)
  151.     {
  152.         system("cls");
  153.  
  154.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  155.  
  156.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  157.  
  158.         CoutCentered("The Labyrinth");
  159.  
  160.         cout << "\n" << "\n";
  161.  
  162.         CoutCentered("Main Menu");
  163.  
  164.         cout << "\n";
  165.  
  166.         for (size_t i = 0; i < size(menu); i++)
  167.         {
  168.             if (i == pointer)
  169.             {
  170.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  171.  
  172.                 if (arrowVisible)
  173.                 {
  174.                     CoutCentered("-> " + menu[i]);
  175.  
  176.                     arrowVisible = false;
  177.                 }
  178.  
  179.                 else
  180.                 {
  181.                     CoutCentered("    ");
  182.  
  183.                     arrowVisible = true;
  184.                 }
  185.             }
  186.  
  187.             else
  188.             {
  189.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  190.  
  191.                 CoutCentered(menu[i]);
  192.             }
  193.         }
  194.  
  195.         bool upKeyState = GetAsyncKeyState(VK_UP);
  196.  
  197.         if ( (upKeyState) && !(lastUpKeyState) )
  198.         {
  199.             pointer -= 1;
  200.  
  201.             if (pointer == -1)
  202.             {
  203.                 pointer = size(menu) - 1; // FROM pointer = 4
  204.             }
  205.         }
  206.  
  207.         lastUpKeyState = upKeyState;
  208.  
  209.         bool downKeyState = GetAsyncKeyState(VK_DOWN);
  210.  
  211.         if ( (downKeyState) && !(lastDownKeyState) )
  212.         {
  213.             pointer += 1;
  214.  
  215.             if (pointer == size(menu)) // FROM pointer = 5
  216.             {
  217.                 pointer = 0;
  218.             }
  219.         }
  220.  
  221.         lastDownKeyState = downKeyState;
  222.  
  223.         bool returnKeyState = GetAsyncKeyState(VK_RETURN);
  224.  
  225.         if ( (returnKeyState) && !(lastReturnKeyState) )
  226.         {
  227.             mainMenuOptions[pointer]();
  228.         }
  229.  
  230.         lastReturnKeyState = returnKeyState;
  231.  
  232.         this_thread::sleep_for(chrono::milliseconds(200));
  233.     }
  234. }
  235.  
  236. void gameStart()
  237. {
  238.     difficultyMenu();
  239. }
  240.  
  241. void customGame()
  242. {
  243.     customGameMenu();
  244. }
  245.  
  246. void gameControls()
  247. {
  248.     system("cls");
  249.  
  250.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  251.  
  252.     CoutCentered("  --------------CONTROLS---------------");
  253.     CoutCentered("  |                                   |");
  254.     CoutCentered("  |                                   |");
  255.     CoutCentered("  |   ^ --> Up Arrow to move up       |");
  256.     CoutCentered("  |   < --> Left Arrow to move left   |");
  257.     CoutCentered("  |   > --> Right Arrow to move right |");
  258.     CoutCentered("  |   v --> Down Arrow to move down   |");
  259.     CoutCentered("  |                                   |");
  260.     CoutCentered("  |   Enter / Return --> Enter        |");
  261.     CoutCentered("  |   Escape --> Back                 |");
  262.     CoutCentered("  |                                   |");
  263.     CoutCentered("  |                                   |");
  264.     CoutCentered("  -------------------------------------");
  265.  
  266.     while (true)
  267.     {
  268.         backToMenu();
  269.     }
  270. }
  271.  
  272. void gameCredits()
  273. {
  274.     system("cls");
  275.  
  276.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  277.  
  278.     CoutCentered("Thanks for playing!");
  279.    
  280.     cout << "\n";
  281.  
  282.     CoutCentered("Creator: Petar Bogdanov");
  283.  
  284.     CoutCentered("The people who helped me with this project: eng. Stoyan Filipov and eng. Monika Gencheva");
  285.    
  286.     cout << "\n";
  287.  
  288.     CoutCentered("Press \"ESCAPE\" to go back to the Main Menu");
  289.  
  290.     while (true)
  291.     {
  292.         backToMenu();
  293.     }
  294. }
  295.  
  296. void customMapInformation()
  297. {
  298.     system("cls");
  299.  
  300.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  301.  
  302.     CoutCentered("To create a custom map you need to:");
  303.  
  304.     cout << "\n";
  305.  
  306.     CoutCentered("1. Create a file with the .txt extension.  ");
  307.  
  308.     CoutCentered("2. Visualize your map inside the .txt file.");
  309.  
  310.     CoutCentered("3. Put the file in the \"custom\" subfolder.");
  311.  
  312.     cout << "\n";
  313.  
  314.     CoutCentered("NOTE: DO NOT DO PART 3 IF YOU HAVE CREATED THE FILE ALREADY THERE!");
  315.    
  316.     cout << "\n" << "\n";
  317.  
  318.     CoutCentered("Press \"ESCAPE\" to go back to the Main Menu");
  319.  
  320.     while (true)
  321.     {
  322.         backToMenu();
  323.     }
  324. }
  325.  
  326. void exitProgram()
  327. {
  328.     exit(0);
  329. }
  330.  
  331. menuOptions customMenuOptions[] = { loadCustomMapFromTheFolder, createACustomMap };
  332.  
  333. int customGameMenu()
  334. {
  335.     string menu[] = { "Play on already created custom map placed in the subfolder", "Create a Custom Map" };
  336.  
  337.     size_t pointer = 0;
  338.  
  339.     bool lastUpKeyState = false;
  340.  
  341.     bool lastDownKeyState = false;
  342.  
  343.     bool lastReturnKeyState = false;
  344.  
  345.     bool arrowVisible = true;
  346.  
  347.     while (true)
  348.     {
  349.         system("cls");
  350.  
  351.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  352.  
  353.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  354.  
  355.         CoutCentered("Type of a custom map");
  356.  
  357.         cout << "\n" << "\n";
  358.  
  359.         for (size_t i = 0; i < size(menu); i++)
  360.         {
  361.             if (i == pointer)
  362.             {
  363.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  364.  
  365.                 if (arrowVisible)
  366.                 {
  367.                     CoutCentered("-> " + menu[i]);
  368.  
  369.                     arrowVisible = false;
  370.                 }
  371.  
  372.                 else
  373.                 {
  374.                     CoutCentered("    ");
  375.  
  376.                     arrowVisible = true;
  377.                 }
  378.             }
  379.  
  380.             else
  381.             {
  382.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  383.  
  384.                 CoutCentered(menu[i]);
  385.             }
  386.         }
  387.  
  388.         bool upKeyState = GetAsyncKeyState(VK_UP);
  389.  
  390.         if ( (upKeyState) && !(lastUpKeyState) )
  391.         {
  392.             pointer -= 1;
  393.  
  394.             if (pointer == -1)
  395.             {
  396.                 pointer = size(menu) - 1;
  397.             }
  398.         }
  399.  
  400.         lastUpKeyState = upKeyState;
  401.  
  402.         bool downKeyState = GetAsyncKeyState(VK_DOWN);
  403.  
  404.         if ( (downKeyState) && !(lastDownKeyState) )
  405.         {
  406.             pointer += 1;
  407.  
  408.             if (pointer == size(menu))
  409.             {
  410.                 pointer = 0;
  411.             }
  412.         }
  413.  
  414.         lastDownKeyState = downKeyState;
  415.  
  416.         bool returnKeyState = GetAsyncKeyState(VK_RETURN);
  417.  
  418.         if ( (returnKeyState) && !(lastReturnKeyState) )
  419.         {
  420.             customMenuOptions[pointer]();
  421.         }
  422.  
  423.         lastReturnKeyState = returnKeyState;
  424.        
  425.         backToMenu();
  426.  
  427.         this_thread::sleep_for(chrono::milliseconds(200));
  428.     }
  429. }
  430.  
  431. menuOptions difficultyMenuOptions[] = { easyDifficulty, normalDifficulty, hardDifficulty };
  432.  
  433. int difficultyMenu()
  434. {
  435.     string difficulty[] = { "Easy", "Normal", "Hard" };
  436.  
  437.     size_t pointer = 0;
  438.  
  439.     bool lastUpKeyState = false;
  440.  
  441.     bool lastDownKeyState = false;
  442.  
  443.     bool lastReturnKeyState = false;
  444.  
  445.     bool arrowVisible = true;
  446.  
  447.     while (true)
  448.     {
  449.         system("cls");
  450.  
  451.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  452.  
  453.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  454.  
  455.         CoutCentered("Choose difficulty");
  456.  
  457.         cout << "\n" << "\n";
  458.  
  459.         for (size_t i = 0; i < size(difficulty); i++)
  460.         {
  461.             if (i == pointer)
  462.             {
  463.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  464.  
  465.                 if (arrowVisible)
  466.                 {
  467.                     CoutCentered("-> " + difficulty[i]);
  468.  
  469.                     arrowVisible = false;
  470.                 }
  471.  
  472.                 else
  473.                 {
  474.                     CoutCentered("    ");
  475.  
  476.                     arrowVisible = true;
  477.                 }
  478.             }
  479.  
  480.             else
  481.             {
  482.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  483.  
  484.                 CoutCentered(difficulty[i]);
  485.             }
  486.         }
  487.  
  488.         bool upKeyState = GetAsyncKeyState(VK_UP);
  489.  
  490.         if ( (upKeyState) && !(lastUpKeyState) )
  491.         {
  492.             pointer -= 1;
  493.  
  494.             if (pointer == -1)
  495.             {
  496.                 pointer = size(difficulty) - 1;
  497.             }
  498.         }
  499.  
  500.         lastUpKeyState = upKeyState;
  501.  
  502.         bool downKeyState = GetAsyncKeyState(VK_DOWN);
  503.  
  504.         if ( (downKeyState) && !(lastDownKeyState) )
  505.         {
  506.             pointer += 1;
  507.  
  508.             if (pointer == size(difficulty))
  509.             {
  510.                 pointer = 0;
  511.             }
  512.         }
  513.  
  514.         lastDownKeyState = downKeyState;
  515.  
  516.         bool returnKeyState = GetAsyncKeyState(VK_RETURN);
  517.  
  518.         if ( (returnKeyState) && !(lastReturnKeyState) )
  519.         {
  520.             difficultyMenuOptions[pointer]();
  521.         }
  522.  
  523.         lastReturnKeyState = returnKeyState;
  524.  
  525.         backToMenu();
  526.  
  527.         this_thread::sleep_for(chrono::milliseconds(200));
  528.     }
  529. }
  530.  
  531. void easyDifficulty()
  532. {
  533.     levels("easy");
  534. }
  535.  
  536. void normalDifficulty()
  537. {
  538.     levels("normal");
  539. }
  540.  
  541. void hardDifficulty()
  542. {
  543.     levels("hard");
  544. }
  545.  
  546. void backToMenu()
  547. {
  548.     if (GetAsyncKeyState(VK_ESCAPE))
  549.     {
  550.         mainMenu();
  551.     }
  552. }
  553.  
  554. void characterMove(string** labyrinth, size_t& x, size_t& y, size_t dx, size_t dy)
  555. {
  556.     if (labyrinth[x + dx][y + dy] == "S" || labyrinth[x + dx][y + dy] == " " || labyrinth[x + dx][y + dy] == "E")
  557.     {
  558.         x += dx;
  559.  
  560.         y += dy;
  561.     }
  562. }
  563.  
  564. void playerMove(string** labyrinth)
  565. {
  566.     //char key = _getch();
  567.  
  568.     //if (key == 72) // The ASCII CODE FOR THE UP ARROW KEY
  569.     //{
  570.     //    characterMove(labyrinth, playerX, playerY, -1, 0);
  571.     //}
  572.  
  573.     //else if (key == 75) // The ASCII CODE FOR THE LEFT ARROW KEY
  574.     //{
  575.     //    characterMove(labyrinth, playerX, playerY, 0, -1);
  576.     //}
  577.  
  578.     //else if (key == 80) // The ASCII CODE FOR THE DOWN ARROW KEY
  579.     //{
  580.     //    characterMove(labyrinth, playerX, playerY, 1, 0);
  581.     //}
  582.  
  583.     //else if (key == 77) // The ASCII CODE FOR THE RIGHT ARROW KEY
  584.     //{
  585.     //    characterMove(labyrinth, playerX, playerY, 0, 1);
  586.     //}
  587.  
  588.     // Using the GetAsyncKeyState function from the Windows.h header performs better than using the ASCII codes for the arrow buttons from the conio.h header
  589.  
  590.     bool upKeyState = GetAsyncKeyState(VK_UP);
  591.  
  592.     bool leftKeyState = GetAsyncKeyState(VK_LEFT);
  593.  
  594.     bool downKeyState = GetAsyncKeyState(VK_DOWN);
  595.  
  596.     bool rightKeyState = GetAsyncKeyState(VK_RIGHT);
  597.  
  598.     if (upKeyState)
  599.     {
  600.         characterMove(labyrinth, playerX, playerY, -1, 0);
  601.     }
  602.  
  603.     else if (leftKeyState)
  604.     {
  605.         characterMove(labyrinth, playerX, playerY, 0, -1);
  606.     }
  607.  
  608.     else if (downKeyState)
  609.     {
  610.         characterMove(labyrinth, playerX, playerY, 1, 0);
  611.     }
  612.  
  613.     else if (rightKeyState)
  614.     {
  615.         characterMove(labyrinth, playerX, playerY, 0, 1);
  616.     }
  617. }
  618.  
  619. void display(string** labyrinth, size_t rowsCount, size_t columnsCount, size_t level, string levelType)
  620. {
  621.     string player = "O";
  622.  
  623.     bool breakAfterRender = false;
  624.  
  625.     while (true)
  626.     {
  627.         system("cls");
  628.  
  629.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  630.  
  631.         // Center the game screen
  632.  
  633.         size_t consoleWidth = GetConsoleWidth();
  634.  
  635.         size_t screenLeftMargin = (consoleWidth - columnsCount) / 2;
  636.  
  637.         CoutCentered("Difficulty: " + levelType);
  638.  
  639.         if ( (levelType == "easy") || (levelType == "normal") || (levelType == "hard") )
  640.         {
  641.             CoutCentered("Level: " + to_string(level) + " / " + to_string(filesInFolderCount(levelType)));
  642.  
  643.             cout << "\n" << "\n";
  644.         }
  645.  
  646.         else
  647.         {
  648.             cout << "\n";
  649.         }
  650.  
  651.         size_t colour = rand() % 15 + 1;
  652.  
  653.         for (size_t i = 0; i < rowsCount; i++)
  654.         {
  655.             cout << setw(screenLeftMargin); // Center each row
  656.  
  657.             for (size_t j = 0; j < columnsCount; j++)
  658.             {
  659.                 if ( (i == playerX) && (j == playerY) )
  660.                 {
  661.                     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colour);
  662.  
  663.                     cout << player;
  664.  
  665.                     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
  666.                 }
  667.  
  668.                 else
  669.                 {
  670.                     cout << labyrinth[i][j];
  671.                 }
  672.             }
  673.  
  674.             cout << "\n";
  675.         }
  676.  
  677.         if (breakAfterRender)
  678.         {
  679.             cout << "\n" << "\n";
  680.  
  681.             CoutCentered("Congratulations! You have reached the end of the level!");
  682.  
  683.             cout << "\n" << "\n";
  684.  
  685.             CoutCentered("Press \"ENTER\" to continue");
  686.  
  687.             cout << "\n";
  688.  
  689.             while (true)
  690.             {
  691.                 if (GetAsyncKeyState(VK_RETURN))
  692.                 {
  693.                     break;
  694.                 }
  695.             }
  696.  
  697.             break;
  698.         }
  699.  
  700.         labyrinth[playerX][playerY] = " ";
  701.  
  702.         playerMove(labyrinth);
  703.  
  704.         if (labyrinth[playerX][playerY] == "E")
  705.         {
  706.             breakAfterRender = true;
  707.         }
  708.  
  709.         labyrinth[playerX][playerY] = player;
  710.  
  711.         // Pause sound
  712.         if (GetAsyncKeyState(VK_ESCAPE))
  713.         {
  714.             system("cls");
  715.  
  716.             cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  717.  
  718.             CoutCentered("Paused");
  719.  
  720.             while (true)
  721.             {
  722.                 if (GetAsyncKeyState(VK_ESCAPE))
  723.                 {
  724.                     break;
  725.                 }
  726.             }
  727.         }
  728.  
  729.         this_thread::sleep_for(chrono::milliseconds(64));
  730.     }
  731. }
  732.  
  733. void loadMapFromAFolder(string fileName, size_t level, string levelType)
  734. {
  735.     size_t rowsCount = 1;
  736.  
  737.     size_t columnsCount = 0;
  738.  
  739.     size_t startAt = 0;
  740.  
  741.     size_t endAt = 0;
  742.  
  743.     ifstream mapFile;
  744.     mapFile.open(fileName);
  745.  
  746.     if (mapFile.is_open())
  747.     {
  748.         char currentSymbol;
  749.  
  750.         while (mapFile)
  751.         {
  752.             currentSymbol = mapFile.get();
  753.  
  754.             if (currentSymbol == '\n')
  755.             {
  756.                 rowsCount++;
  757.             }
  758.  
  759.             else if ( (currentSymbol != '\n') && (rowsCount == 1) )
  760.             {
  761.                 columnsCount++;
  762.             }
  763.  
  764.             else if (currentSymbol == 'S')
  765.             {
  766.                 startAt = rowsCount - 1;
  767.             }
  768.  
  769.             else if (currentSymbol == 'E')
  770.             {
  771.                 endAt = rowsCount - 1;
  772.             }
  773.         }
  774.     }
  775.  
  776.     else
  777.     {
  778.         CoutCentered("Error: Unable to open file " + fileName + ".");
  779.        
  780.         cout << "\n";
  781.  
  782.         CoutCentered("Press \"ESCAPE\" to go back to the Main Menu.");
  783.  
  784.         while (true)
  785.         {
  786.             backToMenu();
  787.         }
  788.     }
  789.  
  790.     mapFile.close();
  791.  
  792.     // Dynamically allocating row space in the heap
  793.     string** labyrinth = new string * [rowsCount];
  794.  
  795.     // Dynamically allocating column space in the heap
  796.     for (size_t i = 0; i < rowsCount; i++)
  797.     {
  798.         labyrinth[i] = new string[columnsCount];
  799.     }
  800.  
  801.     size_t currentRow = 0;
  802.  
  803.     size_t currentColumn = 0;
  804.  
  805.     mapFile.open(fileName);
  806.  
  807.     if (mapFile.is_open())
  808.     {
  809.         char currentSymbol;
  810.  
  811.         while (mapFile.get(currentSymbol))
  812.         {
  813.             if ( (currentRow < rowsCount) && (currentColumn < columnsCount) )
  814.             {
  815.                 labyrinth[currentRow][currentColumn] = currentSymbol;
  816.             }
  817.  
  818.             if (currentSymbol == '\n')
  819.             {
  820.                 currentRow++;
  821.  
  822.                 currentColumn = 0;
  823.             }
  824.  
  825.             else
  826.             {
  827.                 currentColumn++;
  828.             }
  829.         }
  830.     }
  831.  
  832.     mapFile.close();
  833.  
  834.     for (size_t i = 0; i < rowsCount; i++)
  835.     {
  836.         for (size_t j = 0; j < columnsCount; j++)
  837.         {
  838.             if (labyrinth[i][j] == "S")
  839.             {
  840.                 playerX = i;
  841.  
  842.                 playerY = j;
  843.             }
  844.         }
  845.     }
  846.  
  847.     // Displaying the labyrinth
  848.     display(labyrinth, rowsCount, columnsCount, level, levelType);
  849.  
  850.     // Free up the space after the use of the array
  851.     for (size_t i = 0; i < rowsCount; i++)
  852.     {
  853.         delete[] labyrinth[i];
  854.     }
  855.  
  856.     delete[] labyrinth;
  857. }
  858.  
  859. void loadMap(string** labyrinth, size_t rowsCount, size_t columnsCount)
  860. {
  861.     for (size_t i = 0; i < rowsCount; i++)
  862.     {
  863.         for (size_t j = 0; j < columnsCount; j++)
  864.         {
  865.             if (labyrinth[i][j] == "S")
  866.             {
  867.                 playerX = i;
  868.  
  869.                 playerY = j;
  870.             }
  871.         }
  872.     }
  873.  
  874.     // Displaying the labyrinth
  875.     display(labyrinth, rowsCount, columnsCount, size_t(0), "custom");
  876.  
  877.     // Free up the space after the use of the array
  878.     for (size_t i = 0; i < rowsCount; i++)
  879.     {
  880.         delete[] labyrinth[i];
  881.     }
  882.  
  883.     delete[] labyrinth;
  884. }
  885.  
  886. void loadCustomMapFromTheFolder()
  887. {
  888.     size_t fileCount = filesInFolderCount("custom");
  889.  
  890.     string* menu = new string[fileCount];
  891.  
  892.     WIN32_FIND_DATA findData; // Returns information about the directory
  893.  
  894.     HANDLE hFind;
  895.  
  896.     string folderPath = "maps/custom/"; // Folder directory
  897.  
  898.     wstring wideFolderPath(folderPath.begin(), folderPath.end());
  899.  
  900.     wideFolderPath += L"*";
  901.  
  902.     hFind = FindFirstFile(wideFolderPath.c_str(), &findData);
  903.  
  904.     if (hFind != INVALID_HANDLE_VALUE)
  905.     {
  906.         char narrowString[MAX_PATH];
  907.  
  908.         string* newData;
  909.  
  910.         size_t counter = 0;
  911.  
  912.         while (FindNextFile(hFind, &findData) != 0)
  913.         {
  914.             WideCharToMultiByte(CP_ACP, 0, findData.cFileName, -1, narrowString, MAX_PATH, NULL, NULL);
  915.  
  916.             if ( (strcmp(narrowString, ".") != 0) && (strcmp(narrowString, "..") != 0) ) // Find information about . and ..
  917.             {
  918.                 if (counter == fileCount)
  919.                 {
  920.                     newData = new string[fileCount + 2];
  921.  
  922.                     for (size_t i = 0; i < counter; i++)
  923.                     {
  924.                         newData[i] = menu[i];
  925.                     }
  926.  
  927.                     delete[] menu;
  928.  
  929.                     menu = newData;
  930.                 }
  931.  
  932.                 menu[counter] = narrowString;
  933.  
  934.                 counter++;
  935.             }
  936.         }
  937.  
  938.         FindClose(hFind);
  939.     }
  940.  
  941.     size_t pointer = 0;
  942.  
  943.     bool lastUpKeyState = false;
  944.  
  945.     bool lastDownKeyState = false;
  946.  
  947.     bool lastReturnKeyState = false;
  948.  
  949.     bool arrowVisible = true;
  950.  
  951.     while (true)
  952.     {
  953.         system("cls");
  954.  
  955.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  956.  
  957.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  958.  
  959.         CoutCentered("There are " + to_string(fileCount) + " files in the subfolder called \"custom\".");
  960.  
  961.         cout << "\n";
  962.  
  963.         CoutCentered("Select a Custom Map");
  964.  
  965.         cout << "\n";
  966.  
  967.         for (size_t i = 0; i < fileCount; i++)
  968.         {
  969.             if (i == pointer)
  970.             {
  971.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  972.  
  973.                 if (arrowVisible)
  974.                 {
  975.                     CoutCentered("-> " + menu[i]);
  976.  
  977.                     arrowVisible = false;
  978.                 }
  979.  
  980.                 else
  981.                 {
  982.                     CoutCentered("    ");
  983.  
  984.                     arrowVisible = true;
  985.                 }
  986.             }
  987.  
  988.             else
  989.             {
  990.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  991.  
  992.                 CoutCentered(menu[i]);
  993.             }
  994.         }
  995.  
  996.         bool upKeyState = GetAsyncKeyState(VK_UP);
  997.  
  998.         if ( (upKeyState) && !(lastUpKeyState) )
  999.         {
  1000.             pointer -= 1;
  1001.  
  1002.             if (pointer == -1)
  1003.             {
  1004.                 pointer = fileCount - 1;
  1005.             }
  1006.         }
  1007.  
  1008.         lastUpKeyState = upKeyState;
  1009.  
  1010.         bool downKeyState = GetAsyncKeyState(VK_DOWN);
  1011.  
  1012.         if ( (downKeyState) && !(lastDownKeyState) )
  1013.         {
  1014.             pointer += 1;
  1015.  
  1016.             if (pointer == fileCount)
  1017.             {
  1018.                 pointer = 0;
  1019.             }
  1020.         }
  1021.  
  1022.         lastDownKeyState = downKeyState;
  1023.  
  1024.         bool returnKeyState = GetAsyncKeyState(VK_RETURN);
  1025.  
  1026.         if ( (returnKeyState) && !(lastReturnKeyState) )
  1027.         {
  1028.             // Play sound
  1029.             PlaySound(TEXT("river.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  1030.  
  1031.             // Set audio volume to 25%
  1032.             SetVolume(0xFFFF / 4);
  1033.  
  1034.             string mapFile = "maps/custom/" + menu[pointer];
  1035.  
  1036.             // Opening the text file
  1037.             loadMapFromAFolder(mapFile, 0, "custom");
  1038.  
  1039.             PlaySound(TEXT("running_home_to_you.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  1040.  
  1041.             // Set audio volume to 25%
  1042.             SetVolume(0xFFFF / 4);
  1043.  
  1044.             mainMenu();
  1045.         }
  1046.  
  1047.         lastReturnKeyState = returnKeyState;
  1048.        
  1049.         if (GetAsyncKeyState(VK_ESCAPE))
  1050.         {
  1051.             customGameMenu();
  1052.         }
  1053.  
  1054.         this_thread::sleep_for(chrono::milliseconds(200));
  1055.     }
  1056.  
  1057.     delete[] menu;
  1058. }
  1059.  
  1060. void createACustomMap()
  1061. {
  1062.     system("cls");
  1063.  
  1064.     system("color 04");
  1065.  
  1066.     cin.ignore();
  1067.  
  1068.     cin.get();
  1069.  
  1070.     size_t rowsCount = 0;
  1071.  
  1072.     size_t columnsCount = 0;
  1073.  
  1074.     // Possible future update
  1075.     //rowsAndColumnsChoice(rowsCount, columnsCount);
  1076.  
  1077.     rowsAndColumnsSetByThePlayer(rowsCount, columnsCount);
  1078.  
  1079.     size_t farRightAngle = rowsCount * 2 + columnsCount * 2 - 4;
  1080.  
  1081.     size_t farLeftAngle = rowsCount * 2 + columnsCount - 3;
  1082.  
  1083.     system("cls");
  1084.  
  1085.     // Dynamically allocating row space in the heap
  1086.     string** labyrinth = new string * [rowsCount];
  1087.  
  1088.     // Dynamically allocating column space in the heap
  1089.     for (size_t i = 0; i < rowsCount; i++)
  1090.     {
  1091.         labyrinth[i] = new string[columnsCount];
  1092.     }
  1093.  
  1094.     size_t count = 1;
  1095.  
  1096.     for (size_t i = 0; i < rowsCount; i++)
  1097.     {
  1098.         for (size_t j = 0; j < columnsCount; j++)
  1099.         {
  1100.             if ( !( (i > 0) && (i < rowsCount - 1) && (j > 0) && (j < columnsCount - 1) ) )
  1101.             {
  1102.                 labyrinth[i][j] = to_string(count);
  1103.  
  1104.                 count++;
  1105.             }
  1106.         }
  1107.     }
  1108.  
  1109.     system("cls");
  1110.  
  1111.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1112.  
  1113.     displayTheConfiguration(labyrinth, rowsCount, columnsCount);
  1114.  
  1115.     string start;
  1116.  
  1117.     string end;
  1118.  
  1119.     // Possible future update
  1120.     //startAndEndChoice(start, end);
  1121.  
  1122.     startAndEndSetByThePlayer(labyrinth, rowsCount, columnsCount, farRightAngle, farLeftAngle, start, end);
  1123.  
  1124.     /*
  1125.     int wallsCount = 0;
  1126.  
  1127.     setWallsCountChoice(wallsCount);
  1128.     */
  1129.  
  1130.     wallsSetByThePlayerWithoutASetWallsCount(labyrinth, rowsCount, columnsCount);
  1131.  
  1132.     string name;
  1133.  
  1134.     chooseAnAction(labyrinth, rowsCount, columnsCount, name);
  1135. }
  1136.  
  1137. // Possible future update
  1138. void rowsAndColumnsChoice(size_t& rowsCount, size_t& columnsCount)
  1139. {
  1140.     system("cls");
  1141.  
  1142.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1143.  
  1144.     CoutCentered("Do you want to set your own rows and columns or do you want the game to set them for you?");
  1145.     CoutCentered("The possible answers are \"myself\" for you to set them yourself or \"random\" for the game to set them for you.");
  1146.     CoutCenteredWithoutNewLine("Your answer is: ");
  1147.  
  1148.     string choice;
  1149.     getline(cin >> ws, choice);
  1150.  
  1151.     for (size_t i = 0; i < choice.length(); i++)
  1152.     {
  1153.         choice[i] = tolower(choice[i]);
  1154.     }
  1155.  
  1156.     if (choice == "myself")
  1157.     {
  1158.         rowsAndColumnsSetByThePlayer(rowsCount, columnsCount);
  1159.     }
  1160.  
  1161.     else if (choice == "random")
  1162.     {
  1163.         // Possible future update
  1164.     }
  1165.  
  1166.     else
  1167.     {
  1168.         system("cls");
  1169.  
  1170.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1171.  
  1172.         CoutCentered("Invalid choice!");
  1173.  
  1174.         this_thread::sleep_for(chrono::milliseconds(800));
  1175.  
  1176.         return rowsAndColumnsChoice(rowsCount, columnsCount);
  1177.     }
  1178. }
  1179.  
  1180. // The player sets the rows and the columns
  1181. void rowsAndColumnsSetByThePlayer(size_t& rowsCount, size_t& columnsCount)
  1182. {
  1183.     system("cls");
  1184.  
  1185.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1186.  
  1187.     // MIN 5
  1188.     // MAX 23
  1189.  
  1190.     CoutCentered("The allowed values are between 5 and 23.");
  1191.  
  1192.     cout << "\n" << "\n";
  1193.  
  1194.     CoutCenteredWithoutNewLine("Enter rows: ");
  1195.     cin >> rowsCount;
  1196.  
  1197.     while ( (rowsCount < 5) || (rowsCount > 23) )
  1198.     {
  1199.         system("cls");
  1200.  
  1201.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1202.  
  1203.         CoutCentered("Invalid choice!");
  1204.         CoutCentered("The allowed values are between 5 and 23.");
  1205.  
  1206.         CoutCenteredWithoutNewLine("Enter rows: ");
  1207.         cin >> rowsCount;
  1208.     }
  1209.  
  1210.     system("cls");
  1211.  
  1212.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1213.  
  1214.     CoutCentered("The allowed values are between 5 and 23.");
  1215.  
  1216.     cout << "\n" << "\n";
  1217.  
  1218.     CoutCenteredWithoutNewLine("Enter columns: ");
  1219.     cin >> columnsCount;
  1220.  
  1221.     while ( (columnsCount < 5) || (columnsCount > 23) )
  1222.     {
  1223.         system("cls");
  1224.  
  1225.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1226.  
  1227.         CoutCentered("Invalid choice!");
  1228.         CoutCentered("The allowed values are between 5 and 23.");
  1229.  
  1230.         CoutCenteredWithoutNewLine("Ener columns: ");
  1231.         cin >> columnsCount;
  1232.     }
  1233. }
  1234.  
  1235. // Possible future update
  1236. void startAndEndChoice(int& start, int& end)
  1237. {
  1238.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1239.  
  1240.     CoutCentered("Do you want to set your own start and end or you do want the game to set them for you?");
  1241.     CoutCentered("The possible answers are \"myself\" for you to set them yourself or \"random\" for the game to set them for you.");
  1242.     CoutCenteredWithoutNewLine("Your answer is: ");
  1243.  
  1244.     string choice;
  1245.     getline(cin >> ws, choice);
  1246.  
  1247.     for (size_t i = 0; i < choice.length(); i++)
  1248.     {
  1249.         choice[i] = tolower(choice[i]);
  1250.     }
  1251.    
  1252.     if (choice == "myself")
  1253.     {
  1254.  
  1255.     }
  1256.    
  1257.     else if (choice == "random")
  1258.     {
  1259.  
  1260.     }
  1261.    
  1262.     else
  1263.     {
  1264.         system("cls");
  1265.  
  1266.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1267.  
  1268.         CoutCentered("Invalid choice!");
  1269.  
  1270.         this_thread::sleep_for(chrono::milliseconds(800));
  1271.  
  1272.         return startAndEndChoice(start, end);
  1273.     }
  1274. }
  1275.  
  1276. // The player sets the start and the end
  1277. void startAndEndSetByThePlayer(string**& labyrinth, size_t& rowsCount, size_t& columnsCount, size_t& farRightAngle, size_t& farLeftAngle, string& start, string& end)
  1278. {
  1279.     system("cls");
  1280.  
  1281.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1282.  
  1283.     CoutCentered("The starting point can't be on 1, " + to_string(rowsCount) + ", " + to_string(farLeftAngle) + " and " + to_string(farRightAngle) + ".");
  1284.  
  1285.     cout << "\n" << "\n";
  1286.  
  1287.     displayTheConfiguration(labyrinth, rowsCount, columnsCount);
  1288.  
  1289.     cout << "\n";
  1290.  
  1291.     string startAt;
  1292.     CoutCenteredWithoutNewLine("Choose a starting point: ");
  1293.     cin >> startAt;
  1294.  
  1295.     while ( (stoi(startAt) == 1) || (stoi(startAt) == farRightAngle) || (stoi(startAt) == farLeftAngle) || (stoi(startAt) == columnsCount) )
  1296.     {
  1297.         system("cls");
  1298.  
  1299.         CoutCentered("The starting point can't be on 1, " + to_string(rowsCount) + ", " + to_string(farLeftAngle) + " and " + to_string(farRightAngle) + ".");
  1300.  
  1301.         cout << "\n" << "\n";
  1302.  
  1303.         displayTheConfiguration(labyrinth, rowsCount, columnsCount);
  1304.  
  1305.         cout << "\n";
  1306.  
  1307.         CoutCenteredWithoutNewLine("Choose a starting point: ");
  1308.         cin >> startAt;
  1309.     }
  1310.  
  1311.     for (size_t i = 0; i < rowsCount; i++)
  1312.     {
  1313.         for (size_t j = 0; j < columnsCount; j++)
  1314.         {
  1315.             if (startAt == labyrinth[i][j])
  1316.             {
  1317.                 labyrinth[i][j] = "S";
  1318.             }
  1319.         }
  1320.     }
  1321.  
  1322.     system("cls");
  1323.  
  1324.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1325.  
  1326.     CoutCentered("The ending point can't be on 1, " + to_string(rowsCount) + ", " + to_string(farLeftAngle) + " and " + to_string(farRightAngle) + ".");
  1327.  
  1328.     cout << "\n" << "\n";
  1329.  
  1330.     displayTheConfiguration(labyrinth, rowsCount, columnsCount);
  1331.  
  1332.     cout << "\n";
  1333.  
  1334.     string endAt;
  1335.     CoutCenteredWithoutNewLine("Choose an ending point: ");
  1336.     cin >> endAt;
  1337.  
  1338.     while ( (stoi(endAt) == 1) || (endAt == startAt) || (stoi(endAt) == farRightAngle) || (stoi(endAt) == farLeftAngle) || (stoi(endAt) == columnsCount) )
  1339.     {
  1340.         system("cls");
  1341.  
  1342.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1343.  
  1344.         CoutCentered("The ending point can't be on 1, " + to_string(rowsCount) + ", " + to_string(farLeftAngle) + " and " + to_string(farRightAngle) + ".");
  1345.  
  1346.         cout << "\n" << "\n";
  1347.  
  1348.         displayTheConfiguration(labyrinth, rowsCount, columnsCount);
  1349.  
  1350.         cout << "\n";
  1351.  
  1352.         CoutCenteredWithoutNewLine("Choose an ending point: ");
  1353.         cin >> endAt;
  1354.     }
  1355.  
  1356.     for (size_t i = 0; i < rowsCount; i++)
  1357.     {
  1358.         for (size_t j = 0; j < columnsCount; j++)
  1359.         {
  1360.             if (endAt == labyrinth[i][j])
  1361.             {
  1362.                 labyrinth[i][j] = "E";
  1363.             }
  1364.         }
  1365.     }
  1366. }
  1367.  
  1368. // Possible future update
  1369. int setWallsCountChoice(int& wallsCount)
  1370. {
  1371.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1372.  
  1373.     CoutCentered("Do you want to set your number of walls or do you want the game to set them for you?");
  1374.     CoutCentered("The possible answers are \"myself\" for you to set them yourself or \"random\" for the game to set them for you.");
  1375.     CoutCenteredWithoutNewLine("Your answer is: ");
  1376.  
  1377.     string choice;
  1378.     getline(cin >> ws, choice);
  1379.  
  1380.     for (size_t i = 0; i < choice.length(); i++)
  1381.     {
  1382.         choice[i] = tolower(choice[i]);
  1383.     }
  1384.  
  1385.     if (choice == "myself")
  1386.     {
  1387.  
  1388.     }
  1389.  
  1390.     else if (choice == "random")
  1391.     {
  1392.  
  1393.     }
  1394.  
  1395.     else
  1396.     {
  1397.         system("cls");
  1398.  
  1399.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1400.  
  1401.         CoutCentered("Invalid choice!");
  1402.  
  1403.         this_thread::sleep_for(chrono::milliseconds(800));
  1404.  
  1405.         return setWallsCountChoice(wallsCount);
  1406.     }
  1407.  
  1408.     return wallsCount;
  1409. }
  1410.  
  1411. // The player sets walls in the labyrinth
  1412. void wallsSetByThePlayerWithoutASetWallsCount(string**& labyrinth, size_t& rowsCount, size_t& columnsCount)
  1413. {
  1414.     system("cls");
  1415.  
  1416.     size_t count = 1;
  1417.  
  1418.     for (size_t i = 0; i < rowsCount; i++)
  1419.     {
  1420.         for (size_t j = 0; j < columnsCount; j++)
  1421.         {
  1422.             if ( (labyrinth[i][j] == "S") || (labyrinth[i][j] == "E") )
  1423.             {
  1424.                 continue;
  1425.             }
  1426.  
  1427.             else if ( (i > 0) && (i < rowsCount - 1) && (j > 0) && (j < columnsCount - 1) )
  1428.             {
  1429.                 count++;
  1430.             }
  1431.  
  1432.             else
  1433.             {
  1434.                 labyrinth[i][j] = "#";
  1435.             }
  1436.         }
  1437.     }
  1438.  
  1439.     system("cls");
  1440.  
  1441.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1442.  
  1443.     CoutCentered("You can enter as many walls as you want. When you want to stop entering walls, type \"end\".");
  1444.  
  1445.     cout << "\n" << "\n";
  1446.  
  1447.     displayTheConfigurationWithCoordinates(labyrinth, rowsCount, columnsCount);
  1448.  
  1449.     cout << "\n";
  1450.  
  1451.     string currentWall;
  1452.     CoutCenteredWithoutNewLine("Enter a wall (ROWxCOLUMN): ");
  1453.     cin >> currentWall;
  1454.  
  1455.     for (size_t i = 0; i < currentWall.length(); i++)
  1456.     {
  1457.         currentWall[i] = tolower(currentWall[i]);
  1458.     }
  1459.  
  1460.     while (currentWall != "end")
  1461.     {
  1462.         for (size_t i = 0; i < rowsCount; i++)
  1463.         {
  1464.             for (size_t j = 0; j < columnsCount; j++)
  1465.             {
  1466.                 if (currentWall == (to_string(i) + 'x' + to_string(j)))
  1467.                 {
  1468.                     labyrinth[i][j] = "#";
  1469.                 }
  1470.             }
  1471.         }
  1472.  
  1473.         system("cls");
  1474.  
  1475.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1476.  
  1477.         CoutCentered("You can enter as many walls as you want. When you want to stop entering walls, type \"end\".");
  1478.  
  1479.         cout << "\n" << "\n";
  1480.  
  1481.         displayTheConfigurationWithCoordinates(labyrinth, rowsCount, columnsCount);
  1482.  
  1483.         cout << "\n";
  1484.  
  1485.         CoutCenteredWithoutNewLine("Enter a wall (ROWxCOLUMN): ");
  1486.         cin >> currentWall;
  1487.  
  1488.         for (size_t i = 0; i < currentWall.length(); i++)
  1489.         {
  1490.             currentWall[i] = tolower(currentWall[i]);
  1491.         }
  1492.     }
  1493. }
  1494.  
  1495. // The player chooses an action
  1496. void chooseAnAction(string**& labyrinth, size_t& rowsCount, size_t& columnsCount, string& customMapName)
  1497. {
  1498.     system("cls");
  1499.  
  1500.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1501.  
  1502.     displayTheConfigurationWithoutSpaces(labyrinth, rowsCount, columnsCount);
  1503.  
  1504.     cout << "\n" << "\n";
  1505.  
  1506.     CoutCentered("What do you want to do now?");
  1507.  
  1508.     cout << "\n";
  1509.  
  1510.     CoutCentered("If you want to save the map and play it, type \"both\".");
  1511.  
  1512.     cout << "\n";
  1513.  
  1514.     CoutCentered("If you want to save the map without playing it, type \"save\".");
  1515.  
  1516.     cout << "\n";
  1517.  
  1518.     CoutCentered("If you want to play the map without saving it, type \"play\".");
  1519.  
  1520.     cout << "\n";
  1521.  
  1522.     CoutCenteredWithoutNewLine("Your answer is: ");
  1523.  
  1524.     string choice;
  1525.     getline(cin >> ws, choice);
  1526.  
  1527.     for (size_t i = 0; i < choice.length(); i++)
  1528.     {
  1529.         choice[i] = tolower(choice[i]);
  1530.     }
  1531.  
  1532.     if (choice == "both")
  1533.     {
  1534.         saveTheMapConfiguration(labyrinth, rowsCount, columnsCount, customMapName);
  1535.  
  1536.         // Play sound
  1537.         PlaySound(TEXT("river.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  1538.  
  1539.         // Set audio volume to 25%
  1540.         SetVolume(0xFFFF / 4);
  1541.  
  1542.         loadMapFromAFolder(customMapName, size_t(0), "custom");
  1543.  
  1544.         PlaySound(TEXT("running_home_to_you.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  1545.  
  1546.         // Set audio volume to 25%
  1547.         SetVolume(0xFFFF / 4);
  1548.        
  1549.         mainMenu();
  1550.     }
  1551.  
  1552.     else if (choice == "save")
  1553.     {
  1554.         saveTheMapConfiguration(labyrinth, rowsCount, columnsCount, customMapName);
  1555.     }
  1556.  
  1557.     else if (choice == "play")
  1558.     {
  1559.         // Play sound
  1560.         PlaySound(TEXT("river.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  1561.  
  1562.         // Set audio volume to 25%
  1563.         SetVolume(0xFFFF / 4);
  1564.  
  1565.         loadMap(labyrinth, rowsCount, columnsCount);
  1566.  
  1567.         PlaySound(TEXT("running_home_to_you.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  1568.  
  1569.         // Set audio volume to 25%
  1570.         SetVolume(0xFFFF / 4);
  1571.  
  1572.         mainMenu();
  1573.     }
  1574.  
  1575.     else
  1576.     {
  1577.         system("cls");
  1578.  
  1579.         cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1580.  
  1581.         CoutCentered("Invalid choice!");
  1582.  
  1583.         this_thread::sleep_for(chrono::milliseconds(800));
  1584.  
  1585.         return chooseAnAction(labyrinth, rowsCount, columnsCount, customMapName);
  1586.     }
  1587. }
  1588.  
  1589. // Creates a text file and saves it in the subfolder called "custom"
  1590. void saveTheMapConfiguration(string**& labyrinth, size_t& rowsCount, size_t& columnsCount, string& nameWithTheFolderPath)
  1591. {
  1592.     system("cls");
  1593.  
  1594.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1595.  
  1596.     CoutCentered("Type a name for the text file. The name should contain only lowercase letters.");
  1597.     CoutCenteredWithoutNewLine("File's name is: ");
  1598.  
  1599.     string name;
  1600.     getline(cin >> ws, name);
  1601.  
  1602.     for (size_t i = 0; i < name.length(); i++)
  1603.     {
  1604.         name[i] = tolower(name[i]);
  1605.     }
  1606.  
  1607.     time_t currentTime = time(NULL);
  1608.  
  1609.     name += "_" + to_string(currentTime) + ".txt";
  1610.  
  1611.     nameWithTheFolderPath = "maps/custom/" + name;
  1612.  
  1613.     ofstream customMap(nameWithTheFolderPath);
  1614.  
  1615.     for (size_t i = 0; i < rowsCount; i++)
  1616.     {
  1617.         for (size_t j = 0; j < columnsCount; j++)
  1618.         {
  1619.             customMap << labyrinth[i][j];
  1620.         }
  1621.        
  1622.         customMap << "\n";
  1623.     }
  1624.  
  1625.     customMap.close();
  1626. }
  1627.  
  1628. // Displays the labyrinth with spaces between the elements
  1629. void displayTheConfiguration(string** labyrinth, size_t rowsCount, size_t columnsCount)
  1630. {
  1631.     size_t consoleWidth = GetConsoleWidth();
  1632.  
  1633.     size_t screenLeftMargin = (consoleWidth - columnsCount) / 2;
  1634.  
  1635.     string currentElement;
  1636.  
  1637.     size_t currentLength = 0;
  1638.  
  1639.     for (size_t i = 0; i < rowsCount; i++)
  1640.     {
  1641.         cout << setw(screenLeftMargin); // Center each row
  1642.  
  1643.         for (size_t j = 0; j < columnsCount; j++)
  1644.         {
  1645.             currentElement = labyrinth[i][j];
  1646.  
  1647.             currentLength = currentElement.length();
  1648.  
  1649.             if (currentElement.length() < 2)
  1650.             {
  1651.                 currentElement = " " + currentElement;
  1652.             }
  1653.  
  1654.             if (currentElement.length() < 3)
  1655.             {
  1656.                 cout << currentElement + string(3 - currentElement.length(), ' ');
  1657.             }
  1658.  
  1659.             else
  1660.             {
  1661.                 cout << currentElement;
  1662.             }
  1663.         }
  1664.  
  1665.         cout << "\n";
  1666.     }
  1667. }
  1668.  
  1669. // Displays the labyrinth with additional information for rows and columns
  1670. void displayTheConfigurationWithCoordinates(string** labyrinth, size_t rowsCount, size_t columnsCount)
  1671. {
  1672.     size_t consoleWidth = GetConsoleWidth();
  1673.  
  1674.     size_t screenLeftMargin = (consoleWidth - columnsCount) / 2;
  1675.  
  1676.     string currentElement;
  1677.  
  1678.     size_t currentLength = 0;
  1679.  
  1680.     for (size_t i = 0; i < rowsCount; i++)
  1681.     {
  1682.         cout << setw(screenLeftMargin); // Center each row
  1683.  
  1684.         if (i == 0)
  1685.         {
  1686.             for (size_t j = 0; j < columnsCount; j++)
  1687.             {
  1688.                 currentElement = to_string(j);
  1689.  
  1690.                 currentLength = currentElement.length();
  1691.  
  1692.                 if (currentElement.length() < 2)
  1693.                 {
  1694.                     if (j == 0)
  1695.                     {
  1696.                         currentElement = "   " + currentElement + " ";
  1697.                     }
  1698.  
  1699.                     else
  1700.                     {
  1701.                         currentElement = " " + currentElement;
  1702.                     }
  1703.                 }
  1704.  
  1705.                 if (currentElement.length() < 3)
  1706.                 {
  1707.                     cout << currentElement + string(3 - currentElement.length(), ' ');
  1708.                 }
  1709.  
  1710.                 else
  1711.                 {
  1712.                     cout << currentElement;
  1713.                 }
  1714.             }
  1715.  
  1716.             cout << "\n";
  1717.         }
  1718.  
  1719.         cout << setw(screenLeftMargin); // Center each row
  1720.  
  1721.         for (size_t j = 0; j < columnsCount; j++)
  1722.         {
  1723.             currentElement = labyrinth[i][j];
  1724.  
  1725.             currentLength = currentElement.length();
  1726.  
  1727.             if (currentElement.length() < 2)
  1728.             {
  1729.                 if (j == 0)
  1730.                 {
  1731.                     currentElement = " " + to_string(i) + " " + currentElement + " ";
  1732.                 }
  1733.  
  1734.                 else
  1735.                 {
  1736.                     currentElement = " " + currentElement;
  1737.                 }
  1738.             }
  1739.  
  1740.             if (currentElement.length() < 3)
  1741.             {
  1742.                 cout << currentElement + string(3 - currentElement.length(), ' ');
  1743.             }
  1744.  
  1745.             else
  1746.             {
  1747.                 cout << currentElement;
  1748.             }
  1749.         }
  1750.  
  1751.         cout << "\n";
  1752.     }
  1753. }
  1754.  
  1755. // Displays the labyrinth without spaces
  1756. void displayTheConfigurationWithoutSpaces(string** labyrinth, size_t rowsCount, size_t columnsCount)
  1757. {
  1758.     for (size_t i = 0; i < rowsCount; i++)
  1759.     {
  1760.         for (size_t j = 0; j < columnsCount; j++)
  1761.         {
  1762.             if ( (labyrinth[i][j] != "S") && (labyrinth[i][j] != "#") && (labyrinth[i][j] != "E") )
  1763.             {
  1764.                 labyrinth[i][j] = " ";
  1765.             }
  1766.         }
  1767.     }
  1768.  
  1769.     size_t consoleWidth = GetConsoleWidth();
  1770.  
  1771.     size_t screenLeftMargin = (consoleWidth - columnsCount) / 2;
  1772.  
  1773.     for (size_t i = 0; i < rowsCount; i++)
  1774.     {
  1775.         cout << setw(screenLeftMargin); // Center each row
  1776.  
  1777.         for (size_t j = 0; j < columnsCount; j++)
  1778.         {
  1779.             cout << labyrinth[i][j];
  1780.         }
  1781.  
  1782.         cout << "\n";
  1783.     }
  1784. }
  1785.  
  1786. // Returns the count of the text files (maps)
  1787. size_t filesInFolderCount(string levelType)
  1788. {
  1789.     size_t fileCount = 0;
  1790.  
  1791.     string folderPath = "maps/" + levelType + "/";
  1792.  
  1793.     // Get the first file in the folder
  1794.     WIN32_FIND_DATAA findFileData;
  1795.  
  1796.     HANDLE hFind = FindFirstFileA((folderPath + "*").c_str(), &findFileData);
  1797.  
  1798.     // Iterate through the files in the folder
  1799.     if (hFind != INVALID_HANDLE_VALUE)
  1800.     {
  1801.         while (true)
  1802.         {
  1803.             // Check if the current file is a regular file
  1804.             if ( (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 )
  1805.             {
  1806.                 fileCount++;
  1807.             }
  1808.  
  1809.             if (!FindNextFileA(hFind, &findFileData))
  1810.             {
  1811.                 break;
  1812.             }
  1813.         }
  1814.  
  1815.         // Clean up
  1816.         FindClose(hFind);
  1817.     }
  1818.  
  1819.     return fileCount;
  1820. }
  1821.  
  1822. // Information about the current level
  1823. void levels(string levelType)
  1824. {
  1825.     // Play sound
  1826.     PlaySound(TEXT("river.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  1827.  
  1828.     // Set audio volume to 25%
  1829.     SetVolume(0xFFFF / 4);
  1830.  
  1831.     size_t level = 1;
  1832.  
  1833.     if ( (levelType != "easy") && (levelType != "normal") && (levelType != "hard") )
  1834.     {
  1835.         system("cls");
  1836.  
  1837.         CoutCentered("Invalid level type!");
  1838.  
  1839.         return;
  1840.     }
  1841.  
  1842.     string mapFile;
  1843.  
  1844.     while (level <= filesInFolderCount(levelType))
  1845.     {
  1846.         system("cls");
  1847.  
  1848.         mapFile = "maps/" + levelType + "/map_" + to_string(level) + ".txt";
  1849.  
  1850.         // Opening the text file
  1851.         loadMapFromAFolder(mapFile, level, levelType);
  1852.  
  1853.         level++;
  1854.     }
  1855.  
  1856.     system("cls");
  1857.  
  1858.     cout << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n";
  1859.  
  1860.     CoutCentered("Congratulations! You have finished the game!");
  1861.  
  1862.     cout << "\n";
  1863.  
  1864.     CoutCentered("Press \"ENTER\" to continue");
  1865.  
  1866.     while (true)
  1867.     {
  1868.         if (GetAsyncKeyState(VK_RETURN))
  1869.         {
  1870.             break;
  1871.         }
  1872.     }
  1873.  
  1874.     PlaySound(TEXT("running_home_to_you.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
  1875.  
  1876.     // Set audio volume to 25%
  1877.     SetVolume(0xFFFF / 4);
  1878.  
  1879.     gameCredits();
  1880. }
  1881.  
  1882. // This function centers the text within the console window.
  1883. void CoutCentered(string text)
  1884. {
  1885.     HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Get the console handle.
  1886.  
  1887.     CONSOLE_SCREEN_BUFFER_INFO screenInfo;
  1888.  
  1889.     GetConsoleScreenBufferInfo(hConsole, &screenInfo); // Get the console screen buffer info.
  1890.  
  1891.     size_t consoleWidth = screenInfo.dwSize.X;
  1892.  
  1893.     size_t textWidth = static_cast<size_t>(text.length());
  1894.  
  1895.     size_t leftMargin = (consoleWidth - textWidth) / 2;
  1896.  
  1897.     for (size_t i = 0; i < leftMargin; i++)
  1898.     {
  1899.         cout << " ";
  1900.     }
  1901.  
  1902.     cout << text << "\n";
  1903. }
  1904.  
  1905. // This function centers the text within the console window without new line.
  1906. void CoutCenteredWithoutNewLine(string text)
  1907. {
  1908.     HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Get the console handle.
  1909.  
  1910.     CONSOLE_SCREEN_BUFFER_INFO screenInfo;
  1911.  
  1912.     GetConsoleScreenBufferInfo(hConsole, &screenInfo); // Get the console screen buffer info.
  1913.  
  1914.     size_t consoleWidth = screenInfo.dwSize.X;
  1915.  
  1916.     size_t textWidth = static_cast<size_t>(text.length());
  1917.  
  1918.     size_t leftMargin = (consoleWidth - textWidth) / 2;
  1919.  
  1920.     for (size_t i = 0; i < leftMargin; i++)
  1921.     {
  1922.         cout << " ";
  1923.     }
  1924.  
  1925.     cout << text;
  1926. }
  1927.  
  1928. // Returns the console's width
  1929. size_t GetConsoleWidth()
  1930. {
  1931.     CONSOLE_SCREEN_BUFFER_INFO csbi;
  1932.  
  1933.     GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
  1934.  
  1935.     size_t columns = csbi.srWindow.Right - csbi.srWindow.Left + 2;
  1936.  
  1937.     return columns;
  1938. }
  1939.  
  1940. // Sets the audio volume
  1941. void SetVolume(int volume)
  1942. {
  1943.     DWORD newVolume = ((DWORD)volume << 16) | (DWORD)volume;
  1944.  
  1945.     waveOutSetVolume(NULL, newVolume);
  1946. }
  1947.  
  1948. // Removes the cursor
  1949. void ShowConsoleCursor(bool showFlag)
  1950. {
  1951.     HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
  1952.  
  1953.     CONSOLE_CURSOR_INFO cursorInfo;
  1954.  
  1955.     GetConsoleCursorInfo(out, &cursorInfo);
  1956.  
  1957.     cursorInfo.bVisible = showFlag; // Sets the cursor visability
  1958.  
  1959.     SetConsoleCursorInfo(out, &cursorInfo);
  1960. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement