Creative Russian Tetris

Keywords: C++ Windows less

Copyright Statement: Visitors may use the contents or services provided by this website for personal study, research or appreciation, and other non-commercial or non-profit purposes, but at the same time, they shall abide by the provisions of Copyright Law and other relevant laws, and shall not infringe upon the legitimate rights of this website and its relevant obligees. In addition, when any content or service of this website is used for other purposes, written permission and remuneration shall be obtained from this website and the relevant obligee. Reproduction should indicate the address of the article.

If the original author of this website is unwilling to publish the content on this website, please inform this website in time and delete it.

Author QQ: 1765813715

I wrote a copyright declaration because the game has poured a lot of time and creativity into me.

The game also adds two types of squares to the basic Russian squares.

One is the ghost box (which can be moved arbitrarily between squares until there is no space under the column in which it is located).

Another is the bomb box (which can be converted between activation and inactivation. When activated, it reaches the bottom and clears the surrounding 3*3 blocks, the inactivation is no different from the normal box.

The first time I wrote a game with Windows Api, there were a lot of comments. I also checked a lot of information.

After the creation of Windows windows windows, I am writing a detailed description here. I will start with CALLBACK WndProc to explain my program structure directly.

 

 

Let's talk about each function.

void DrawPanel(HDC hdc); Draw game panels

void RefreshPanel(HDC hdc); Refresh Game Panel
void creat(); Create a total of nine square.
bool isbottom(HWND hwnd); different ways of judging whether to reach the bottom; processing after reaching the bottom (i.e. explosion into a map or bomb box) and detecting the end of the game
bool drop(HDC hdc,HWND hwnd); drop where isbottom () is called if it reaches the bottom, call clear (), creat e (), refreshpanel ()
void move_left(); move left to detect collisions (ghost squares are also special handles)
void move_right(); ibid.
void transform(); Deformation Deformation needs to be checked to see if it meets Deformation of the bomb box is a transition between active and inactive states.
void clear(HDC hdc);
void preview(HDC hdc); Graphic preview box

 

Adding a process record here also helps other people like learning to have a clear path.

April 28, 6:00 p.m. - 12:00 p.m. - Learning Window Creation. How to Draw a Graphic Interface
April 29, 8 a.m. - 11.30. Write out the tested (block generation, collision detection, downward movement of clock system, pause function, end of game detection)
Untested (negative)
1 p.m. - 1:40 p.m. Complete the move around. Test the disappearance, but no reason has been found (sleep first)...
3 p.m. - 4 p.m. - Modify the Bus to complete the conversion function. By this time, the basic functions are almost complete.
Now the basic Russian cubes have been completed, but my Russian cubes are more advanced. There are two other types of cubes: the ghost cubes and the bomb cubes.
6 p.m. - 7 p.m. Game Test Find BUG (not to mention it)
11 p.m. - 11.30 p.m. Complete the ghost box
April 30 8-11 a.m. Complete the Bomb Block Graphic Preview
At 11 p.m. BGM is completed.

 

Note: I developed the test on vs2017. It can't be compiled on dev, and because I added BGM, it may not be compiled on your computer.

If header file is missing, Please add it yourself

If so, delete the code that plays BGM or load the resource file yourself

Here I upload my files to Baidu Disk. You can download them if you need. The EXE files in bebug and release can be directly used for play.

     http://pan.baidu.com/s/1cpf9AA

#include "stdafx.h"
#include <windows.h>

// C Runtime header file
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include<time.h>
#include<iostream>
#include "Tetris.h"
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")//Knowledge is wealth. A background music has been playing for a long time.
#define CELL 20//Block size
#define ROWS 25 //Row number
#define COLS 15//Column number
using namespace std;
TCHAR str[256];
int id; //Record the current box type
int next_id;//Record the next box ID Achieve Preview
int len;
int score = 0;                //Score
int level = 0;                    //Game Level
int speed = 500;                //The game rate is initialized to 1 second and then to 1 second.  speed-min(level,7)*100;
UINT timer = 0;
bool ispause = 0;            //Does the record pause?
bool panel[25][15] = { 0 };    //Record the bottom picture of the game
bool active;                //Record whether the bomb box is activated
int direction[8][2] = { 1,0,0,1,-1,0,0,-1,1,1,-1,-1,1,-1,-1,1 };//Eight Directions of Bomb Block Blasting
COORD pre_peak;
bool pre_panel[2][4];        //Preview Pane

bool* block=NULL;            //The location of the combination is determined by recording the coordinates of the leftmost upper corner of the block combination (which we later call the vertex) and the width and height of the combination. This has great benefits.
int block_top = 0;
int block_left = 0;
int block_height = 0;
int block_width = 0;

void DrawPanel(HDC hdc);
void RefreshPanel(HDC hdc);
void creat();
bool isbottom(HWND hwnd);
bool drop(HDC hdc,HWND hwnd);
void move_left();
void move_right();
void transform();
void clear(HDC hdc);
void preview(HDC hdc);
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lparam);//callback

