MaximCherchuk

Tetris

Apr 9th, 2015
224
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.88 KB | None | 0 0
  1. #include <iostream>
  2. #include <windows.h>
  3. #include <time.h>
  4. #include <sstream>
  5.  
  6. using namespace std;
  7.  
  8. const int FIELD_WIDTH = 10;
  9. const int FIELD_HEIGHT = 24;
  10. const int FIELD_HIDDEN = 4;
  11.  
  12. const int SQUARE_SIZE = 30;
  13. const int WINDOW_WIDTH = 440;
  14. const int WINDOW_HEIGHT = 600;
  15.  
  16. const int COLORS = 4;
  17. const int BLOCKS = 5;
  18.  
  19. char map[FIELD_HEIGHT][FIELD_WIDTH];
  20. int nextBlock[4][4];
  21. int currentBlock[4][4];
  22. int currentX, currentY;
  23.  
  24. int score = 0;
  25.  
  26. const int colors[COLORS + 1][3] = {
  27.     { 220, 220, 220 },
  28.     { 220, 0, 0 },
  29.     { 0, 150, 0 },
  30.     { 0, 0, 220 },
  31.     { 175, 175, 0 }
  32. };
  33.  
  34. const bool blocks[BLOCKS][4][4] = {
  35.     {
  36.         { 0, 1, 0, 0 },
  37.         { 0, 1, 0, 0 },
  38.         { 0, 1, 0, 0 },
  39.         { 0, 1, 0, 0 }
  40.     },
  41.     {
  42.         { 1, 0, 0, 0 },
  43.         { 1, 0, 0, 0 },
  44.         { 1, 1, 0, 0 },
  45.         { 0, 0, 0, 0 }
  46.     },
  47.     {
  48.         { 0, 1, 0, 0 },
  49.         { 0, 1, 0, 0 },
  50.         { 1, 1, 0, 0 },
  51.         { 0, 0, 0, 0 }
  52.     },
  53.     {
  54.         { 0, 1, 0, 0 },
  55.         { 1, 1, 0, 0 },
  56.         { 1, 0, 0, 0 },
  57.         { 0, 0, 0, 0 }
  58.     },
  59.     {
  60.         { 1, 1, 0, 0 },
  61.         { 1, 1, 0, 0 },
  62.         { 0, 0, 0, 0 },
  63.         { 0, 0, 0, 0 }
  64.     },
  65. };
  66.  
  67. void init(HWND);
  68. void update(HWND);
  69. void draw(HDC);
  70. void moveDown(HWND);
  71. void rotateCurrent();
  72. void moveLeft();
  73. void moveRight();
  74.  
  75. void drawRect(HDC hdc, int x, int y, int width, int height, int r, int g, int b) {
  76.     RECT rect = { x, y, x + width, y + height};
  77.     HBRUSH brush = CreateSolidBrush(RGB(r, g, b));
  78.     FillRect(hdc, &rect, brush);
  79.     DeleteObject(brush);
  80. }
  81.  
  82. void redraw(HWND hWnd) {
  83.     RECT rect;
  84.     GetClientRect(hWnd, &rect);
  85.     InvalidateRect(hWnd, &rect, true);
  86. }
  87.  
  88. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
  89.     PAINTSTRUCT ps;
  90.     HDC hdc;
  91.     HDC backBufferDC;
  92.     HBITMAP backBuffer;
  93.     HBITMAP realBackBuffer;
  94.     int savedDC;
  95.  
  96.     switch (message) {
  97.         case WM_ERASEBKGND:
  98.             return 1;
  99.         case WM_PAINT:
  100.             hdc = BeginPaint(hWnd, &ps);
  101.  
  102.             backBufferDC = CreateCompatibleDC(hdc);
  103.             backBuffer = CreateCompatibleBitmap(hdc, WINDOW_WIDTH, WINDOW_HEIGHT);
  104.             SelectObject(backBufferDC, backBuffer);
  105.            
  106.             draw(backBufferDC);
  107.  
  108.             BitBlt(hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, backBufferDC, 0, 0, SRCCOPY);
  109.  
  110.             SelectObject(backBufferDC, backBuffer);
  111.             DeleteObject(backBuffer);
  112.             DeleteDC(backBufferDC);
  113.  
  114.             EndPaint(hWnd, &ps);
  115.             break;
  116.         case WM_DESTROY:
  117.             PostQuitMessage(0);
  118.             break;
  119.         case WM_KEYDOWN:
  120.             if (wParam == 37) {
  121.                 moveLeft();
  122.                 redraw(hWnd);
  123.             } else if (wParam == 39) {
  124.                 moveRight();
  125.                 redraw(hWnd);
  126.             } else if (wParam == 40) {
  127.                 moveDown(hWnd);
  128.                 redraw(hWnd);
  129.             } else if (wParam == 32) {
  130.                 rotateCurrent();
  131.                 redraw(hWnd);
  132.             }
  133.             break;
  134.         case WM_TIMER:
  135.             update(hWnd);
  136.             redraw(hWnd);
  137.             break;
  138.         default:
  139.             return DefWindowProc(hWnd, message, wParam, lParam);
  140.     }
  141. }
  142.  
  143. //int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nCmdShow) {
  144. int main() {
  145.  
  146.     WNDCLASSEX wcex = { 0 };
  147.     wcex.cbSize = sizeof(WNDCLASSEX);
  148.     wcex.style = CS_HREDRAW | CS_VREDRAW;
  149.     wcex.lpfnWndProc = WndProc;
  150.     wcex.cbClsExtra = 0;
  151.     wcex.cbWndExtra = 0;
  152.     wcex.hInstance = (HINSTANCE)GetModuleHandle(NULL);
  153.     wcex.hIcon = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
  154.     wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  155.     wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  156.     wcex.lpszMenuName = NULL;
  157.     wcex.lpszClassName = "snakesnake";
  158.     wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
  159.  
  160.     if (!RegisterClassEx(&wcex)) {
  161.         return 1;
  162.     }
  163.    
  164.     RECT client = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
  165.     AdjustWindowRectEx(&client, WS_OVERLAPPEDWINDOW, false, NULL);
  166.     HWND hWnd = CreateWindowEx(NULL, "snakesnake", "Snake", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, -client.left + client.right, -client.top + client.bottom, NULL, NULL, wcex.hInstance, NULL);
  167.  
  168.     if (!hWnd) {
  169.         return 1;
  170.     }
  171.  
  172.     ShowWindow(hWnd, SW_SHOW);
  173.     UpdateWindow(hWnd);
  174.  
  175.     init(hWnd);
  176.    
  177.     MSG msg;
  178.     while (1) {
  179.         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  180.             if (msg.message == WM_QUIT) break;
  181.             TranslateMessage(&msg);
  182.             DispatchMessage(&msg);
  183.         }
  184.     }
  185.  
  186.     return msg.wParam;
  187. }
  188.  
  189. void cleanNext() {
  190.     for (int i = 0; i < 4; i++) {
  191.         for (int j = 0; j < 4; j++) {
  192.             nextBlock[i][j] = 0;
  193.         }
  194.     }
  195. }
  196.  
  197. void generateNextBlock() {
  198.     int nextBlockID = rand() % BLOCKS;
  199.     char nextColor = rand() % COLORS + 1;
  200.  
  201.     cleanNext();
  202.  
  203.     for (int i = 0; i < 4; i++) {
  204.         for (int j = 0; j < 4; j++) {
  205.             nextBlock[i][j] = blocks[nextBlockID][i][j] ? nextColor : 0;
  206.         }
  207.     }
  208. }
  209.  
  210. void setCurrentBlock() {
  211.     currentX = FIELD_WIDTH / 2 - 1;
  212.     for (int i = 0; i < 4; i++) {
  213.         for (int j = 0; j < 4; j++) {
  214.             currentBlock[i][j] = nextBlock[i][j];
  215.         }
  216.     }
  217.  
  218.     int size = 0;
  219.     for (int i = 0; i < 4; i++)
  220.         for (int j = 0; j < 4; j++)
  221.             if (currentBlock[i][j])
  222.                 size = max(max(size, i), j);
  223.  
  224.     currentY = 3 - size;
  225. }
  226.  
  227. void placeCurrentBlock(HWND hWnd) {
  228.     for (int i = 0; i < 4; i++) {
  229.         for (int j = 0; j < 4; j++) {
  230.             if (currentBlock[i][j]) {
  231.                 map[currentY + i][currentX + j] = currentBlock[i][j];
  232.                 if (currentY + i < FIELD_HIDDEN) {
  233.                     init(hWnd);
  234.                     return;
  235.                 }
  236.             }
  237.         }
  238.     }
  239. }
  240.  
  241. void init(HWND hWnd) {
  242.     srand(time(NULL));
  243.     KillTimer(hWnd, 3001);
  244.     SetTimer(hWnd, 3001, 260 - (int)sqrt(score / 100.0), NULL);
  245.     score = 0;
  246.     for (int i = 0; i < FIELD_HEIGHT; i++) {
  247.         for (int j = 0; j < FIELD_WIDTH; j++) {
  248.             map[i][j] = 0;
  249.         }
  250.     }
  251.     generateNextBlock();
  252.     setCurrentBlock();
  253.     generateNextBlock();
  254. }
  255.  
  256. void moveDown(HWND hWnd) {
  257.     currentY++;
  258.     for (int i = 0; i < 4; i++) {
  259.         for (int j = 0; j < 4; j++) {
  260.             if (currentBlock[i][j]) {
  261.                 if (currentY + i == FIELD_HEIGHT || map[currentY + i][currentX + j]) {
  262.                     currentY--;
  263.                     placeCurrentBlock(hWnd);
  264.                     setCurrentBlock();
  265.                     generateNextBlock();
  266.                     return;
  267.                 }
  268.             }
  269.         }
  270.     }
  271. }
  272.  
  273. void moveLeft() {
  274.     for (int i = 0; i < 4; i++) {
  275.         for (int j = 0; j < 4; j++) {
  276.             if (currentBlock[i][j]) {
  277.                 if (currentX - 1 + j < 0 || map[currentY + i][currentX - 1 + j]) {
  278.                     return;
  279.                 }
  280.             }
  281.         }
  282.     }
  283.     currentX--;
  284. }
  285.  
  286. void moveRight() {
  287.     for (int i = 0; i < 4; i++) {
  288.         for (int j = 0; j < 4; j++) {
  289.             if (currentBlock[i][j]) {
  290.                 if (currentX + 1 + j >= FIELD_WIDTH || map[currentY + i][currentX + 1 + j]) {
  291.                     return;
  292.                 }
  293.             }
  294.         }
  295.     }
  296.     currentX++;
  297. }
  298.  
  299. void rotateCurrent() {
  300.     int size = 0;
  301.     for (int i = 0; i < 4; i++)
  302.         for (int j = 0; j < 4; j++)
  303.             if (currentBlock[i][j])
  304.                 size = max(max(size, i), j);
  305.  
  306.     char newBlock[4][4];
  307.     for (int i = 0; i < 4; i++)
  308.         for (int j = 0; j < 4; j++)
  309.             newBlock[i][j] = 0;
  310.  
  311.     for (int i = 0; i <= size; i++)
  312.         for (int j = 0; j <= size; j++) {
  313.             newBlock[i][j] = currentBlock[size - j][i];
  314.             if (newBlock[i][j]) {
  315.                 if (currentX + j >= FIELD_WIDTH || currentX + j < 0 || currentY >= FIELD_HEIGHT || map[currentY + i][currentX + j]) {
  316.                     return;
  317.                 }
  318.             }
  319.         }
  320.  
  321.     for (int i = 0; i <= size; i++)
  322.         for (int j = 0; j <= size; j++)
  323.             currentBlock[i][j] = newBlock[i][j];
  324. }
  325.  
  326. void checkForLine(HWND hWnd) {
  327.     for (int i = FIELD_HIDDEN; i < FIELD_HEIGHT; i++) {
  328.         for (int j = 0; j < FIELD_WIDTH; j++) {
  329.             if (map[i][j] == 0) {
  330.                 goto away;
  331.             }
  332.         }
  333.         for (int j = i; j > 0; j--) {
  334.             for (int k = 0; k < FIELD_WIDTH; k++) {
  335.                 map[j][k] = map[j - 1][k];
  336.                 map[j - 1][k] = 0;
  337.             }
  338.         }
  339.  
  340.         score += 100;
  341.         KillTimer(hWnd, 3001);
  342.         SetTimer(hWnd, 3001, 260 - (int)sqrt(score / 50.0), NULL);
  343.  
  344.         away: continue;
  345.     }
  346. }
  347.  
  348. void update(HWND hWnd) {
  349.     moveDown(hWnd);
  350.     checkForLine(hWnd);
  351. }
  352.  
  353. void draw(HDC hdc) {
  354.     drawRect(hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 150, 150, 150);
  355.  
  356.     for (int i = FIELD_HIDDEN; i < FIELD_HEIGHT; i++) {
  357.         for (int j = 0; j < FIELD_WIDTH; j++) {
  358.             drawRect(hdc, j * SQUARE_SIZE + 1, (i - FIELD_HIDDEN) * SQUARE_SIZE + 1, SQUARE_SIZE - 2, SQUARE_SIZE - 2, colors[map[i][j]][0], colors[map[i][j]][1], colors[map[i][j]][2]);
  359.         }
  360.     }
  361.  
  362.     for (int i = 0; i < 4; i++) {
  363.         for (int j = 0; j < 4; j++) {
  364.             drawRect(hdc, FIELD_WIDTH * SQUARE_SIZE + 10 + j * SQUARE_SIZE + 1, (i + 1) * SQUARE_SIZE + 1, SQUARE_SIZE - 2, SQUARE_SIZE - 2, colors[nextBlock[i][j]][0], colors[nextBlock[i][j]][1], colors[nextBlock[i][j]][2]);
  365.         }
  366.     }
  367.  
  368.     for (int i = 0; i < 4; i++) {
  369.         for (int j = 0; j < 4; j++) {
  370.             if (currentY - FIELD_HIDDEN + i < 0) continue;
  371.             if (currentBlock[i][j] == 0) continue;
  372.             drawRect(hdc, (currentX + j) * SQUARE_SIZE + 1, (currentY - FIELD_HIDDEN + i) * SQUARE_SIZE + 1, SQUARE_SIZE - 2, SQUARE_SIZE - 2, colors[currentBlock[i][j]][0], colors[currentBlock[i][j]][1], colors[currentBlock[i][j]][2]);
  373.         }
  374.     }
  375.  
  376.     HFONT font = CreateFont(-20, 0, 0, 0, 0, ANSI_CHARSET, 0U, 0U, 0U, 0U, 0U, 0U, 0U, TEXT("Arial"));
  377.     HGDIOBJ obj = SelectObject(hdc, font);
  378.     SetTextColor(hdc, 0);
  379.     SetBkMode(hdc, TRANSPARENT);
  380.  
  381.     RECT rect = { FIELD_WIDTH * SQUARE_SIZE + 10, 5 * SQUARE_SIZE + 10, FIELD_WIDTH * SQUARE_SIZE + 10 + WINDOW_WIDTH - (FIELD_WIDTH * SQUARE_SIZE + 10), WINDOW_HEIGHT };
  382.    
  383.     ostringstream o;
  384.     o << "SCORE: " << score;
  385.  
  386.     string str = "";
  387.     str += o.str();
  388.     DrawText(hdc, str.c_str(), str.length(), &rect, 0);
  389.  
  390.     //RECT rect1 = { FIELD_WIDTH * SQUARE_SIZE + 10, 5 * SQUARE_SIZE + 35, FIELD_WIDTH * SQUARE_SIZE + 10 + WINDOW_WIDTH - (FIELD_WIDTH * SQUARE_SIZE + 10), WINDOW_HEIGHT };
  391.     //str = "";
  392.     //str += (int)sqrt(score / 50.0);
  393.     //DrawText(hdc, str.c_str(), str.length(), &rect1, 0);
  394.    
  395.     SelectObject(hdc, obj);
  396.     DeleteObject(font);
  397. }
Advertisement
Add Comment
Please, Sign In to add comment