Guest User

Untitled

a guest
Dec 21st, 2018
2,053
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.71 KB | None | 0 0
  1. //------------------------------------------------------------------------------
  2.  
  3. #ifndef TetrisH
  4. #define TetrisH
  5.  
  6. //------------------------------------------------------------------------------
  7.  
  8. #include <vcl.h>
  9. #include <mem.h>
  10.  
  11. #include "Figures.h"
  12.  
  13. //------------------------------------------------------------------------------
  14. //
  15. // class Figure
  16. //
  17. //------------------------------------------------------------------------------
  18.  
  19. // класс фигуры
  20. class Figure {
  21.    
  22.     friend class Glass;
  23.    
  24.     // массив данных фигуры
  25.     bool data[4][4];
  26.    
  27. public:
  28.  
  29.     // конструктор
  30.     Figure() {
  31.         clear();
  32.     }
  33.  
  34.     // очистка фигуры
  35.     void clear() {
  36.         memset(data, 0, sizeof(data));
  37.     }
  38.    
  39.     // инициализация фигуры из массива символов
  40.     void init(char d[4][4]) {  
  41.        
  42.         for (int i=0; i<4; i++) {
  43.             for (int j=0; j<4; j++) {
  44.                 data[i][j] = d[i][j] != ' ';
  45.             }
  46.         }
  47.        
  48.     }
  49.    
  50.     // инициализация фигуры из 4 строк
  51.     void init(char l0[4], char l1[4], char l2[4], char l3[4]) {
  52.        
  53.         for (int i=0;i<4;i++) {
  54.             data[0][i] = l0[i] != ' ';
  55.             data[1][i] = l1[i] != ' ';
  56.             data[2][i] = l2[i] != ' ';
  57.             data[3][i] = l3[i] != ' ';
  58.         }
  59.     }
  60.    
  61.     // создавть фигуру в сцене
  62.     void createFigure(Scene &scene, int x, int y, int size = 5) {
  63.        
  64.         // будем хранить указатель только на одну ноду,
  65.         // будем ее двигать
  66.         // и удалять вместе с потомками
  67.         origin_node = new OriginNode(&Scene);
  68.         origin_node->setPos(vec3(x, y, 0.0f));
  69.         origin_node->setScale(vec3(size, size, size));
  70.        
  71.         for (int i=0;i<4;i++) {
  72.             for (int j=0;j<4;j++) {
  73.                
  74.                 if (data[j][i] == false) continue;
  75.                 MeshNode *node = new MeshNode(Scene, "Core/Primitives/pBox.mesh");
  76.                 node->setPos(vec3(i, j, 0.0f));
  77.                 node->setParent(origin_node, false);
  78.                
  79.             }
  80.         }
  81.        
  82.     }
  83.    
  84. };
  85.  
  86. //------------------------------------------------------------------------------
  87. //
  88. // class Glass
  89. //
  90. //------------------------------------------------------------------------------
  91.  
  92. // стакан
  93. class Glass {
  94.    
  95.    
  96.     int **data;     // массив стакана
  97.     int width;      // ширина стакана
  98.     int height;     // высота стакана
  99.  
  100.     // освободить память
  101.     void release() {
  102.        
  103.         for (int i=0; i<height; i++) {
  104.             delete []data[i];
  105.         }
  106.        
  107.         delete []data;
  108.         data = NULL;   
  109.        
  110.     }
  111.    
  112. public:
  113.    
  114.     // конструктор
  115.     Glass(int w = 10, int h = 20) {
  116.         setSize(w, h);
  117.         clear();
  118.     }
  119.  
  120.     // деструктор
  121.     ~Glass() {
  122.         release();
  123.     }
  124.    
  125.     // изменить размер стакана
  126.     void setSize(int w = 10, int h = 20) {
  127.        
  128.         release();
  129.  
  130.         width = w;
  131.         height = h;
  132.         data = new int *[height];  
  133.        
  134.         for (int i=0; i<height; i++) {
  135.             data[i] = new int[width];
  136.         }
  137.            
  138.         clear();   
  139.     }
  140.  
  141.     // очистить стакан
  142.     void clear() {
  143.        
  144.         for (int i=0; i<width; i++) {
  145.             for (int j=0; j<height; j++) {
  146.                 data[j][i] = 0;
  147.             }
  148.         }
  149.        
  150.     }
  151.  
  152.     // рисовать стакан
  153.     void render(TCanvas *canvas, int x = 0, int y = 0, int size = 5) {
  154.        
  155.         for (int i=0; i<width; i++) {
  156.             for (int j=0; j<height; j++) {
  157.                
  158.                 if (data[j][i] == 0) continue;
  159.                
  160.                 canvas->Brush->Color = colors[data[j][i]-1];
  161.                 canvas->Rectangle(x + i*size, y + j*size, x + (i+1)*size, y + (j+1)*size);
  162.                
  163.             }
  164.         }
  165.        
  166.     }
  167.  
  168.     // проверить столкновение фигуры со стаканом
  169.     // x, y - смещение фигуры относительно стакана
  170.     bool collide(int x, int y, const Figure &figure) {
  171.        
  172.         for (int i=0; i<4; i++) {
  173.             for (int j=0; j<4; j++) {
  174.                
  175.                 // если элемент фигуры не закрашен, столкновение не проверяем
  176.                 if (figure.data[i][j] ==) continue;
  177.                
  178.                
  179.                 // если элемент фигуры выходит за границы стакана или под элементом не пусто
  180.                 if (j + x < 0 || i + y < 0 || j + x >= width || i + y >= height || data[i + y][j + x]) {
  181.                     return true; // столкновение есть
  182.                 }
  183.                
  184.             }
  185.         }
  186.        
  187.         return false; // столкновения нет
  188.     }
  189.  
  190.     // установить фигуру в стакан и вернуть true если фигура установлена
  191.     bool place(int x, int y, const Figure &figure, int col = 1) {
  192.        
  193.         if (collide(x, y, figure)) return false; // фигура не установлена
  194.        
  195.         for (int i=0; i<4; i++) {
  196.             for (int j=0; j<4; j++) {
  197.                 if (figure.data[i][j] == false) continue;
  198.                 data[i + y][j + x] = col + 1;
  199.             }
  200.         }
  201.        
  202.         return true; // фигура установлена
  203.     }
  204.    
  205.     // проверить заполненные линии, удалить и вернуть их количество
  206.     int checkLines() {
  207.        
  208.         // количество заполненных линий
  209.         int lines = 0;
  210.        
  211.         for (int i=0; i<height; i++) {
  212.            
  213.             // флаг заполненности линии
  214.             bool is_line_full = true;
  215.            
  216.             for (int j=0; j<width; j++)
  217.                
  218.                 // если хотя бы один элемент линии не заполнен
  219.                 if (data[i][j] != 0) continue;
  220.                
  221.                 // сброить флаг заполненности
  222.                 is_line_full = false;
  223.                 break;
  224.             }
  225.            
  226.             // если линия заполнена
  227.             if (is_line_full) {
  228.                
  229.                 // увеличить счетчик заполненных линий
  230.                 lines++;
  231.                
  232.                 // удалить линию
  233.                 for (int k=i; k>0; k--) {
  234.                     for (int l=0; l<width; l++) {
  235.                         data[k][l] = data[k - 1][l];
  236.                     }
  237.                 }
  238.             }
  239.         }
  240.        
  241.         // вернуть количество удаленных заполненных линий
  242.         return lines;
  243.        
  244.     }
  245.    
  246.     // получить центра стакана
  247.     int getCenter() {  
  248.         return (width - 2) / 2;
  249.     }
  250.    
  251.     // получить ширину стакана
  252.     int getWidth() {   
  253.         return width;
  254.     }
  255.    
  256.     // получить высоту стакана
  257.     int getHeight() {  
  258.         return height;
  259.     }
  260.    
  261. };
  262.  
  263. //------------------------------------------------------------------------------
  264. //
  265. // class Tetris
  266. //
  267. //------------------------------------------------------------------------------
  268.  
  269. // игра тетрис
  270. class Tetris {
  271.    
  272.     int x;                  // х координата падающей фигуры
  273.     int y;                  // у координата падающей фигуры
  274.     int rotation;           // поворот падающей фигуры
  275.     int current;            // тип текущей фигуры
  276.     int next;               // тип следующей фигуры
  277.    
  278.     Glass field;            // игровое поле
  279.     Figure figure[7][4];    // все фигуры, используемые в игре
  280.    
  281.     int score;              // счет
  282.     int scSingle;           // количество одинарных линий
  283.     int scDouble;           // количество двойных линий
  284.     int scTriple;           // количество тройных линий
  285.     int scQuadra;           // количество четверных линий
  286.    
  287. public:
  288.    
  289.  
  290.     Tetris() {
  291.        
  292.         // иницилизировать фигуры из массива фигур
  293.         for (int i=0; i<7; i++) {
  294.             for (int j=0; j<4; j++) {
  295.                 figure[i][j].init(figures[i][j]);
  296.             }
  297.         }
  298.        
  299.         newGame();
  300.        
  301.     }
  302.    
  303.     // рисовать игру
  304.     void render(TCanvas *canvas, int size = 10) {
  305.    
  306.         canvas->Brush->Color = 0x00000000;
  307.         canvas->Rectangle(0, 0, field.getWidth()*size, field.getHeight()*size);
  308.  
  309.         canvas->Rectangle(
  310.             (field.getWidth()+1)*size, field.getHeight()/2*size,
  311.             (field.getWidth()+1)*size+size*4, field.getHeight()/2*size+size*4);
  312.  
  313.         canvas->Brush->Color = colors[next];
  314.         figure[next][0].render(canvas, (field.getWidth()+1)*size, field.getHeight()/2*size, size);
  315.  
  316.         field.render(canvas, 0,0, size);
  317.         canvas->Brush->Color = colors[current];
  318.         figure[current][rotation].render(canvas, x*size, y*size, size);
  319.     }
  320.  
  321.     // инициировать новую игру
  322.     void newGame() {
  323.        
  324.         // сбросить счет
  325.         score       = 0;
  326.         scSingle    = 0;
  327.         scDouble    = 0;
  328.         scTriple    = 0;
  329.         scQuadra    = 0;
  330.        
  331.         // очистить поле
  332.         field.clear();
  333.        
  334.         // иницилизировать первую и следующую фигуры
  335.         randomize();
  336.         next = random(7);
  337.         nextFigure();
  338.        
  339.     }
  340.    
  341.     // сделать следующую фигуру текущей и создать следующую
  342.     virtual void nextFigure() {
  343.         current = next;
  344.         next = random(7);
  345.         rotation = 0;
  346.         x = field.getCenter();
  347.         y = 0;
  348.     }
  349.  
  350.     // обновить игру
  351.     void update() {
  352.         moveDown();
  353.     }
  354.  
  355.     void moveSide(int delta) {
  356.         if (field.collide(x + delta, y, figure[current][rotation]) == false) {
  357.             // двигать
  358.             x += delta;
  359.         }
  360.     }
  361.    
  362.     // двигать фигуру влево
  363.     void moveLeft() {
  364.         moveSide(-1);
  365.     }
  366.    
  367.     // двигать фигуру вправо
  368.     void moveRight() {
  369.         moveSide(+1);
  370.     }
  371.    
  372.     // двигать фигуру вниз
  373.     void moveDown() {
  374.        
  375.         // если не столкнемся
  376.         if (field.collide(x, y + 1, figure[current][rotation]) == false) {
  377.             // двигать
  378.             y ++;
  379.         } else {
  380.             // иначе установить
  381.             field.place(x, y, figure[current][rotation], current);
  382.            
  383.             // проверить линии
  384.             int s = field.checkLines();
  385.            
  386.             // посчитать очки и статистику
  387.             score += s * s;
  388.             switch (s)  {
  389.                 case 1:scSingle++;break;
  390.                 case 2:scDouble++;break;
  391.                 case 3:scTriple++;break;
  392.                 case 4:scQuadra++;break;
  393.                 default:
  394.             }
  395.            
  396.             // создать следующую фигуру
  397.             nextFigure();
  398.            
  399.         }  
  400.     }
  401.    
  402.     // повернуть фигуру
  403.     void turn() {
  404.  
  405.         int new_rotation = (rotation + 1) % 4;
  406.         // если не столкнемся
  407.         if (field.collide(x, y, figure[current][new_rotation]) == false) {
  408.             // повернуть фигуру
  409.             rotation = new_rotation;
  410.         } else {
  411.             float move_inside_delta = 1;
  412.             float sign = -1;
  413.             if (x < 4) sign = 1;
  414.             while (field.collide(x + move_inside_delta * sign, y, figure[current][new_rotation]) == true) {
  415.                 move_inside_delta ++;
  416.                 if (move_inside_delta > 4) return;
  417.             }
  418.             moveSide(move_inside_delta * sign);
  419.             rotation = new_rotation;
  420.         }
  421.     }
  422.  
  423.     // хуйня какая-то не помню зачем
  424.     int getOptimalSize(int w, int h)
  425.     {
  426.         if ((float)w/(float)field.getWidth() < (float)h/(float)field.getHeight())
  427.             return w/field.getWidth();
  428.         else
  429.             return h/field.getHeight();
  430.     }
  431.    
  432. };
  433.  
  434. //------------------------------------------------------------------------------
  435.  
  436. #endif
  437.  
  438. //------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment