Изобразить на экране детскую пирамидку - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Изобразить на экране детскую пирамидку из n разноцветных прямоугольников, размеры которых шаг за шагом уменьшаются на 10%.

Решение задачи: «Изобразить на экране детскую пирамидку»

textual
Листинг программы
#include <windows.h>
#include <stdlib.h>
#include <time.h>
 
#define TIMER_FOR_SEC 10000
#define CLR 256;
 
LRESULT CALLBACK WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
int GetPerimetre(int, int);
int SetEdge (int, int);
 
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nShowCmd)
{
    srand(time(0));
 
    WNDCLASSEX wClass;
    ZeroMemory(&wClass,sizeof(WNDCLASSEX));
    wClass.cbClsExtra=NULL;
    wClass.cbSize=sizeof(WNDCLASSEX);
    wClass.cbWndExtra=NULL;
    wClass.hbrBackground=(HBRUSH)COLOR_WINDOW;
    wClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    wClass.hIcon=NULL;
    wClass.hIconSm=NULL;
    wClass.hInstance=hInst;
    wClass.lpfnWndProc=(WNDPROC)WinProc;
    wClass.lpszClassName="Window Class";
    wClass.lpszMenuName=NULL;
    wClass.style=CS_HREDRAW|CS_VREDRAW;
 
    if(!RegisterClassEx(&wClass))
    {
        int nResult=GetLastError();
        MessageBox(NULL,
            "Window class creation failed\r\n",
            "Window Class Failed",
            MB_ICONERROR);
    }
 
    HWND hWnd=CreateWindowEx(NULL,
            "Window Class",
            "Windows application",
            WS_OVERLAPPEDWINDOW,
            200,
            200,
            1000,
            800,
            NULL,
            NULL,
            hInst,
            NULL);
 
    if(!hWnd)
    {
        int nResult=GetLastError();
 
        MessageBox(NULL,
            "Window creation failed\r\n",
            "Window Creation Failed",
            MB_ICONERROR);
    }
 
    ShowWindow(hWnd,nShowCmd);
 
    MSG msg;
    ZeroMemory(&msg,sizeof(MSG));
 
    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
 
    return 0;
}
 
LRESULT CALLBACK WinProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    static int n = 9;
    static int sx, sy;
    HDC hdc;
    RECT rct;
    HBRUSH rectangles [n];
 
    GetClientRect(hWnd, &rct);
 
    switch(msg)
    {
    case WM_CREATE:
        {
            SetTimer(hWnd, TIMER_FOR_SEC, 400, NULL);
            break;
        }
    case WM_PAINT:
        {
            int i = 0, bottom = rct.bottom;
 
            for (i = 0; i < n; ++i)
            {
                int R = rand() % CLR;
                int G = rand() % CLR;
                int B = rand() % CLR;
                rectangles [i] = (HBRUSH)CreateSolidBrush(RGB( R, G, B ));
            }
 
            hdc = GetDC(hWnd);
            sy = (rct.bottom - rct.top) / n;
            sx = (rct.right - rct.left) - 100;
 
            for (i = 0; i < n; ++i)
            {
                int top = bottom - sy;
                int right = rct.right - ((rct.right - rct.left - sx) / 2);
                int left = rct.left + ((rct.right - rct.left - sx) / 2);
                int p;
 
                SelectObject(hdc, rectangles [i]);
 
                Rectangle(hdc, left, top, right, bottom);
 
                bottom -= sy;
                p = GetPerimetre(sx, sy);
                sx = SetEdge(p - (p / 10) , sy);
            }
 
            for (i = 0; i < n; ++i)
            {
                DeleteObject(rectangles [i]);
            }
 
            ReleaseDC(hWnd, hdc);
            break;
        }
    case WM_TIMER:
        {
            switch(wParam)
            {
            case TIMER_FOR_SEC:
                {
                    SendMessage(hWnd, WM_PAINT, 0, 0);
                    break;
                }
                break;
            }
            break;
        }
    case WM_DESTROY:
        {
            KillTimer(hWnd, TIMER_FOR_SEC);
            PostQuitMessage(0);
        }
        break;
    }
 
    return DefWindowProc(hWnd,msg,wParam,lParam);
}
 
int GetPerimetre(int width, int height) {
    return 2 * (width + height);
}
 
int SetEdge (int perimetre, int height)
{
    return (perimetre - (height * 2)) / 2;
}

Объяснение кода листинга программы

  1. Переменная n инициализируется значением 9.
  2. Переменные sx и sy инициализируются нулевыми значениями.
  3. Создается массив rectangles из n элементов, который будет хранить HBRUSH объекты.
  4. Получается размер окна rct.
  5. В случае WM_CREATE сообщения, устанавливается таймер, который будет вызывать WM_PAINT сообщение каждую секунду.
  6. В случае WM_PAINT сообщения, происходит отрисовка пирамидки, состоящей из n прямоугольников, каждый из которых имеет свой уникальный цвет.
  7. Для каждого прямоугольника создается HBRUSH объект, который хранит его цвет.
  8. Для отрисовки каждого прямоугольника используются функции SelectObject и Rectangle, которые принимают в качестве аргументов hdc (дескриптор устройства), left, top, right и bottom (координаты прямоугольника), а также rectangles[i] (дескриптор кисти).
  9. После отрисовки всех прямоугольников, все HBRUSH объекты удаляются с помощью функции DeleteObject.
  10. В случае WM_TIMER сообщения, проверяется его параметр wParam. Если он равен TIMER_FOR_SEC, то это вызывает WM_PAINT сообщение.
  11. В случае WM_DESTROY сообщения, останавливается таймер и отправляется сообщение PostQuitMessage, которое завершает работу программы.
  12. Функция GetPerimetre принимает в качестве аргументов ширину и высоту прямоугольника и возвращает периметр этого прямоугольника, который вычисляется как двойная сумма ширины и высоты.
  13. Функция SetEdge принимает в качестве аргументов периметр прямоугольника и его высоту. Вычитает из периметра значение, равное удвоенной высоте, и возвращает полученное значение, которое будет использоваться как ширина прямоугольника.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 3.636 из 5
Похожие ответы