//Building a window requires five steps to design the window type registration window type and create a display message loop
int APIENTRY WinMain(HINSTANCE hInstance,   //Instance Handles for Current Running of Programs
    HINSTANCE hPrevInstance,                //The previous instance of the current instance w32 Next does not work anymore.
    LPSTR lpCmdLine,                        //Represents command-line parameters passed to a program
    int nCmdShow)                          //Specify how program windows are displayed, such as maximizing and minimizing
{
    WNDCLASS wndclass;                    //The following are all registered content... (Much.)
    HWND hwnd;
    MSG msg;
    TCHAR lpszClassName[] = TEXT("Tetris");
    wndclass.style = CS_HREDRAW | CS_VREDRAW;           //window style
    wndclass.lpfnWndProc = WndProc;                     //Pointer to window function
    wndclass.cbClsExtra = 0;                            //Additional bytes of window class, shared for this kind of window, generally set 0
    wndclass.cbWndExtra = 0;                            //General value of window byte 0
    wndclass.hInstance = hInstance;                        //Instance Handles for Current Applications
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);    //Specify window icon
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);        //Specify window cursor
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//Setting Background Colors
    wndclass.lpszMenuName = NULL;                                //Window menu resource name
    wndclass.lpszClassName = lpszClassName;                        //Window class name
    if (!RegisterClass(&wndclass))                                //register
        return FALSE;
    hwnd = CreateWindow(lpszClassName, TEXT("Tetris"),        //Establish
        WS_OVERLAPPEDWINDOW, 
        CW_USEDEFAULT, CW_USEDEFAULT, 
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, 
        hInstance, NULL);
    ShowWindow(hwnd, nCmdShow);                                    //display
    UpdateWindow(hwnd);                                            //upload
    while (GetMessage(&msg, NULL, 0, 0))                        //Message loop
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)//Return function
{
    switch (message)
    {
    case WM_CREATE:
        PlaySound(                        //BGM
            MAKEINTRESOURCE(130),        //I don't know why I can't write directly here. IDR_WAVE1 It's about writing his numbers. id
            GetModuleHandle(NULL),
            SND_RESOURCE | SND_ASYNC | SND_LOOP);
        MoveWindow(hwnd, 200, 200, COLS*CELL+300, ROWS*CELL+40, FALSE);//16.40
        pre_peak.X = 16; pre_peak.Y = 2; //Determine the vertex coordinates of the preview box
        srand(int(time(0)));
        next_id = rand() % 9;
        creat();
        timer = SetTimer(hwnd, 1, speed - min(7, level) * 50, NULL);  //Create a clock
        return 0;
    case WM_PAINT:
        HDC hdc;
        PAINTSTRUCT ps;
        hdc = BeginPaint(hwnd, &ps);
        DrawPanel(hdc);
        RefreshPanel(hdc);
        preview(hdc);
        TextOutW(hdc, 350+100, 370-330, TEXT("Score:"), 3);
        TextOutW(hdc, 350+100, 390-330, TEXT("Grade:"), 3);
        TextOut(hdc, 350, 480, TEXT("Made by LYON"), strlen("Made by LYON"));
        len = wsprintf(str, TEXT("%d"),  score);  //. . . To find this    For an hour... How to convert integers into strings
        TextOutW(hdc, 390+100, 370-330, str, len);            //In fact, you can write a conversion function by yourself, but... How can we use only knowledge?
        len = wsprintf(str, TEXT("%d"), level);
        TextOutW(hdc, 390+100, 390-330, str, len);

        EndPaint(hwnd, &ps);
        return 0;
    case WM_TIMER:                        //The message from the clock should be dropped by this time.
        if (!ispause)
        {
            hdc = GetDC(hwnd);
            drop(hdc, hwnd);
            ReleaseDC(hwnd, hdc);
        }
        return 0;
    case WM_KEYDOWN:                //Press the button
        hdc = GetDC(hwnd);                //Getting device context
        switch (wParam)
        {
        case VK_SPACE:
            if (ispause)
            {
                ispause = !ispause;
                timer = SetTimer(hwnd, 1, speed - min(7, level) * 50, NULL);
            }
            else
            {
                ispause = !ispause;
                KillTimer(hwnd, timer);            //Destroy Clocks
            }
            break;
        case VK_UP:
            if (ispause) break;
            transform();
            RefreshPanel(hdc);
            break;
        case VK_LEFT:
            if (ispause) break;
            if (block_left == 0) break;    //This sentence can also be deleted, but if it is written in move If judged in it, the interface will still be redrawn by long press LEFT It will cause the square to flash.
            move_left();
            RefreshPanel(hdc);
            break;
        case VK_RIGHT:
            if (ispause) break;
            if (block_left + block_width == 15) break;   //Ditto
            move_right();
            RefreshPanel(hdc);
            break;
        case VK_DOWN:
            if (!ispause)
            {
                hdc = GetDC(hwnd);
                drop(hdc, hwnd);
                ReleaseDC(hwnd, hdc);
            }
            break;
        default:
            break;
        }
        ReleaseDC(hwnd, hdc);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

bool isbottom(HWND hwnd)                //Check if it reaches the bottom
{
    if (block == NULL) return 0;
    bool flag = 0;
    if (id == 7)            //Ghost Block Needs Special Judgment
    {
        flag = 1;
        for (int i = 1; block_top + i < 25; i++) //Judge if there is still room under this column 
        {
            if (!panel[block_top + i][block_left])
            {
                flag = 0; break;
            }
        }
    }
    else
    {
        for (int i = block_height - 1; i >= 0 && !flag; i--)
        {
            for (int j = 0; j < block_width && !flag; j++)
            {
                if (*(block + i*block_width + j))                               //Judge that there are no more squares under each one
                {
                    if (block_top + i + 1 < 0)continue;          //Not yet on the map
                    if (panel[block_top + i + 1][block_left + j] || block_top + i + 1 == 25)
                    {
                        flag = 1; break;

                    }
                }
            }
        }
    }
    if (flag)            //If it reaches the bottom 
    {
        if (id == 8 && active)            //Bomb boxes are handled differently when they reach the bottom
        {
            for (int i = 0; i < 8; i++)
            {
                if (block_top + direction[i][0] < 0 || block_top + direction[i][0] == 25 || block_left + direction[i][1] < 0 || block_left + direction[i][1] >= 15)
                    continue;
                panel[block_top + direction[i][0]][block_left + direction[i][1]] = FALSE;
            }
            return flag;
        }
        if (block_top < 0)//At the end of the game, the box can't get into the map. It's full below. Gameover
        {
            if (timer)
            {
                KillTimer(hwnd,timer);
            }
            if (block) delete[] block;
            MessageBox(hwnd, TEXT("Game over"), TEXT("MSG"), MB_OK | MB_ICONEXCLAMATION);
            SendMessage(hwnd, WM_CLOSE, 0, 0);
        }
        else                        //Integrate boxes into maps
        {
            for (int i = 0; i < block_height; i++)
            {
                for (int j = 0; j < block_width; j++)
                {
                    if (*(block + i*block_width + j))
                    {
                        panel[block_top + i][block_left + j] = TRUE;
                    }
                }
            }
        }
    }
    return flag;
}
void clear(HDC hdc)                                //Something the matter
{
    bool flag; int number=0;
    for (int i = 0; i < block_height; i++)
    {
        flag = 1;
        for (int j = 0; j < 15; j++)
        {
            if (!panel[block_top + i][j])
            {
                flag = 0; break;
            }
        }
        if (flag)
        {
            number++;
            MessageBeep(1);//There will be sound when walking down.
            for (int k = block_top+i; k > 0; k--)
            {
                for (int j = 0; j < 15; j++)
                {
                    panel[k][j] = panel[k - 1][j];
                }
            }
            for (int j = 0; j < 15; j++)
                panel[0][j] = FALSE;
        }
    }

    switch (number)
    {
    case 1:score += 5;  break;
    case 2:score += 13; break;
    case 3:score += 20; break;
    case 4:score += 28; break;
    default: break;
    }
    level = score / 50;
    len = wsprintf(str, TEXT("%d"), score);  
    TextOutW(hdc, 390+100, 370-330, str, len);
    len = wsprintf(str, TEXT("%d"), level);
    TextOutW(hdc, 390+100, 390-330, str, len);
} 
bool drop(HDC hdc,HWND hwnd)                    //whereabouts
{
    if (!isbottom(hwnd))        //It hasn't reached the bottom yet.
        block_top++;
    else                    //It has reached the bottom.
    {
        clear(hdc);//Elimination
        creat();//Create a new combination
        preview(hdc);
        RefreshPanel(hdc);
    }
    RefreshPanel(hdc);
    return 0;
}
void DrawPanel(HDC hdc)          //Draw game panels
{
    int x, y;
    RECT rect;//Rectangular class

    for (y = 0; y<ROWS; y++)
    {
        for (x = 0; x<COLS; x++)
        {
            //Calculate the border range of a box
            rect.top = y*CELL + 1;
            rect.bottom = (y + 1) *CELL - 1;
            rect.left = x*CELL + 1;
            rect.right = (x + 1) *CELL - 1;
            FrameRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));//Drawing Rectangular Borders
        }
    }
    rect.top = pre_peak.Y*CELL-1;
    rect.bottom = (pre_peak.Y + 2)*CELL+1;
    rect.left = pre_peak.X*CELL-1;
    rect.right = (pre_peak.X + 4)*CELL+1;
    FrameRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
    TextOut(hdc, pre_peak.X*CELL, pre_peak.Y*CELL - 30, TEXT("Graphic Preview"), 4);
}
void RefreshPanel(HDC hdc)              //Refresh panel
{
    int x, y;
    RECT rect;
    HBRUSH h_bSolid = (HBRUSH)GetStockObject(GRAY_BRUSH),          //Set brush color
        h_bEmpty = (HBRUSH)GetStockObject(WHITE_BRUSH),
        h_bomb_active = CreateSolidBrush(RGB(255, 0, 0)),
        h_bomb_nactive= CreateSolidBrush(RGB(100, 0, 0)),
    h_ghost = (HBRUSH)GetStockObject(BLACK_BRUSH); 
    //First brush the screen
    for (y = 0; y<ROWS; y++)
    {
        for (x = 0; x<COLS; x++)
        {
            //To avoid brushing off the border of the square, rect Scope must be 1 less than border range
            rect.top = y*CELL + 2;
            rect.bottom = (y + 1) *CELL - 2;
            rect.left = x*CELL + 2;
            rect.right = (x + 1) *CELL - 2;
            if (panel[y][x])
                FillRect(hdc, &rect, h_bSolid);                    //Drawing the inside of a rectangle
            else
                FillRect(hdc, &rect, h_bEmpty);
        }
    }
    if (block == NULL) return;
    if (id == 7)  //The ghost box is black
    {
        rect.top = block_top*CELL + 2;
        rect.bottom = (block_top + 1)*CELL - 2;
        rect.left = block_left*CELL + 2;
        rect.right = (block_left + 1)*CELL - 2;
        FillRect(hdc, &rect, h_ghost);
    }
    else if (id == 8)
    {
        rect.top = block_top*CELL + 2;
        rect.bottom = (block_top + 1)*CELL - 2;
        rect.left = block_left*CELL + 2;
        rect.right = (block_left + 1)*CELL - 2;
        if(active)
        FillRect(hdc, &rect, h_bomb_active);
        else
        FillRect(hdc, &rect, h_bomb_nactive);
    }
    else
    {
        for (int i = 0; i < block_height; i++)                    //Draw a block combination
        {
            for (int j = 0; j < block_width; j++)
            {
                if (*(block + i*block_width + j))
                {
                    rect.top = (block_top + i)*CELL + 2;
                    rect.bottom = (block_top + i + 1)*CELL - 2;
                    rect.left = (block_left + j)*CELL;
                    rect.right = (block_left + j + 1)*CELL - 2;
                    FillRect(hdc, &rect, h_bSolid);
                }
            }
        }
    }
}
void creat()
{
    srand(int(time(0)));
    id = next_id;
    next_id = rand() % 9;
    if (block != NULL)
    {
        delete[] block;
    }
    switch (id)
    {
    case 0:                                    //Straight line type
        block_height = 1;
        block_width = 4;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width / 2;//Locate on top of the middle
        block = new bool[block_height*block_width];                //Allocate enough space to store combinations
        *(block) = TRUE;   *(block + 1) = TRUE;   *(block + 2) = TRUE;  *(block + 3) = TRUE;
        break;
    case 1:                                    //Square
        block_height = 2;
        block_width = 2;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width /2;
        block = new bool[block_height*block_width];        
        *(block) = TRUE;      *(block + 1) = TRUE;   
        *(block + 2) = TRUE;  *(block + 3) = TRUE;
        break;
    case 2:                                    //inverted T type
        block_height = 2;
        block_width = 3;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width /2;
        block = new bool[block_height*block_width];
        *(block) = FALSE;       *(block + 1) = TRUE;    *(block + 2) = FALSE;
        *(block + 3) = TRUE;    *(block + 4) = TRUE;    *(block + 5) = TRUE;
        break;
    case 3:                                    //Left L type
        block_height = 2;
        block_width = 3;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width / 2;
        block = new bool[block_height*block_width];
        *(block) = TRUE;        *(block + 1) = FALSE;   *(block + 2) = FALSE;
        *(block + 3) = TRUE;    *(block + 4) = TRUE;    *(block + 5) = TRUE;
        break;
    case 4:                                //right L type
        block_height = 2;
        block_width = 3;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width / 2;
        block = new bool[block_height*block_width];
        *(block) = FALSE;        *(block + 1) = FALSE;    *(block + 2) = TRUE;
        *(block + 3) = TRUE;    *(block + 4) = TRUE;    *(block + 5) = TRUE;
        break;
    case 5:                            //just Z type
        block_height = 2;
        block_width = 3;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width / 2;
        block = new bool[block_height*block_width];
        *(block) = TRUE;        *(block + 1) = TRUE;    *(block + 2) = FALSE;
        *(block + 3) = FALSE;    *(block + 4) = TRUE;    *(block + 5) = TRUE;
        break;
    case 6:                        //inverted Z type
        block_height = 2;
        block_width = 3;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width / 2;
        block = new bool[block_height*block_width];
        *(block) = FALSE;        *(block + 1) = TRUE;    *(block + 2) = TRUE;
        *(block + 3) = TRUE;    *(block + 4) = TRUE;    *(block + 5) = FALSE;
        break;
    case 7:                        //Ghost block
        block_height = 1;
        block_width = 1;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width / 2;
        block = new bool[block_height*block_width];
        *(block) = TRUE;
    case 8:                                //Bomb box
        block_height = 1;
        block_width = 1;
        block_top = -block_height;
        block_left = (COLS - block_width) / 2 + block_width / 2;
        block = new bool[block_height*block_width];
        *(block) = TRUE;
        active = TRUE;
        break;
    }
}
void move_left()                                    //There are no squares on the left side of the judgement box. If there are no squares, you can go there.
{
    if (id == 7)
    {
        if (block_left == 0) return;
    }
    else
    {
        for (int i = 0; i < block_height; i++)
        {
            for (int j = 0; j < block_width; j++)
            {
                if (*(block + block_width*i + j))
                {
                    if (panel[block_top + i][block_left + j - 1] || block_left == 0)
                        return;
                }
            }
        }
    }
    block_left--;                                        //Moving vertex coordinates without
}
void move_right()                                    //Determine if there are any squares on the right side of the square  
{
    if (id == 7)
    {
        if (block_left ==14)
            return;
    }
    else
    {
        for (int i = 0; i < block_height; i++)
        {
            for (int j = block_width - 1; j >= 0; j--)
            {
                if (*(block + i*block_width + j))
                {
                    if (panel[block_top + i][block_left + j + 1] || block_left + block_width == 15)
                        return;
                }
            }
        }
    }
    block_left++;
}
void transform()//deformation
{
    if (id == 7 || id == 1) return;//There is no difference between ghost square and square square after conversion.
    if (id == 8)                //Bomb Block Direct Conversion Activation
    {
        active = !active; return;
    }
    bool* zz = new bool[block_height*block_width];      //First, create a cache to represent the location of the converted square.
    for (int i = 0; i < block_width; i++)
    {
        for (int j = 0; j < block_height; j++)
        {
            //zz[i][j]=block[block_height-j-1][i]   Conversion formula
            *(zz + i*block_height + j) = *(block + (block_height-1-j)*block_width + i);  //Transformation
        }
    }
    //Beginning without repositioning vertex sensory conversion is particularly rigid, not central rotation, so here's a change to the left of the vertex
    //Well, I feel much better after a change.
    int zz_top = block_top + (block_height - block_width) / 2;
    int zz_left = block_left + (block_width - block_height) / 2;
    if (zz_top + block_width >= 25 || zz_left + block_height > 15||zz_left<0) return;   //Judging whether a box is out of bounds
    for (int i = 0; i < block_width; i++)                                            //Determine whether the location already has a box
    {
        for (int j = 0; j < block_height; j++)
        {
            if (panel[zz_top + j][zz_left + j])
                return;
        }
    }

    for (int i = 0; i < block_width; i++)                                      //The preceding instructions are all up to standard and can be converted.
    {
        for (int j = 0; j < block_height; j++)
            *(block + i*block_height + j) = *(zz + i*block_height + j);
    }
    delete[] zz;                                                                //Delete Cache
    int a;
    block_top = zz_top;
    block_left = zz_left;
    a = block_width; block_width = block_height; block_height = a;
}
void preview(HDC hdc)        //Graphic Preview
{
    memset(pre_panel, 0, sizeof(pre_panel));
    RECT rect;
    HBRUSH h_brush = (HBRUSH)GetStockObject(GRAY_BRUSH);
    switch (next_id)
    {
    case 0:
        pre_panel[0][0] = TRUE; pre_panel[0][1] = TRUE; pre_panel[0][2] = TRUE; pre_panel[0][3] = TRUE;
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("straight line          "), 7);
        break;
    case 1:
        pre_panel[0][1] = TRUE; pre_panel[0][2] = TRUE; pre_panel[1][1] = TRUE; pre_panel[1][2] = TRUE;
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("Square          "), 7);
        break;
    case 2:
        pre_panel[0][1] = TRUE; pre_panel[1][0] = TRUE; pre_panel[1][1] = TRUE; pre_panel[1][2] = TRUE;
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("inverted T           "), 7);
        break;
    case 3:
        pre_panel[0][0] = TRUE; pre_panel[1][0] = TRUE; pre_panel[1][1] = TRUE; pre_panel[1][2] = TRUE;
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("Left L           "), 7);
        break;
    case 4:
        pre_panel[0][2] = TRUE; pre_panel[1][0] = TRUE; pre_panel[1][1] = TRUE; pre_panel[1][2] = TRUE;
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("right L           "), 7);
        break;
    case 5:
        pre_panel[0][0] = TRUE; pre_panel[0][1] = TRUE; pre_panel[1][1] = TRUE; pre_panel[1][2] = TRUE;
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("Left Lightning        "), 7);
        break;
    case 6:
        pre_panel[0][2] = TRUE; pre_panel[0][1] = TRUE; pre_panel[1][1] = TRUE; pre_panel[1][0] = TRUE;
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("Right Lightning        "), 7);
        break;
    case 7:
        pre_panel[0][1] = TRUE;
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("ghost          "), 7);
        h_brush = (HBRUSH)GetStockObject(BLACK_BRUSH);
        break;
    case 8:
        h_brush = CreateSolidBrush(RGB(255, 0, 0));
        TextOut(hdc, pre_peak.X*CELL+20, pre_peak.Y*CELL + 50, TEXT("Bomb          "), 7);
        pre_panel[0][1] = TRUE;
        break;
    }
    rect.top = pre_peak.Y*CELL;
    rect.bottom = (pre_peak.Y + 2)*CELL;
    rect.left = pre_peak.X*CELL;
    rect.right = (pre_peak.X + 4)*CELL;
    FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if (pre_panel[i][j])
            {
                rect.top = (pre_peak.Y + i)*CELL + 2;
                rect.bottom = (pre_peak.Y + i + 1)*CELL - 2;
                rect.left = (pre_peak.X + j)*CELL + 2;
                rect.right = (pre_peak.X + j + 1)*CELL - 2;
                FillRect(hdc, &rect, h_brush);
            }
        }
    }
}

 

Review Summary: There are many difficulties in the process of compiling. Many of the knowledge is not clear, but they only look for people everywhere, and they are not abstracted as class extensibility and code reuse ability is too poor (a graphics preview I also wrote an additional constructed function, which can be used in creat (), but It's the incomplete consideration that leads to the trouble of later modification.

Posted by Zaid on Thu, 04 Jul 2019 11:54:08 -0700