Advertisement
PIBogdanov

The Labyrinth

Feb 13th, 2023
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.88 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. int filesInFolderCount(string);
  54.  
  55. void levels(string);
  56.  
  57. void ShowConsoleCursor(bool showFlag);
  58.  
  59. int main()
  60. {
  61.     system("color 04");
  62.  
  63.     ShowWindow(GetConsoleWindow(), SW_MAXIMIZE);
  64.  
  65.     SendMessage(GetConsoleWindow(), WM_SYSKEYDOWN, VK_RETURN, 0x2000000);
  66.  
  67.     ShowConsoleCursor(false);
  68.  
  69.     mainMenu();
  70.  
  71.     return 0;
  72. }
  73.  
  74. typedef void(*menuOptions)();
  75.  
  76. menuOptions mainMenuOptions[] = { gameStart, customGame, gameControls, gameCredits, exitProgram };
  77.  
  78. int mainMenu()
  79. {
  80.     string menu[5] = { "Start Game", "Create a Custom Game", "Controls", "Credits", "Exit" };
  81.  
  82.     int pointer = 0;
  83.  
  84.     bool lastUpKeyState = false;
  85.  
  86.     bool lastDownKeyState = false;
  87.  
  88.     bool lastReturnKeyState = false;
  89.  
  90.     bool arrowVisible = true;
  91.  
  92.     while (true)
  93.     {
  94.         system("cls");
  95.  
  96.         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  97.  
  98.         cout << "The Labyrinth" << "\n" << "\n";
  99.  
  100.         cout << "Main Menu" << "\n" << "\n";
  101.  
  102.         for (int i = 0; i < 5; i++)
  103.         {
  104.             if (i == pointer)
  105.             {
  106.                 if (arrowVisible)
  107.                 {
  108.                     cout << "-> ";
  109.  
  110.                     arrowVisible = false;
  111.                 }
  112.  
  113.                 else
  114.                 {
  115.                     cout << "    "; // Prints 4 spaces to cover the previous "-> "
  116.  
  117.                     arrowVisible = true;
  118.                 }
  119.  
  120.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  121.  
  122.                 cout << menu[i] << endl;
  123.             }
  124.  
  125.             else
  126.             {
  127.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  128.  
  129.                 cout << menu[i] << endl;
  130.             }
  131.         }
  132.  
  133.         bool upKeyState = GetAsyncKeyState(VK_UP);
  134.  
  135.         if ( (upKeyState) && !(lastUpKeyState) )
  136.         {
  137.             pointer -= 1;
  138.  
  139.             if (pointer == -1)
  140.             {
  141.                 pointer = 4;
  142.             }
  143.         }
  144.  
  145.         lastUpKeyState = upKeyState;
  146.  
  147.         bool downKeyState = GetAsyncKeyState(VK_DOWN);
  148.  
  149.         if ( (downKeyState) && !(lastDownKeyState) )
  150.         {
  151.             pointer += 1;
  152.  
  153.             if (pointer == 5)
  154.             {
  155.                 pointer = 0;
  156.             }
  157.         }
  158.  
  159.         lastDownKeyState = downKeyState;
  160.  
  161.         bool returnKeyState = GetAsyncKeyState(VK_RETURN);
  162.  
  163.         if ( (returnKeyState) && !(lastReturnKeyState) )
  164.         {
  165.             mainMenuOptions[pointer]();
  166.         }
  167.  
  168.         lastReturnKeyState = returnKeyState;
  169.  
  170.         this_thread::sleep_for(chrono::milliseconds(200));
  171.     }
  172. }
  173.  
  174. void gameStart()
  175. {
  176.     difficultyMenu();
  177. }
  178.  
  179. void customGame()
  180. {
  181.     system("cls");
  182. }
  183.  
  184. void gameControls()
  185. {
  186.     system("cls");
  187.  
  188.     cout << "\n";
  189.  
  190.     cout << "  --------------CONTROLS---------------" << "\n";
  191.     cout << "  |                                   |" << "\n";
  192.     cout << "  |                                   |" << "\n";
  193.     cout << "  |   ^ --> Up Arrow to move up       |" << "\n";
  194.     cout << "  |   < --> Left Arrow to move left   |" << "\n";
  195.     cout << "  |   > --> Right Arrow to move right |" << "\n";
  196.     cout << "  |   v --> Down Arrow to move down   |" << "\n";
  197.     cout << "  |                                   |" << "\n";
  198.     cout << "  |   Enter / Return --> Enter        |" << "\n";
  199.     cout << "  |   Escape --> Back                 |" << "\n";
  200.     cout << "  |                                   |" << "\n";
  201.     cout << "  |                                   |" << "\n";
  202.     cout << "  -------------------------------------" << "\n";
  203.  
  204.     while (true)
  205.     {
  206.         backToMenu();
  207.     }
  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" << "\n";
  221.  
  222.     cout << "Press \"ESCAPE\" to go back to the Main Menu" << "\n";
  223.  
  224.     while (true)
  225.     {
  226.         backToMenu();
  227.     }
  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.  
  270.                 else
  271.                 {
  272.                     cout << "    "; // Prints 4 spaces to cover the previous "-> "
  273.  
  274.                     arrowVisible = true;
  275.                 }
  276.  
  277.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  278.  
  279.                 cout << difficulty[i] << endl;
  280.             }
  281.  
  282.             else
  283.             {
  284.                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  285.  
  286.                 cout << difficulty[i] << endl;
  287.             }
  288.         }
  289.  
  290.         bool upKeyState = GetAsyncKeyState(VK_UP);
  291.  
  292.         if ( (upKeyState) && !(lastUpKeyState) )
  293.         {
  294.             pointer -= 1;
  295.  
  296.             if (pointer == -1)
  297.             {
  298.                 pointer = 2;
  299.             }
  300.         }
  301.  
  302.         lastUpKeyState = upKeyState;
  303.  
  304.         bool downKeyState = GetAsyncKeyState(VK_DOWN);
  305.  
  306.         if ( (downKeyState) && !(lastDownKeyState) )
  307.         {
  308.             pointer += 1;
  309.  
  310.             if (pointer == 3)
  311.             {
  312.                 pointer = 0;
  313.             }
  314.         }
  315.  
  316.         lastDownKeyState = downKeyState;
  317.  
  318.         bool returnKeyState = GetAsyncKeyState(VK_RETURN);
  319.  
  320.         if ( (returnKeyState) && !(lastReturnKeyState) )
  321.         {
  322.             difficultyMenuOptions[pointer]();
  323.         }
  324.  
  325.         backToMenu();
  326.  
  327.         lastReturnKeyState = returnKeyState;
  328.  
  329.         this_thread::sleep_for(chrono::milliseconds(200));
  330.     }
  331. }
  332.  
  333. void easyDifficulty()
  334. {
  335.     levels("easy");
  336. }
  337.  
  338. void normalDifficulty()
  339. {
  340.     levels("normal");
  341. }
  342.  
  343. void hardDifficulty()
  344. {
  345.     levels("hard");
  346. }
  347.  
  348. void backToMenu()
  349. {
  350.     if (GetAsyncKeyState(VK_ESCAPE))
  351.     {
  352.         main();
  353.     }
  354. }
  355.  
  356. void characterMove(string** labyrinth, int& x, int& y, int dx, int dy)
  357. {
  358.     if (labyrinth[x + dx][y + dy] == "S" || labyrinth[x + dx][y + dy] == " " || labyrinth[x + dx][y + dy] == "E")
  359.     {
  360.         x += dx;
  361.         y += dy;
  362.     }
  363. }
  364.  
  365. void playerMove(string** labyrinth)
  366. {
  367.     char key = _getch();
  368.  
  369.     if (key == 72) // The ASCII CODE FOR THE UP ARROW KEY
  370.     {
  371.         characterMove(labyrinth, playerX, playerY, -1, 0);
  372.     }
  373.  
  374.     else if (key == 75) // The ASCII CODE FOR THE LEFT ARROW KEY
  375.     {
  376.         characterMove(labyrinth, playerX, playerY, 0, -1);
  377.     }
  378.  
  379.     else if (key == 80) // The ASCII CODE FOR THE DOWN ARROW KEY
  380.     {
  381.         characterMove(labyrinth, playerX, playerY, 1, 0);
  382.     }
  383.  
  384.     else if (key == 77) // The ASCII CODE FOR THE RIGHT ARROW KEY
  385.     {
  386.         characterMove(labyrinth, playerX, playerY, 0, 1);
  387.     }
  388. }
  389.  
  390. void display(string** labyrinth, int rowsCount, int columnsCount, int level, string levelType)
  391. {
  392.     bool breakAfterRender = false;
  393.  
  394.     while (true)
  395.     {
  396.         system("cls");
  397.  
  398.         cout << "Difficulty: " << levelType << "\n";
  399.  
  400.         cout << "Level: " << level << " / " << filesInFolderCount(levelType) << "\n" << "\n";
  401.  
  402.         int colour = rand() % 15 + 1;
  403.  
  404.         for (int i = 0; i < rowsCount; i++)
  405.         {
  406.             for (int j = 0; j < columnsCount; j++)
  407.             {
  408.                 if ((i == playerX) && (j == playerY))
  409.                 {
  410.                     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colour);
  411.  
  412.                     cout << player;
  413.  
  414.                     SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
  415.                 }
  416.  
  417.                 else
  418.                 {
  419.                     cout << labyrinth[i][j];
  420.                 }
  421.             }
  422.  
  423.             cout << "\n";
  424.         }
  425.  
  426.         if (breakAfterRender)
  427.         {
  428.             cout << "\n";
  429.  
  430.             cout << "Congratulations! You have reached the end of the level!" << "\n";
  431.  
  432.             playerX = originalPlayerX;
  433.  
  434.             playerY = originalPlayerY;
  435.  
  436.             cout << "\n" << "\n";
  437.  
  438.             cout << "Press \"ENTER\" to continue" << "\n";
  439.  
  440.             while (true)
  441.             {
  442.                 if (_getch() == 13) // The ASCII CODE FOR THE ENTER / RETURN KEY
  443.                 {
  444.                     break;
  445.                 }
  446.             }
  447.  
  448.             break;
  449.         }
  450.  
  451.         labyrinth[playerX][playerY] = " ";
  452.  
  453.         playerMove(labyrinth);
  454.  
  455.         if (labyrinth[playerX][playerY] == "E")
  456.         {
  457.             breakAfterRender = true;
  458.         }
  459.  
  460.         labyrinth[playerX][playerY] = player;
  461.  
  462.         this_thread::sleep_for(chrono::milliseconds(24));
  463.     }
  464. }
  465.  
  466. void loadMap(string fileName, int level, string levelType)
  467. {
  468.     int rowsCount = 1;
  469.  
  470.     int columnsCount = 0;
  471.  
  472.     int startAt = 0;
  473.  
  474.     int endAt = 0;
  475.  
  476.     ifstream mapFile;
  477.     mapFile.open(fileName);
  478.  
  479.     if (mapFile.is_open())
  480.     {
  481.         char mychar;
  482.  
  483.         while (mapFile)
  484.         {
  485.             mychar = mapFile.get();
  486.  
  487.             if (mychar == '\n')
  488.             {
  489.                 rowsCount++;
  490.             }
  491.  
  492.             else if ( (mychar != '\n') && (rowsCount == 1) )
  493.             {
  494.                 columnsCount++;
  495.             }
  496.  
  497.             else if (mychar == 'S')
  498.             {
  499.                 startAt = rowsCount - 1;
  500.             }
  501.  
  502.             else if (mychar == 'E')
  503.             {
  504.                 endAt = rowsCount - 1;
  505.             }
  506.         }
  507.     }
  508.  
  509.     else
  510.     {
  511.         cout << "Error: Unable to open file " << fileName << "\n" << "\n";
  512.  
  513.         cout << "Press \"ESCAPE\" to go back to the Main Menu" << "\n";
  514.  
  515.         while (true)
  516.         {
  517.             backToMenu();
  518.         }
  519.     }
  520.  
  521.     mapFile.close();
  522.  
  523.     // Dynamically allocating row space in the heap
  524.     string** labyrinth = new string * [rowsCount];
  525.  
  526.     // Dynamically allocating column space in the heap
  527.     for (int i = 0; i < rowsCount; i++)
  528.     {
  529.         labyrinth[i] = new string[columnsCount];
  530.     }
  531.  
  532.     int currentRow = 0;
  533.  
  534.     int currentColumn = 0;
  535.  
  536.     mapFile.open(fileName);
  537.  
  538.     if (mapFile.is_open())
  539.     {
  540.         char currentSymbol;
  541.  
  542.         while (mapFile.get(currentSymbol))
  543.         {
  544.             if ( (currentRow < rowsCount) && (currentColumn < columnsCount) )
  545.             {
  546.                 labyrinth[currentRow][currentColumn] = currentSymbol;
  547.             }
  548.  
  549.             if (currentSymbol == '\n')
  550.             {
  551.                 currentRow++;
  552.  
  553.                 currentColumn = 0;
  554.             }
  555.  
  556.             else
  557.             {
  558.                 currentColumn++;
  559.             }
  560.         }
  561.     }
  562.  
  563.     mapFile.close();
  564.  
  565.     // Displaying the labyrinth
  566.     display(labyrinth, rowsCount, columnsCount, level, levelType);
  567.  
  568.     // Free up the space after the use of the array
  569.     for (int i = 0; i < rowsCount; i++)
  570.     {
  571.         delete[] labyrinth[i];
  572.     }
  573.  
  574.     delete[] labyrinth;
  575. }
  576.  
  577. int filesInFolderCount(string levelType)
  578. {
  579.     int fileCount = 0;
  580.  
  581.     string folderPath = "maps/" + levelType + "/";
  582.  
  583.     // Get the first file in the folder
  584.     WIN32_FIND_DATAA findFileData;
  585.  
  586.     HANDLE hFind = FindFirstFileA((folderPath + "*").c_str(), &findFileData);
  587.  
  588.     // Iterate through the files in the folder
  589.     if (hFind != INVALID_HANDLE_VALUE)
  590.     {
  591.         while (true)
  592.         {
  593.             // Check if the current file is a regular file
  594.             if ( (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 )
  595.             {
  596.                 fileCount++;
  597.             }
  598.  
  599.             if ( !(FindNextFileA(hFind, &findFileData)) )
  600.             {
  601.                 break;
  602.             }
  603.         }
  604.  
  605.         // Clean up
  606.         FindClose(hFind);
  607.     }
  608.  
  609.     return fileCount;
  610. }
  611.  
  612. void levels(string levelType)
  613. {
  614.     int level = 1;
  615.  
  616.     if ( (levelType != "easy") && (levelType != "normal") && (levelType != "hard") )
  617.     {
  618.         system("cls");
  619.  
  620.         cout << "Invalid level!" << "\n";
  621.  
  622.         return;
  623.     }
  624.  
  625.     while (level <= filesInFolderCount(levelType))
  626.     {
  627.         system("cls");
  628.  
  629.         string mapFile = "maps/" + levelType + "/map_" + to_string(level) + ".txt";
  630.  
  631.         // Opening the text file
  632.         loadMap(mapFile, level, levelType);
  633.  
  634.         level++;
  635.     }
  636.  
  637.     gameCredits();
  638. }
  639.  
  640. void ShowConsoleCursor(bool showFlag)
  641. {
  642.     HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
  643.  
  644.     CONSOLE_CURSOR_INFO     cursorInfo;
  645.  
  646.     GetConsoleCursorInfo(out, &cursorInfo);
  647.  
  648.     cursorInfo.bVisible = showFlag; // SET THE CURSOR VISIBILITY
  649.  
  650.     SetConsoleCursorInfo(out, &cursorInfo);
  651. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement