Библиотека graphics.h в C/C++: 15 примеров от новичка до профи

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Студенты и новички в программировании, изучающие C/C++ и графику
  • Программисты, интересующиеся графическим программированием и разработкой игр
  • Преподаватели, ищущие наглядные примеры и проекты для обучения студентов

    Библиотека graphics.h — мощный, но часто недооценённый инструмент в арсенале C/C++ программиста. Несмотря на свой возраст, она остаётся отличным способом быстро визуализировать алгоритмы, создать простые игры или графические демонстрации без погружения в сложности современных графических API. Владение этой библиотекой — навык, который не только прокачивает понимание графических принципов, но и позволяет буквально "увидеть" свой код в действии. 🚀 Рассмотрим 15 готовых примеров, которые превратят вас из новичка в уверенного пользователя graphics.h.

Изучаете программирование и хотите создавать визуальные приложения быстро и эффективно? Курс Java-разработки от Skypro погружает вас в мир современных технологий, где вы освоите не только базовые принципы программирования, но и продвинутые техники создания графических интерфейсов. В отличие от устаревшей библиотеки graphics.h, Java предлагает кроссплатформенные решения с богатым функционалом и поддержкой актуальных стандартов. Инвестируйте в навыки будущего!

Основы работы с библиотекой graphics.h в C/C++

Библиотека graphics.h — это классическое решение для работы с графикой в C/C++, разработанное Borland. Хотя она не является частью стандартной библиотеки, её широко используют в образовательных целях для обучения основам компьютерной графики. 📊

Для использования библиотеки необходимо включить следующие заголовочные файлы:

  • graphics.h — основной файл, содержащий объявления графических функций
  • conio.h — для консольного ввода-вывода
  • dos.h — для доступа к функциям DOS (при работе в устаревших средах)

Первый пример демонстрирует базовую инициализацию графического режима:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

outtextxy(100, 100, "Привет, Graphics.h!");

getch();
closegraph();
return 0;
}

Этот код инициализирует графический режим с автоопределением драйвера, выводит текст и ожидает нажатия клавиши перед закрытием.

Пример №2 демонстрирует работу с цветами:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

// Установка цвета фона
setbkcolor(BLUE);
cleardevice(); // Применение цвета фона

// Установка цвета рисования
setcolor(YELLOW);
outtextxy(100, 100, "Жёлтый текст на синем фоне");

getch();
closegraph();
return 0;
}

Основные функции инициализации и настройки среды graphics.h:

Функция Назначение Пример использования
initgraph() Инициализирует графический режим initgraph(&gd, &gm, "путькдрайверам");
closegraph() Закрывает графический режим closegraph();
setcolor() Устанавливает цвет рисования setcolor(RED);
setbkcolor() Устанавливает цвет фона setbkcolor(BLACK);
cleardevice() Очищает экран cleardevice();

Пример №3 показывает, как получить информацию о графическом режиме:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <stdio.h>

int main() {
int gd = DETECT, gm;
char driver[10], mode[10];
initgraph(&gd, &gm, "C:\\TC\\BGI");

// Получаем информацию о текущем драйвере и режиме
getdrivername(driver);
getmodename(gm, mode);

// Выводим информацию на экран
settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
outtextxy(10, 10, driver);
outtextxy(10, 30, mode);

sprintf(driver, "Разрешение: %dx%d", getmaxx()+1, getmaxy()+1);
outtextxy(10, 50, driver);

getch();
closegraph();
return 0;
}

Александр Петров, руководитель курса компьютерной графики

Однажды ко мне обратился студент второго курса, который никак не мог понять, почему его код с библиотекой graphics.h выглядит иначе на разных компьютерах. "На моём ноутбуке круги выглядят как эллипсы, а линии толще чем нужно," — жаловался он.

После анализа мы обнаружили, что он не учитывал аспектное соотношение пикселей. Мы модифировали его код, добавив коррекцию с использованием функций getaspectratio() и setaspectratio(). Результат поразил студента — его визуализация физической модели маятника теперь выглядела идеально на любом дисплее. Этот случай стал отличным практическим уроком о важности понимания особенностей графических систем.

Пошаговый план для смены профессии

Простые геометрические фигуры и анимации в graphics.h

Библиотека graphics.h предоставляет широкий набор функций для рисования базовых геометрических фигур. Освоив их, вы сможете создавать как статичные изображения, так и простые анимации. 🔶

Пример №4 демонстрирует рисование основных фигур:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

// Рисование линии
setcolor(RED);
line(50, 50, 200, 50);

// Рисование прямоугольника
setcolor(GREEN);
rectangle(50, 70, 200, 120);

// Рисование окружности
setcolor(BLUE);
circle(125, 170, 50);

// Рисование эллипса
setcolor(YELLOW);
ellipse(125, 270, 0, 360, 75, 25);

// Рисование дуги
setcolor(MAGENTA);
arc(125, 350, 45, 315, 50);

getch();
closegraph();
return 0;
}

Пример №5 показывает заполненные фигуры:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

// Закрашенный прямоугольник
setfillstyle(SOLID_FILL, RED);
bar(50, 50, 150, 100);

// Прямоугольник с узором
setfillstyle(HATCH_FILL, GREEN);
bar3d(200, 50, 300, 100, 20, 1);

// Закрашенный круг
setfillstyle(SOLID_FILL, BLUE);
fillellipse(100, 200, 50, 50);

// Закрашенный сектор
setfillstyle(SOLID_FILL, YELLOW);
pieslice(250, 200, 30, 300, 50);

getch();
closegraph();
return 0;
}

Различные стили заливки и линий доступные в graphics.h:

Тип стиля Константы Описание
Стили заливки
EMPTY_FILL Без заливки
SOLID_FILL Сплошная заливка
HATCH_FILL Штриховая заливка
PATTERN_FILL Пользовательский узор
Стили линий
SOLID_LINE Сплошная линия
DOTTED_LINE Точечная линия
DASHED_LINE Пунктирная линия

Пример №6 демонстрирует создание простой анимации — движущегося круга:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <dos.h>

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

int x = 50;
int y = getmaxy() / 2;
int radius = 30;
int max_x = getmaxx() – radius;

// Анимация движения круга
while(!kbhit()) {
// Очистка предыдущего кадра
cleardevice();

// Рисуем круг в новой позиции
setcolor(YELLOW);
setfillstyle(SOLID_FILL, RED);
fillellipse(x, y, radius, radius);

// Обновляем позицию
x += 5;
if(x > max_x) x = radius;

// Задержка для видимости анимации
delay(50);
}

getch();
closegraph();
return 0;
}

Пример №7 показывает создание "отскакивающего" мяча с физикой:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <dos.h>

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

int x = 100;
int y = 100;
int radius = 20;
int dx = 5;
int dy = 3;
int max_x = getmaxx() – radius;
int max_y = getmaxy() – radius;

while(!kbhit()) {
// Стираем предыдущий кадр
cleardevice();

// Рисуем мяч
setcolor(WHITE);
setfillstyle(SOLID_FILL, RED);
fillellipse(x, y, radius, radius);

// Обновляем позицию
x += dx;
y += dy;

// Проверяем столкновения со стенками
if(x <= radius || x >= max_x) dx = -dx;
if(y <= radius || y >= max_y) dy = -dy;

delay(30);
}

getch();
closegraph();
return 0;
}

Создание интерактивных элементов с помощью graphics.h

Библиотека graphics.h позволяет не только рисовать, но и создавать интерактивные элементы, реагирующие на ввод пользователя. Эти возможности превращают статичные изображения в интерактивные приложения. 🖱️

Пример №8 демонстрирует использование мыши в программе с graphics.h:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <dos.h>

void initialize_mouse();
void show_mouse();
void get_mouse_position(int *button, int *x, int *y);

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

initialize_mouse();
show_mouse();

int button, x, y;
char pos[40];

outtextxy(10, 10, "Кликните для рисования точки. ESC для выхода.");

while(1) {
if(kbhit() && getch() == 27) break; // ESC

get_mouse_position(&button, &x, &y);

sprintf(pos, "X: %d, Y: %d ", x, y);
outtextxy(10, getmaxy() – 20, pos);

if(button == 1) { // Левая кнопка мыши
putpixel(x, y, RED);
}

delay(50);
}

closegraph();
return 0;
}

// Функции работы с мышью через прерывания DOS
void initialize_mouse() {
union REGS regs;
regs.x.ax = 0;
int86(0x33, &regs, &regs);
}

void show_mouse() {
union REGS regs;
regs.x.ax = 1;
int86(0x33, &regs, &regs);
}

void get_mouse_position(int *button, int *x, int *y) {
union REGS regs;
regs.x.ax = 3;
int86(0x33, &regs, &regs);
*button = regs.x.bx;
*x = regs.x.cx;
*y = regs.x.dx;
}

Пример №9 показывает создание простой кнопки:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <dos.h>

// Структура для представления кнопки
struct Button {
int x1, y1, x2, y2;
char *label;
int color, hover_color;
int is_hover;
};

// Функция проверки наведения на кнопку
int is_mouse_over(struct Button *btn, int mx, int my) {
return (mx >= btn->x1 && mx <= btn->x2 && my >= btn->y1 && my <= btn->y2);
}

// Функция отрисовки кнопки
void draw_button(struct Button *btn) {
// Основной прямоугольник
setfillstyle(SOLID_FILL, btn->is_hover ? btn->hover_color : btn->color);
bar(btn->x1, btn->y1, btn->x2, btn->y2);

// Граница
setcolor(WHITE);
rectangle(btn->x1, btn->y1, btn->x2, btn->y2);

// Текст кнопки
int text_width = textwidth(btn->label);
int text_height = textheight(btn->label);
int text_x = btn->x1 + (btn->x2 – btn->x1 – text_width) / 2;
int text_y = btn->y1 + (btn->y2 – btn->y1 – text_height) / 2;

setcolor(WHITE);
outtextxy(text_x, text_y, btn->label);
}

// Функции для работы с мышью
void initialize_mouse();
void show_mouse();
void get_mouse_position(int *button, int *x, int *y);

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

initialize_mouse();
show_mouse();

// Создаем кнопку
struct Button btn;
btn.x1 = 150;
btn.y1 = 150;
btn.x2 = 350;
btn.y2 = 200;
btn.label = "Нажми меня!";
btn.color = BLUE;
btn.hover_color = RED;
btn.is_hover = 0;

int button, mx, my;
char message[40] = "";

while(1) {
if(kbhit() && getch() == 27) break; // ESC

get_mouse_position(&button, &mx, &my);

// Проверка наведения
int hover = is_mouse_over(&btn, mx, my);
if(hover != btn.is_hover) {
btn.is_hover = hover;
draw_button(&btn);
}

// Проверка клика
if(button == 1 && hover) {
strcpy(message, "Кнопка была нажата!");
cleardevice();
draw_button(&btn);
}

// Вывод сообщения
setcolor(WHITE);
outtextxy(150, 220, message);

delay(50);
}

closegraph();
return 0;
}

// Реализации функций для работы с мышью
void initialize_mouse() {
union REGS regs;
regs.x.ax = 0;
int86(0x33, &regs, &regs);
}

void show_mouse() {
union REGS regs;
regs.x.ax = 1;
int86(0x33, &regs, &regs);
}

void get_mouse_position(int *button, int *x, int *y) {
union REGS regs;
regs.x.ax = 3;
int86(0x33, &regs, &regs);
*button = regs.x.bx;
*x = regs.x.cx;
*y = regs.x.dx;
}

Пример №10 демонстрирует создание простого рисовального приложения:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>

// Функции для работы с мышью
void initialize_mouse();
void show_mouse();
void hide_mouse();
void get_mouse_position(int *button, int *x, int *y);

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

initialize_mouse();
show_mouse();

int current_color = WHITE;
int brush_size = 2;
int prev_x = -1, prev_y = -1;
int button, x, y;
char message[80];

// Отображаем инструкции
sprintf(message, "ЛКМ: рисовать | ПКМ: стереть | +/-: размер кисти | 1-9: цвета | ESC: выход");
outtextxy(10, 10, message);

while(1) {
if(kbhit()) {
char key = getch();
if(key == 27) break; // ESC

// Изменение размера кисти
if(key == '+' && brush_size < 10) brush_size++;
if(key == '-' && brush_size > 1) brush_size--;

// Выбор цвета (1-9 соответствуют разным цветам)
if(key >= '1' && key <= '9') {
current_color = key – '1' + 1; // Маппинг 1-9 на цвета 1-9
}

// Обновление информации
setcolor(WHITE);
setfillstyle(SOLID_FILL, BLACK);
bar(10, getmaxy() – 30, getmaxx() – 10, getmaxy() – 10);
sprintf(message, "Цвет: %d | Размер кисти: %d", current_color, brush_size);
outtextxy(10, getmaxy() – 20, message);
}

get_mouse_position(&button, &x, &y);

// Проверка, находится ли курсор в области рисования
if(y > 30 && y < getmaxy() – 30) {
if(button == 1) { // Левая кнопка – рисование
hide_mouse(); // Скрываем курсор перед рисованием

setcolor(current_color);
if(prev_x != -1 && prev_y != -1) {
// Рисуем линию к новой позиции для плавности
setlinestyle(SOLID_LINE, 0, brush_size);
line(prev_x, prev_y, x, y);
} else {
// Рисуем точку при первом клике
for(int i = 0; i < brush_size; i++) {
circle(x, y, i);
}
}

show_mouse(); // Показываем курсор после рисования
prev_x = x;
prev_y = y;
} else if(button == 2) { // Правая кнопка – стирание
hide_mouse();

setcolor(BLACK);
setfillstyle(SOLID_FILL, BLACK);
fillellipse(x, y, brush_size*2, brush_size*2);

show_mouse();
prev_x = x;
prev_y = y;
} else {
// Сбрасываем предыдущую позицию, если кнопка не нажата
prev_x = prev_y = -1;
}
}

delay(10);
}

closegraph();
return 0;
}

// Реализации функций для работы с мышью
void initialize_mouse() {
union REGS regs;
regs.x.ax = 0;
int86(0x33, &regs, &regs);
}

void show_mouse() {
union REGS regs;
regs.x.ax = 1;
int86(0x33, &regs, &regs);
}

void hide_mouse() {
union REGS regs;
regs.x.ax = 2;
int86(0x33, &regs, &regs);
}

void get_mouse_position(int *button, int *x, int *y) {
union REGS regs;
regs.x.ax = 3;
int86(0x33, &regs, &regs);
*button = regs.x.bx;
*x = regs.x.cx;
*y = regs.x.dx;
}

Ирина Соколова, старший преподаватель программирования

Запомнила случай с группой третьего курса, когда мы изучали взаимодействие с пользователем через graphics.h. Студент Михаил пытался создать простую игру-лабиринт, но столкнулся с проблемой: при нажатии клавиш персонаж двигался рывками, а не плавно, что портило впечатление от игры.

После консультации мы перестроили логику работы с клавиатурой. Вместо проверки нажатий в основном цикле с помощью getch() мы использовали неблокирующее чтение с помощью kbhit() и отслеживали состояние клавиш. Это позволило реализовать более плавную анимацию, а заодно добавить одновременное отслеживание нескольких клавиш. Михаил был поражён, насколько лучше стала работать его игра. "Это же совсем другой уровень!" — сказал он после тестирования. Этот подход стал стандартным в нашем курсе для всех проектов, требующих взаимодействия с пользователем.

Практические проекты: от простых игр до визуализаций

Библиотека graphics.h открывает возможности для создания разнообразных проектов: от классических игр до визуализации алгоритмов. Рассмотрим примеры, демонстрирующие практическое применение знаний о графике в C/C++. 🎮

Пример №11 — простая игра "Змейка":

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <time.h>

#define MAX_LENGTH 100

// Структуры для представления координат
struct Point {
int x, y;
};

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

randomize(); // Инициализация генератора случайных чисел

// Настройки игры
int cell_size = 10;
int width = getmaxx() / cell_size;
int height = getmaxy() / cell_size;
int score = 0;
int game_over = 0;

// Инициализация змейки
struct Point snake[MAX_LENGTH];
int length = 3;
int direction = 0; // 0-вправо, 1-вниз, 2-влево, 3-вверх

// Начальное положение змейки
for(int i = 0; i < length; i++) {
snake[i].x = width / 2 – i;
snake[i].y = height / 2;
}

// Случайное положение еды
struct Point food;
food.x = rand() % width;
food.y = rand() % height;

char score_text[20];

// Игровой цикл
while(!game_over) {
// Очистка экрана
cleardevice();

// Отображение счета
sprintf(score_text, "Score: %d", score);
setcolor(WHITE);
outtextxy(10, 10, score_text);

// Проверка нажатий клавиш
if(kbhit()) {
char key = getch();
switch(key) {
case 'w': if(direction != 1) direction = 3; break;
case 's': if(direction != 3) direction = 1; break;
case 'a': if(direction != 0) direction = 2; break;
case 'd': if(direction != 2) direction = 0; break;
case 27: game_over = 1; break; // ESC для выхода
}
}

// Перемещение змейки (сначала хвост)
for(int i = length – 1; i > 0; i--) {
snake[i] = snake[i-1];
}

// Перемещение головы
switch(direction) {
case 0: snake[0].x++; break;
case 1: snake[0].y++; break;
case 2: snake[0].x--; break;
case 3: snake[0].y--; break;
}

// Проверка столкновения со стеной
if(snake[0].x < 0 || snake[0].x >= width ||
snake[0].y < 0 || snake[0].y >= height) {
game_over = 1;
}

// Проверка столкновения с собой
for(int i = 1; i < length; i++) {
if(snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
game_over = 1;
}
}

// Проверка съедания еды
if(snake[0].x == food.x && snake[0].y == food.y) {
length++;
score += 10;

// Новая позиция еды
food.x = rand() % width;
food.y = rand() % height;
}

// Отрисовка змейки
setcolor(GREEN);
setfillstyle(SOLID_FILL, GREEN);
for(int i = 0; i < length; i++) {
int x = snake[i].x * cell_size;
int y = snake[i].y * cell_size;
fillellipse(x + cell_size/2, y + cell_size/2, cell_size/2, cell_size/2);
}

// Отрисовка еды
setcolor(RED);
setfillstyle(SOLID_FILL, RED);
fillellipse(food.x * cell_size + cell_size/2, 
food.y * cell_size + cell_size/2, 
cell_size/2, cell_size/2);

delay(100); // Скорость игры
}

// Экран окончания игры
cleardevice();
setcolor(WHITE);
settextstyle(DEFAULT_FONT, HORIZ_DIR, 2);
outtextxy(getmaxx()/2 – 100, getmaxy()/2 – 20, "GAME OVER");
sprintf(score_text, "Final Score: %d", score);
outtextxy(getmaxx()/2 – 100, getmaxy()/2 + 20, score_text);

getch();
closegraph();
return 0;
}

Пример №12 — визуализация сортировки пузырьком:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>
#include <dos.h>
#include <time.h>

#define ARR_SIZE 50

void drawArray(int arr[], int size, int highlight1, int highlight2) {
cleardevice();

int bar_width = getmaxx() / size;
int max_height = getmaxy() – 50;

// Находим максимальное значение для масштабирования
int max_val = arr[0];
for(int i = 1; i < size; i++) {
if(arr[i] > max_val) max_val = arr[i];
}

// Рисуем каждый элемент массива как столбец
for(int i = 0; i < size; i++) {
int height = (arr[i] * max_height) / max_val;
int x1 = i * bar_width;
int y1 = getmaxy() – height;
int x2 = x1 + bar_width – 1;
int y2 = getmaxy();

// Выделяем текущие сравниваемые элементы
if(i == highlight1 || i == highlight2) {
setfillstyle(SOLID_FILL, RED);
} else {
setfillstyle(SOLID_FILL, WHITE);
}

bar(x1, y1, x2, y2);
}

delay(50); // Замедление для наблюдения
}

void bubbleSort(int arr[], int size) {
for(int i = 0; i < size – 1; i++) {
for(int j = 0; j < size – i – 1; j++) {
// Визуализируем текущее сравнение
drawArray(arr, size, j, j+1);

if(arr[j] > arr[j+1]) {
// Обмен элементов и визуализация
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;

drawArray(arr, size, j, j+1);
}
}
}

// Финальное отображение отсортированного массива
drawArray(arr, size, -1, -1);
}

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

randomize();

// Инициализация массива случайными значениями
int arr[ARR_SIZE];
for(int i = 0; i < ARR_SIZE; i++) {
arr[i] = rand() % 100 + 1; // Значения от 1 до 100
}

// Отображение начального состояния
drawArray(arr, ARR_SIZE, -1, -1);
getch(); // Ожидание нажатия клавиши для начала сортировки

// Сортировка и визуализация
bubbleSort(arr, ARR_SIZE);

getch();
closegraph();
return 0;
}

Пример №13 — визуализация фрактала (дерево):

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <math.h>

#define PI 3.14159265

// Рекурсивная функция для рисования фрактального дерева
void drawTree(int x, int y, double angle, int depth) {
if(depth == 0) return;

int length = depth * 10;

// Вычисляем конечную точку ветви
int x2 = x + (int)(cos(angle * PI / 180) * length);
int y2 = y – (int)(sin(angle * PI / 180) * length);

// Цвет зависит от глубины
if(depth < 3) {
setcolor(GREEN);
} else {
setcolor(BROWN);
}

// Рисуем линию (ветвь)
line(x, y, x2, y2);

// Рекурсивно рисуем левую и правую ветви
drawTree(x2, y2, angle – 20, depth – 1);
drawTree(x2, y2, angle + 20, depth – 1);
}

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

// Рисуем фрактальное дерево
drawTree(getmaxx() / 2, getmaxy() – 10, 90, 9);

getch();
closegraph();
return 0;
}

Сравнение различных типов практических проектов на основе graphics.h:

Тип проекта Сложность Основные компоненты Учебная ценность
Игры (Snake, Pong, Tetris) Средняя Анимация, обработка ввода, коллизии Алгоритмы, управление состоянием, интерактивность
Визуализация алгоритмов Средняя Отрисовка данных, пошаговая визуализация Понимание алгоритмов, представление данных
Фракталы и математические визуализации Высокая Рекурсия, математические формулы Рекурсивное мышление, математическое моделирование
Редакторы и инструменты Высокая UI элементы, обработка событий Разработка интерфейсов, управление пользовательским опытом

Пример №14 — простой редактор фигур:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>

// Функции для работы с мышью
void initialize_mouse();
void show_mouse();
void hide_mouse();
void get_mouse_position(int *button, int *x, int *y);

// Типы фигур
#define SHAPE_LINE 0
#define SHAPE_RECT 1
#define SHAPE_CIRCLE 2

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

initialize_mouse();
show_mouse();

int current_color = WHITE;
int current_shape = SHAPE_LINE;
int start_x = -1, start_y = -1;
int button, x, y;
int drawing = 0;
char message[80];

// Отображаем инструкции
sprintf(message, "L: линия | R: прямоугольник | C: круг | 1-9: цвет | ESC: выход");
outtextxy(10, 10, message);

while(1) {
if(kbhit()) {
char key = getch();
if(key == 27) break; // ESC

// Выбор фигуры
if(key == 'l' || key == 'L') current_shape = SHAPE_LINE;
if(key == 'r' || key == 'R') current_shape = SHAPE_RECT;
if(key == 'c' || key == 'C') current_shape = SHAPE_CIRCLE;

// Выбор цвета (1-9 соответствуют разным цветам)
if(key >= '1' && key <= '9') {
current_color = key – '1' + 1;
}

// Обновление информации
setfillstyle(SOLID_FILL, BLACK);
bar(10, getmaxy() – 30, getmaxx() – 10, getmaxy() – 10);

setcolor(WHITE);
sprintf(message, "Форма: %s | Цвет: %d", 
current_shape == SHAPE_LINE ? "Линия" : 
current_shape == SHAPE_RECT ? "Прямоугольник" : "Круг", 
current_color);
outtextxy(10, getmaxy() – 20, message);
}

get_mouse_position(&button, &x, &y);

// Если нажата левая кнопка мыши
if(button == 1) {
if(!drawing) {
// Начало рисования
drawing = 1;
start_x = x;
start_y = y;
} else {
// Предварительный просмотр фигуры
hide_mouse();

// Очистка предыдущего превью
setcolor(BLACK);
setwritemode(XOR_PUT);

switch(current_shape) {
case SHAPE_LINE:
line(start_x, start_y, x, y);
break;
case SHAPE_RECT:
rectangle(start_x, start_y, x, y);
break;
case SHAPE_CIRCLE:
int radius = sqrt((x-start_x)*(x-start_x) + (y-start_y)*(y-start_y));
circle(start_x, start_y, radius);
break;
}

setwritemode(COPY_PUT);
show_mouse();
}
} else if(drawing) {
// Завершение рисования
drawing = 0;

// Рисуем окончательную фигуру
hide_mouse();

setcolor(current_color);
setlinestyle(SOLID_LINE, 0, 1);

switch(current_shape) {
case SHAPE_LINE:
line(start_x, start_y, x, y);
break;
case SHAPE_RECT:
rectangle(start_x, start_y, x, y);
break;
case SHAPE_CIRCLE:
int radius = sqrt((x-start_x)*(x-start_x) + (y-start_y)*(y-start_y));
circle(start_x, start_y, radius);
break;
}

show_mouse();
}

delay(50);
}

closegraph();
return 0;
}

// Реализации функций для работы с мышью
void initialize_mouse() {
union REGS regs;
regs.x.ax = 0;
int86(0x33, &regs, &regs);
}

void show_mouse() {
union REGS regs;
regs.x.ax = 1;
int86(0x33, &regs, &regs);
}

void hide_mouse() {
union REGS regs;
regs.x.ax = 2;
int86(0x33, &regs, &regs);
}

void get_mouse_position(int *button, int *x, int *y) {
union REGS regs;
regs.x.ax = 3;
int86(0x33, &regs, &regs);
*button = regs.x.bx;
*x = regs.x.cx;
*y = regs.x.dx;
}

Советы по отладке и оптимизации кода с graphics.h

Работа с графикой часто требует не только творческого подхода, но и умения оптимизировать код для достижения плавных анимаций и эффективной работы программы. Рассмотрим некоторые техники отладки и оптимизации при использовании библиотеки graphics.h. 🔧

Пример №15 — оптимизированная анимация с двойной буферизацией:

cpp
Скопировать код
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>
#include <dos.h>
#include <stdio.h>
#include <time.h>

// Функция для реализации двойной буферизации
void* createBuffer() {
// Создаем буфер в памяти размером с экран
void* buffer = malloc(imagesize(0, 0, getmaxx(), getmaxy()));
return buffer;
}

// Переключаем буфер на экран
void swapBuffers(void* buffer) {
// Сохраняем текущий экран в буфер
getimage(0, 0, getmaxx(), getmaxy(), buffer);

// Переносим буфер на экран
putimage(0, 0, buffer, COPY_PUT);
}

int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TC\\BGI");

// Инициализация двойной буферизации
void* buffer = createBuffer();
if(!buffer) {
outtextxy(10, 10, "Ошибка: не удалось создать буфер");
getch();
closegraph();
return 1;
}

randomize();

// Создаем множество шариков
#define NUM_BALLS 50

struct Ball {
int x, y;
int dx, dy;
int radius;
int color;
} balls[NUM_BALLS];

// Инициализируем шарики случайными значениями
for(int i = 0; i < NUM_BALLS; i++) {
balls[i].x = rand() % getmaxx();
balls[i].y = rand() % getmaxy();
balls[i].dx = (rand() % 5) + 1;
balls[i].dy = (rand() % 5) + 1;
balls[i].radius = (rand() % 10) + 5;
balls[i].color = (rand() % 15) + 1;
}

// Измерение FPS
clock_t start_time, end_time;
int frames = 0;
double fps = 0;
char fps_text[20];

start_time = clock();

// Основной цикл анимации
while(!kbhit()) {
// Очистка буфера
cleardevice();

// Отрисовка и обновление позиций всех шариков
for(int i = 0; i < NUM_BALLS; i++) {
setcolor(balls[i].color);
setfillstyle(SOLID_FILL, balls[i].color);
fillellipse(balls[i].x, balls[i].y, balls[i].radius, balls[i].radius);

// Обновление позиции
balls[i].x += balls[i].dx;
balls[i].y += balls[i].dy;

// Обработка столкновений со стенами
if(balls[i].x – balls[i].radius <= 0 || 
balls[i].x + balls[i].radius >= getmaxx()) {
balls[i].dx = -balls[i].dx;
}

if(balls[i].y – balls[i].radius <= 0 || 
balls[i].y + balls[i].radius >= getmaxy()) {
balls[i].dy = -balls[i].dy;
}
}

// Отображение FPS
frames++;
end_time = clock();

// Обновляем FPS каждую секунду
if((double)(end_time – start_time) / CLOCKS_PER_SEC >= 1) {
fps = frames / ((double)(end_time – start_time) / CLOCKS_PER_SEC);
frames = 0;
start_time = end_time;
}

setcolor(WHITE);
sprintf(fps_text, "FPS: %.1f", fps);
outtextxy(10, 10, fps_text);

// Выводим буфер на экран
swapBuffers(buffer);

// Задержка для ограничения FPS
delay(10);
}

free(buffer);
getch();
closegraph();
return 0;
}

Ключевые рекомендации по оптимизации кода с graphics.h:

  • Используйте двойную буферизацию для устранения мерцания при анимации
  • Минимизируйте очистку экрана — перерисовывайте только изменившиеся части
  • Оптимизируйте циклы отрисовки — располагайте тяжёлые вычисления за пределами циклов
  • Кэшируйте результаты тригонометрических и других сложных вычислений
  • Используйте целочисленную арифметику вместо вычислений с плавающей точкой, где возможно
  • Применяйте стратегию "грязных прямоугольников" — отслеживайте и обновляйте только изменённые области

Распространённые ошибки при работе с graphics.h и способы их исправления:

Проблема Причина Решение
"BGI Error: Graphics not initialized" Не найдены драйвера BGI или неправильный путь Указать корректный путь к драйверам или использовать detectgraph()
Программа закрывается сразу после открытия Отсутствие ожидания ввода пользователя Добавить getch() перед closegraph()
Мерцание при анимации Перерисовка всего экрана каждый кадр Использовать двойную буферизацию или XOR_PUT для временных объектов
Низкая производительность Неэффективные алгоритмы отрисовки Оптимизировать циклы, уменьшить количество вызовов функций отрисовки
Искажение пропорций изображения Различное аспектное соотношение пикселей Использовать getaspectratio() и корректировать координаты

Для отладки графических программ рекомендуется использовать следующие подходы:

  • Выводите диагностические сообщения на экран с помощью outtextxy()
  • Добавляйте визуальные маркеры в ключевых точках алгоритма
  • Создавайте режим отладки с замедленной анимацией и отображением дополнительной информации
  • Используйте пошаговый режим, где каждый шаг алгоритма выполняется по нажатию клавиши
  • Внедряйте измерение FPS для отслеживания производительности

Помните, что современные компиляторы могут требовать дополнительной настройки для работы с библиотекой graphics.h. В некоторых случаях может потребоваться использование специальных заголовочных файлов или компиляторов, таких как Turbo C или WinBGIm для современных систем.

Продвигаясь вперёд от примитивной графики graphics.h к профессиональным графическим библиотекам, важно осознать эволюцию технологий визуализации. Эти 15 примеров демонстрируют не только базовые графические возможности C/C++, но и лежащие в их основе принципы, актуальные для любой графической библиотеки. Вы можете видеть, как от простых линий и кругов мы перешли к интерактивным приложениям, играм и визуализациям. Каждый пример — это ступенька к мастерству в мире компьютерной графики, независимо от используемых инструментов.

Читайте также

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Что такое библиотека graphics.h?
1 / 5

Загрузка...