Advertisement
DeltaJoseph

Tetris_3.cpp

Aug 12th, 2020
1,094
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.89 KB | None | 0 0
  1. #include <vector>
  2. #include <string>
  3. #include <random>
  4. #include <Windows.h>
  5.  
  6. using namespace std;
  7.  
  8. const int nScreenWidth = 39;
  9. const int nScreenHeight = 21;
  10.  
  11. const int nBoardWidth = 22;
  12. const int nBoardHeight = 21;
  13.  
  14. const vector<vector<wstring>> tetromino = {
  15.     // I
  16.     {
  17.         L"....XX......XX......XX......XX..", //   0 deg
  18.         L"................XXXXXXXX........", //  90 deg
  19.         L"..XX......XX......XX......XX....", // 180 deg
  20.         L"........XXXXXXXX................"  // 270 deg
  21.     },
  22.  
  23.     // J
  24.     {
  25.         L"....XX......XX....XXXX..........",
  26.         L"..........XX......XXXXXX........",
  27.         L"..........XXXX....XX......XX....",
  28.         L"........XXXXXX......XX.........."
  29.     },
  30.  
  31.     // L
  32.     {
  33.         L"..XX......XX......XXXX..........",
  34.         L"..........XXXXXX..XX............",
  35.         L"..........XXXX......XX......XX..",
  36.         L"............XX..XXXXXX.........."
  37.     },
  38.  
  39.     // O
  40.     {
  41.         L"..........XXXX....XXXX..........",
  42.         L"..........XXXX....XXXX..........",
  43.         L"..........XXXX....XXXX..........",
  44.         L"..........XXXX....XXXX.........."
  45.     },
  46.  
  47.     // S
  48.     {
  49.         L"..XX......XXXX......XX..........",
  50.         L"............XXXX..XXXX..........",
  51.         L"..........XX......XXXX......XX..",
  52.         L"..........XXXX..XXXX............"
  53.     },
  54.  
  55.     // T
  56.     {
  57.         L"..XX......XXXX....XX............",
  58.         L"..........XXXXXX....XX..........",
  59.         L"............XX....XXXX......XX..",
  60.         L"..........XX....XXXXXX.........."
  61.     },
  62.  
  63.     // Z
  64.     {
  65.         L"....XX....XXXX....XX............",
  66.         L"..........XXXX......XXXX........",
  67.         L"............XX....XXXX....XX....",
  68.         L"........XXXX......XXXX.........."
  69.     }
  70. };
  71.  
  72. const wstring detail = L" ▓█░╚╝║═";
  73.  
  74. void Configure()
  75. {
  76.     system("MODE 39, 22");
  77.     system("color 89");
  78.  
  79.     HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  80.  
  81.     CONSOLE_SCREEN_BUFFER_INFOEX csbiex;
  82.     csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
  83.     GetConsoleScreenBufferInfoEx(hConsoleOutput, &csbiex);
  84.     csbiex.ColorTable[0] = RGB(0, 188, 212);
  85.     csbiex.ColorTable[1] = RGB(63, 81, 181);
  86.     csbiex.ColorTable[2] = RGB(255, 87, 34);
  87.     csbiex.ColorTable[3] = RGB(255, 235, 59);
  88.     csbiex.ColorTable[4] = RGB(76, 175, 80);
  89.     csbiex.ColorTable[5] = RGB(156, 39, 176);
  90.     csbiex.ColorTable[6] = RGB(237, 28, 36);
  91.     csbiex.ColorTable[7] = RGB(242, 242, 242);
  92.     csbiex.ColorTable[8] = RGB(248, 248, 248);
  93.     csbiex.ColorTable[9] = RGB(20, 20, 0);
  94.     csbiex.ColorTable[10] = RGB(50, 44, 46);
  95.     csbiex.ColorTable[11] = RGB(225, 225, 225);
  96.  
  97.     SetConsoleScreenBufferInfoEx(hConsoleOutput, &csbiex);
  98.  
  99.     CONSOLE_FONT_INFOEX cfiex;
  100.     cfiex.cbSize = sizeof(CONSOLE_FONT_INFOEX);
  101.  
  102.     GetCurrentConsoleFontEx(hConsoleOutput, 0, &cfiex);
  103.     cfiex.dwFontSize.Y = 36;
  104.  
  105.     SetCurrentConsoleFontEx(hConsoleOutput, 0, &cfiex);
  106. }
  107.  
  108. void Text(wchar_t*& pBuffer, WORD*& pColor, wstring wsContent, WORD wColor, int nPosX, int nPosY)
  109. {
  110.     for (int i = 0; i < wsContent.length(); i++, nPosX++)
  111.     {
  112.         pBuffer[nPosY * nScreenWidth + nPosX] = wsContent.at(i);
  113.         pColor[nPosY * nScreenWidth + nPosX] = wColor;
  114.     }
  115. }
  116.  
  117. void Block(wchar_t*& pBuffer, WORD*& pColor, int nTetromino, int nPosX, int nPosY)
  118. {
  119.     for (int j = 0; j < 4; j++)
  120.     {
  121.         for (int i = 0; i < 8; i++)
  122.         {
  123.             if (tetromino.at(nTetromino).at(0).at(j * 8 + i) != L'.')
  124.             {
  125.                 pBuffer[(nPosY + j) * nScreenWidth + (nPosX + i)] = L'▓';
  126.             }
  127.             else
  128.             {
  129.                 pBuffer[(nPosY + j) * nScreenWidth + (nPosX + i)] = L' ';
  130.             }
  131.             pColor[(nPosY + j) * nScreenWidth + (nPosX + i)] = 8 * 16 + nTetromino;
  132.         }
  133.     }
  134. }
  135.  
  136. void Frame(wchar_t*& pBuffer, wstring wsCaption, int nWidth, int nHeight, int nPosX, int nPosY)
  137. {
  138.     for (int i = nPosX; i < nWidth + nPosX; i++)
  139.     {
  140.         for (int j = nPosY; j < nHeight + nPosY; j++)
  141.         {
  142.             if (i == nPosX)
  143.             {
  144.                 if (j == nPosY)
  145.                 {
  146.                     pBuffer[j * nScreenWidth + i] = L'╔';
  147.                 }
  148.                 else if (j == nHeight + nPosY - 1)
  149.                 {
  150.                     pBuffer[j * nScreenWidth + i] = L'╚';
  151.                 }
  152.                 else
  153.                 {
  154.                     pBuffer[j * nScreenWidth + i] = L'║';
  155.                 }
  156.             }
  157.             else if (i == nWidth + nPosX - 1)
  158.             {
  159.                 if (j == nPosY)
  160.                 {
  161.                     pBuffer[j * nScreenWidth + i] = L'╗';
  162.                 }
  163.                 else if (j == nHeight + nPosY - 1)
  164.                 {
  165.                     pBuffer[j * nScreenWidth + i] = L'╝';
  166.                 }
  167.                 else
  168.                 {
  169.                     pBuffer[j * nScreenWidth + i] = L'║';
  170.                 }
  171.             }
  172.             else
  173.             {
  174.                 if (j == nPosY || j == nHeight + nPosY - 1)
  175.                 {
  176.                     pBuffer[j * nScreenWidth + i] = L'═';
  177.                 }
  178.                 else
  179.                 {
  180.                     pBuffer[j * nScreenWidth + i] = L' ';
  181.                 }
  182.  
  183.             }
  184.         }
  185.     }
  186.  
  187.     int CapIndex = nPosY * nScreenWidth + (nPosX + 1);
  188.     for (int i = 0; i < wsCaption.length(); i++, CapIndex++)
  189.     {
  190.         pBuffer[CapIndex] = wsCaption.at(i);
  191.     }
  192. }
  193.  
  194. bool CheckPiece(int*& pMatrix, int nTetromino, int nRotation, int nPosX, int nPosY)
  195. {
  196.     for (int i = 0; i < 8; i++)
  197.     {
  198.         for (int j = 0; j < 4; j++)
  199.         {
  200.             if (nPosX + i >= 0 && nPosX + i < nBoardWidth)
  201.             {
  202.                 if (nPosY + j >= 0 && nPosY + j < nBoardHeight)
  203.                 {
  204.                     if (tetromino.at(nTetromino).at(nRotation).at(j * 8 + i) != L'.' && pMatrix[(nPosY + j) * nBoardWidth + (nPosX + i)] != 0)
  205.                     {
  206.                         return 0;
  207.                     }
  208.                 }
  209.             }
  210.         }
  211.     }
  212.  
  213.     return 1;
  214. }
  215.  
  216. int random(int nMin, int nMax)
  217. {
  218.     random_device rd;
  219.     mt19937 rng(rd());
  220.     uniform_int_distribution<int> uni(nMin, nMax);
  221.  
  222.     auto num = uni(rng);
  223.     return num;
  224. }
  225.  
  226. int main()
  227. {
  228.     Configure();
  229.  
  230.     // Buffer data
  231.     WORD* pColor = new WORD[nScreenWidth * nScreenHeight];
  232.     wchar_t* pBuffer = new wchar_t[nScreenWidth * nScreenHeight];
  233.  
  234.     // Create screen buffer
  235.     HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
  236.     DWORD dwBytesWritten = 0;
  237.  
  238.     while (1)
  239.     {
  240.         SetConsoleActiveScreenBuffer(hConsole);
  241.  
  242.         // GET STARTED
  243.  
  244.         const vector<wstring> wsThree = {
  245.             L"──▄",
  246.             L" ─█",
  247.             L"──▀"
  248.         };
  249.  
  250.         const vector<wstring> wsTwo = {
  251.             L"──▄",
  252.             L"▄─▀",
  253.             L"▀──"
  254.         };
  255.  
  256.         const vector<wstring> wsOne = {
  257.             L"─▄ ",
  258.             L" █ ",
  259.             L" ▀ "
  260.         };
  261.  
  262.         const vector<wstring> wsReady = {
  263.             L"▄──┐ ▄── ┌──▄ ▄──┐ ▄ ┬",
  264.             L"█─┬┘ █─  ├──█ █ ┌┘ ▀▄┘",
  265.             L"▀ └─ ▀── ┴  ▀ ▀─┘   ▀ "
  266.         };
  267.  
  268.         const vector<vector<wstring>> wsCountDown = { wsThree, wsTwo, wsOne, wsReady };
  269.  
  270.         // Clear screen
  271.         for (int i = 0; i < nScreenWidth; i++)
  272.         {
  273.             for (int j = 0; j < nScreenHeight; j++)
  274.             {
  275.                 pBuffer[j * nScreenWidth + i] = L' ';
  276.                 pColor[j * nScreenWidth + i] = 8 * 16 + 9;
  277.             }
  278.         }
  279.  
  280.         // Count down
  281.         for (int i = 0; i < wsCountDown.size(); i++)
  282.         {
  283.             for (int j = 0; j < wsCountDown.at(i).size(); j++)
  284.             {
  285.                 if (i == 3)
  286.                 {
  287.                     Text(pBuffer, pColor, wsCountDown.at(i).at(j), 8 * 16 + 4, 9, 9 + j);
  288.                 }
  289.                 else
  290.                 {
  291.                     Text(pBuffer, pColor, wsCountDown.at(i).at(j), 8 * 16 + 4, 18, 9 + j);
  292.                 }
  293.  
  294.             }
  295.  
  296.             for (int j = 0; j < nScreenHeight; j++)
  297.             {
  298.                 for (int i = 0; i < nScreenWidth; i++)
  299.                 {
  300.                     COORD cPos;
  301.                     cPos.X = i;
  302.                     cPos.Y = j;
  303.                     WriteConsoleOutputAttribute(hConsole, &pColor[j * nScreenWidth + i], 1, cPos, &dwBytesWritten);
  304.                 }
  305.             }
  306.             WriteConsoleOutputCharacter(hConsole, pBuffer, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
  307.             Sleep(1000);
  308.         }
  309.  
  310.         // Create game screen
  311.         for (int i = 0; i < nScreenWidth; i++)
  312.         {
  313.             for (int j = 0; j < nScreenHeight; j++)
  314.             {
  315.                 pBuffer[j * nScreenWidth + i] = L' ';
  316.                 if (i == 0 || i >= nBoardWidth - 1 || j == nBoardHeight - 1)
  317.                 {
  318.                     pColor[j * nScreenWidth + i] = 8 * 16 + 9;
  319.                 }
  320.                 else
  321.                 {
  322.                     if (j % 2 == 1)
  323.                     {
  324.                         if (i % 4 == 1 || i % 4 == 2)
  325.                         {
  326.                             pColor[j * nScreenWidth + i] = 8 * 16 + 9;
  327.                         }
  328.                         else
  329.                         {
  330.                             pColor[j * nScreenWidth + i] = 7 * 16 + 9;
  331.                         }
  332.                     }
  333.                     else
  334.                     {
  335.                         if (i % 4 == 3 || i % 4 == 0)
  336.                         {
  337.                             pColor[j * nScreenWidth + i] = 8 * 16 + 9;
  338.                         }
  339.                         else
  340.                         {
  341.                             pColor[j * nScreenWidth + i] = 7 * 16 + 9;
  342.                         }
  343.                     }
  344.                 }
  345.             }
  346.         }
  347.  
  348.         Frame(pBuffer, L"[ SCORE ]", 17, 3, nBoardWidth, 1);
  349.         Frame(pBuffer, L"[ LINE ]", 17, 3, nBoardWidth, 4);
  350.         Frame(pBuffer, L"[ NEXT ]", 17, 6, nBoardWidth, 7);
  351.  
  352.         // Game data
  353.         int* pMatrix = new int[nBoardWidth * nBoardHeight];
  354.         for (int i = 0; i < nBoardWidth; i++)
  355.         {
  356.             for (int j = 0; j < nBoardHeight; j++)
  357.             {
  358.                 if (j == nBoardHeight - 1)
  359.                 {
  360.                     if (i == 0)
  361.                     {
  362.                         pMatrix[j * nBoardWidth + i] = 4;
  363.                     }
  364.                     else if (i == nBoardWidth - 1)
  365.                     {
  366.                         pMatrix[j * nBoardWidth + i] = 5;
  367.                     }
  368.                     else
  369.                     {
  370.                         pMatrix[j * nBoardWidth + i] = 7;
  371.                     }
  372.                 }
  373.                 else
  374.                 {
  375.                     if (i == 0 || i == nBoardWidth - 1)
  376.                     {
  377.                         pMatrix[j * nBoardWidth + i] = 6;
  378.                     }
  379.                     else
  380.                     {
  381.                         pMatrix[j * nBoardWidth + i] = 0;
  382.                     }
  383.                 }
  384.             }
  385.         }
  386.  
  387.         const vector<char> key = { 'W', 'A', 'S', 'D', 27 };
  388.         bool bKey[5];
  389.  
  390.         int nCurrentPiece = random(0, 6);
  391.         int nNextPiece = random(0, 6);
  392.         int nCurrentRotation = 0;
  393.         int nCurrentX = nBoardWidth / 2 - 4;
  394.         int nCurrentY = 0;
  395.  
  396.         int nFrame = 20;
  397.         int nFrameCount = 0;
  398.  
  399.         bool bForceDown = 0;
  400.  
  401.         bool bRotateHold = 1;
  402.  
  403.         int nLevelLimit = 2;
  404.         int nPieceCount = 0;
  405.  
  406.         int nScore = 0;
  407.         int nScorePosX = 37;
  408.         int nScoreComp = 10;
  409.  
  410.         int nLine = 0;
  411.         int nLinePosX = 37;
  412.         int nLineComp = 10;
  413.  
  414.         vector<int> vLines;
  415.  
  416.         // Game loop
  417.         while (1)
  418.         {
  419.             // GAME TIMING
  420.             Sleep(50);
  421.             nFrameCount++;
  422.             if (nFrameCount == nFrame)
  423.             {
  424.                 bForceDown = 1;
  425.             }
  426.             else
  427.             {
  428.                 bForceDown = 0;
  429.             }
  430.  
  431.             // INPUT
  432.             for (int i = 0; i < key.size(); i++)
  433.             {
  434.                 if ((GetKeyState(key.at(i)) & 0x8000) != 0)
  435.                 {
  436.                     bKey[i] = 1;
  437.                 }
  438.                 else
  439.                 {
  440.                     bKey[i] = 0;
  441.                 }
  442.             }
  443.  
  444.             // GAME LOGIC
  445.  
  446.             // Game over limit
  447.             int nLimit = 0;
  448.             if (nCurrentPiece == 3)
  449.             {
  450.                 nLimit = -1;
  451.             }
  452.  
  453.             // Handling input
  454.             if (bKey[3] == 1 && nCurrentY >= nLimit)
  455.             {
  456.                 if (CheckPiece(pMatrix, nCurrentPiece, nCurrentRotation, nCurrentX + 2, nCurrentY) == 1)
  457.                 {
  458.                     nCurrentX += 2;
  459.                 }
  460.             }
  461.  
  462.             if (bKey[1] == 1 && nCurrentY >= nLimit && CheckPiece(pMatrix, nCurrentPiece, nCurrentRotation, nCurrentX - 2, nCurrentY) == 1)
  463.             {
  464.                 nCurrentX -= 2;
  465.             }
  466.  
  467.             if (bKey[2] == 1 && nCurrentY >= nLimit)
  468.             {
  469.                 int i{};
  470.                 while (CheckPiece(pMatrix, nCurrentPiece, nCurrentRotation, nCurrentX, nCurrentY + i) == 1)
  471.                 {
  472.                     i++;
  473.                 }
  474.                 nCurrentY += i - 1;
  475.             }
  476.  
  477.             if (bKey[0] == 1 && nCurrentY >= nLimit && bRotateHold == 1 && CheckPiece(pMatrix, nCurrentPiece, (nCurrentRotation + 1) % 4, nCurrentX, nCurrentY) == 1)
  478.             {
  479.                 nCurrentRotation++;
  480.                 nCurrentRotation %= 4;
  481.                 bRotateHold = 0;
  482.             }
  483.             else
  484.             {
  485.                 bRotateHold = 1;
  486.             }
  487.  
  488.             // Pause
  489.             if (bKey[4] == 1)
  490.             {
  491.                 int nSelect = 0;
  492.                 WORD* pTmpColor = new WORD[nScreenWidth * nScreenHeight];
  493.  
  494.                 for (int i = 0; i < nScreenWidth * nScreenHeight; i++)
  495.                 {
  496.                     pTmpColor[i] = pColor[i];
  497.                 }
  498.  
  499.                 while (1)
  500.                 {
  501.                     Text(pBuffer, pTmpColor, L" ═════ PAUSE ════ ", 10 * 16 + 11, 2, 8);
  502.                     Text(pBuffer, pTmpColor, L"                  ", 10 * 16 + 11, 2, 9);
  503.                     Text(pBuffer, pTmpColor, L" ════════════════ ", 10 * 16 + 11, 2, 12);
  504.  
  505.  
  506.                     if (nSelect == 0)
  507.                     {
  508.                         Text(pBuffer, pTmpColor, L" >>  Continue  << ", 10 * 16 + 4, 2, 10);
  509.                         Text(pBuffer, pTmpColor, L"       Quit       ", 10 * 16 + 11, 2, 11);
  510.  
  511.                         if (GetKeyState('S') & 0x8000)
  512.                         {
  513.                             nSelect++;
  514.                         }
  515.                         else if (GetKeyState(13) & 0x8000)
  516.                         {
  517.                             break;
  518.                         }
  519.                     }
  520.                     else
  521.                     {
  522.                         Text(pBuffer, pTmpColor, L"     Continue     ", 10 * 16 + 11, 2, 10);
  523.                         Text(pBuffer, pTmpColor, L" >>    Quit    << ", 10 * 16 + 6, 2, 11);
  524.  
  525.                         if (GetKeyState('W') & 0x8000)
  526.                         {
  527.                             nSelect--;
  528.                         }
  529.                         else if (GetKeyState(13) & 0x8000)
  530.                         {
  531.                             return 0;
  532.                         }
  533.                     }
  534.  
  535.                     for (int j = 0; j < nScreenHeight; j++)
  536.                     {
  537.                         for (int i = 0; i < nScreenWidth; i++)
  538.                         {
  539.                             COORD cPos;
  540.                             cPos.X = i;
  541.                             cPos.Y = j;
  542.                             WriteConsoleOutputAttribute(hConsole, &pTmpColor[j * nScreenWidth + i], 1, cPos, &dwBytesWritten);
  543.                         }
  544.                     }
  545.                     WriteConsoleOutputCharacter(hConsole, pBuffer, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
  546.                 }
  547.             }
  548.  
  549.             // Move down
  550.             if (bForceDown)
  551.             {
  552.                 // Update difficulty
  553.                 nFrameCount = 0;
  554.                 if (nPieceCount == nLevelLimit && nFrame >= 5)
  555.                 {
  556.                     nFrame--;
  557.                     nPieceCount = 0;
  558.                     nLevelLimit *= 2;
  559.                 }
  560.  
  561.                 // Test if piece can be moved down
  562.                 if (CheckPiece(pMatrix, nCurrentPiece, nCurrentRotation, nCurrentX, nCurrentY + 1))
  563.                 {
  564.                     nCurrentY++;
  565.                 }
  566.                 else
  567.                 {
  568.                     // If the tetromino has not appeared completely, game over
  569.                     if (nCurrentY < nLimit)
  570.                     {
  571.                         break;
  572.                     }
  573.                     else
  574.                     {
  575.                         nPieceCount++;
  576.  
  577.                         //Fix the tetromino
  578.                         for (int i = 0; i < 8; i++)
  579.                         {
  580.                             for (int j = 0; j < 4; j++)
  581.                             {
  582.                                 if (nCurrentY >= 0 && tetromino.at(nCurrentPiece).at(nCurrentRotation).at(j * 8 + i) != L'.')
  583.                                 {
  584.                                     pMatrix[(nCurrentY + j) * nBoardWidth + (nCurrentX + i)] = 2;
  585.                                     if ((nCurrentY + j) % 2 == 1)
  586.                                     {
  587.                                         if ((nCurrentX + i) % 4 == 1 || (nCurrentX + i) % 4 == 2)
  588.                                         {
  589.                                             pColor[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = 8 * 16 + nCurrentPiece;
  590.                                         }
  591.                                         else
  592.                                         {
  593.                                             pColor[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = 7 * 16 + nCurrentPiece;
  594.                                         }
  595.                                     }
  596.                                     else
  597.                                     {
  598.                                         if ((nCurrentX + i) % 4 == 3 || (nCurrentX + i) % 4 == 0)
  599.                                         {
  600.                                             pColor[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = 8 * 16 + nCurrentPiece;
  601.                                         }
  602.                                         else
  603.                                         {
  604.                                             pColor[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = 7 * 16 + nCurrentPiece;
  605.                                         }
  606.                                     }
  607.                                 }
  608.                             }
  609.                         }
  610.  
  611.                         // Check for lines
  612.                         for (int j = 0; j < 4; j++)
  613.                         {
  614.                             if (nCurrentY + j < nBoardHeight - 1)
  615.                             {
  616.                                 bool bLine = 1;
  617.                                 for (int i = 1; i < nBoardWidth - 1; i++)
  618.                                 {
  619.                                     if (pMatrix[(nCurrentY + j) * nBoardWidth + i] == 0)
  620.                                     {
  621.                                         bLine = 0;
  622.                                         break;
  623.                                     }
  624.                                 }
  625.  
  626.                                 if (bLine == 1)
  627.                                 {
  628.                                     nLine++;
  629.  
  630.                                     // A little animation
  631.                                     for (int i = 1; i < nBoardWidth - 1; i++)
  632.                                     {
  633.                                         pMatrix[(nCurrentY + j) * nBoardWidth + i] = 3;
  634.                                     }
  635.                                     vLines.push_back(nCurrentY + j);
  636.                                 }
  637.                             }
  638.                         }
  639.  
  640.                         // Increase score
  641.                         nScore += 25;
  642.                         if (!vLines.empty())
  643.                         {
  644.                             nScore += (1 << vLines.size()) * 100;
  645.                         }
  646.  
  647.                         // Pick new tetromino
  648.                         nCurrentX = nBoardWidth / 2 - 4;
  649.                         nCurrentY = -4;
  650.                         nCurrentRotation = 0;
  651.                         nCurrentPiece = nNextPiece;
  652.                         nNextPiece = random(0, 6);
  653.                     }
  654.                 }
  655.             }
  656.  
  657.             // DISPLAY
  658.  
  659.             // Frame
  660.             for (int i = 0; i < nBoardWidth; i++)
  661.             {
  662.                 for (int j = 0; j < nBoardHeight; j++)
  663.                 {
  664.                     pBuffer[j * nScreenWidth + i] = detail[pMatrix[j * nBoardWidth + i]];
  665.                 }
  666.             }
  667.  
  668.             // Current tetromino
  669.             for (int i = 0; i < 8; i++)
  670.             {
  671.                 for (int j = 0; j < 4; j++)
  672.                 {
  673.                     if (tetromino.at(nCurrentPiece).at(nCurrentRotation).at(j * 8 + i) != L'.' && nCurrentY + j >= 0)
  674.                     {
  675.                         if ((nCurrentY + j) % 2 == 1)
  676.                         {
  677.                             if ((nCurrentX + i) % 4 == 1 || (nCurrentX + i) % 4 == 2)
  678.                             {
  679.                                 pColor[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = 8 * 16 + nCurrentPiece;
  680.                             }
  681.                             else
  682.                             {
  683.                                 pColor[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = 7 * 16 + nCurrentPiece;
  684.                             }
  685.                         }
  686.                         else
  687.                         {
  688.                             if ((nCurrentX + i) % 4 == 3 || (nCurrentX + i) % 4 == 0)
  689.                             {
  690.                                 pColor[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = 8 * 16 + nCurrentPiece;
  691.                             }
  692.                             else
  693.                             {
  694.                                 pColor[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = 7 * 16 + nCurrentPiece;
  695.                             }
  696.                         }
  697.                         pBuffer[(nCurrentY + j) * nScreenWidth + (nCurrentX + i)] = L'▓';
  698.                     }
  699.                 }
  700.             }
  701.  
  702.             // Next tetromino
  703.             Block(pBuffer, pColor, nNextPiece, 26, 8);
  704.  
  705.             // Score
  706.             if (nScore >= nScoreComp)
  707.             {
  708.                 nScorePosX--;
  709.                 nScoreComp *= 10;
  710.             }
  711.             Text(pBuffer, pColor, to_wstring(nScore), 8 * 16 + 9, nScorePosX, 2);
  712.  
  713.             // Line
  714.             if (nLine >= nLineComp)
  715.             {
  716.                 nLinePosX--;
  717.                 nLineComp *= 10;
  718.             }
  719.             Text(pBuffer, pColor, to_wstring(nLine), 8 * 16 + 9, nLinePosX, 5);
  720.  
  721.             // Destroy the lines
  722.             if (!vLines.empty())
  723.             {
  724.                 WriteConsoleOutputCharacter(hConsole, pBuffer, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
  725.                 Sleep(400);
  726.  
  727.                 for (int l = 0; l < vLines.size(); l++)
  728.                 {
  729.                     for (int i = 1; i < nBoardWidth - 1; i++)
  730.                     {
  731.                         for (int j = vLines.at(l); j > 0; j--)
  732.                         {
  733.                             if (j % 2 == 0)
  734.                             {
  735.                                 if (i % 4 == 1 || i % 4 == 2)
  736.                                 {
  737.                                     pColor[j * nScreenWidth + i] = pColor[(j - 1) * nScreenWidth + i] - 16;
  738.                                 }
  739.                                 else
  740.                                 {
  741.                                     pColor[j * nScreenWidth + i] = pColor[(j - 1) * nScreenWidth + i] + 16;
  742.                                 }
  743.                             }
  744.                             else
  745.                             {
  746.                                 if (i % 4 == 1 || i % 4 == 2)
  747.                                 {
  748.                                     pColor[j * nScreenWidth + i] = pColor[(j - 1) * nScreenWidth + i] + 16;
  749.                                 }
  750.                                 else
  751.                                 {
  752.                                     pColor[j * nScreenWidth + i] = pColor[(j - 1) * nScreenWidth + i] - 16;
  753.                                 }
  754.                             }
  755.                             pMatrix[j * nBoardWidth + i] = pMatrix[(j - 1) * nBoardWidth + i];
  756.                         }
  757.                         pMatrix[i] = 0;
  758.                     }
  759.                 }
  760.                 vLines.clear();
  761.             }
  762.  
  763.             for (int j = 0; j < nScreenHeight; j++)
  764.             {
  765.                 for (int i = 0; i < nScreenWidth; i++)
  766.                 {
  767.                     COORD cPos;
  768.                     cPos.X = i;
  769.                     cPos.Y = j;
  770.                     WriteConsoleOutputAttribute(hConsole, &pColor[j * nScreenWidth + i], 1, cPos, &dwBytesWritten);
  771.                 }
  772.             }
  773.             WriteConsoleOutputCharacter(hConsole, pBuffer, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
  774.         }
  775.  
  776.         // Game over
  777.         const vector<wstring> wsGameOver = {
  778.             L"▄──┐┌──▄ ┌─▄─▄ ▄──",
  779.             L"█ ─┐├──█ │ ▀ █ █─ ",
  780.             L"▀──┘┴  ▀ ┴   ▀ ▀──",
  781.             L"▄──┐ ▄  ┬ ▄── ▄──┐",
  782.             L"█  │ █ ┌┘ █─  █─┬┘",
  783.             L"▀──┘ ▀─┘  ▀── ▀ └─"
  784.         };
  785.  
  786.         for (int i = 0; i < nScreenWidth; i++)
  787.         {
  788.             for (int j = 0; j < nScreenHeight; j++)
  789.             {
  790.                 pBuffer[j * nScreenWidth + i] = L' ';
  791.                 pColor[j * nScreenWidth + i] = 10 * 16 + 11;
  792.             }
  793.         }
  794.  
  795.         int nSelect = 0;
  796.         while (1)
  797.         {
  798.             for (int i = 0; i < wsGameOver.size(); i++)
  799.             {
  800.                 Text(pBuffer, pColor, wsGameOver.at(i), 10 * 16 + 1, 10, 3 + i);
  801.             }
  802.  
  803.             Text(pBuffer, pColor, L"════ SCORE ════", 10 * 16 + 3, 12, 11);
  804.             Text(pBuffer, pColor, L"═══════════════", 10 * 16 + 3, 12, 13);
  805.  
  806.             int nScorePosX = 19;
  807.             int nScoreComp = 100;
  808.             while (nScore >= nScoreComp)
  809.             {
  810.                 nScorePosX--;
  811.                 nScoreComp *= 100;
  812.             }
  813.  
  814.             Text(pBuffer, pColor, to_wstring(nScore), 10 * 16 + 3, nScorePosX, 12);
  815.  
  816.             if (nSelect == 0)
  817.             {
  818.                 Text(pBuffer, pColor, L">> Play Again <<", 10 * 16 + 4, 11, 17);
  819.                 Text(pBuffer, pColor, L"      Quit      ", 10 * 16 + 11, 11, 18);
  820.  
  821.                 if (GetKeyState('S') & 0x8000)
  822.                 {
  823.                     nSelect++;
  824.                 }
  825.                 if (GetKeyState(13) & 0x8000)
  826.                 {
  827.                     break;
  828.                 }
  829.             }
  830.             else
  831.             {
  832.                 Text(pBuffer, pColor, L"   Play Again   ", 10 * 16 + 11, 11, 17);
  833.                 Text(pBuffer, pColor, L">>    Quit    <<", 10 * 16 + 6, 11, 18);
  834.  
  835.                 if (GetKeyState('W') & 0x8000)
  836.                 {
  837.                     nSelect--;
  838.                 }
  839.                 if (GetKeyState(13) & 0x8000)
  840.                 {
  841.                     return 0;
  842.                 }
  843.             }
  844.  
  845.             for (int j = 0; j < nScreenHeight; j++)
  846.             {
  847.                 for (int i = 0; i < nScreenWidth; i++)
  848.                 {
  849.                     COORD cPos;
  850.                     cPos.X = i;
  851.                     cPos.Y = j;
  852.                     WriteConsoleOutputAttribute(hConsole, &pColor[j * nScreenWidth + i], 1, cPos, &dwBytesWritten);
  853.                 }
  854.             }
  855.             WriteConsoleOutputCharacter(hConsole, pBuffer, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
  856.         }
  857.     }
  858.  
  859.     return 0;
  860. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement