Визуализация быстрой сортировки с SFML и C++20

c4b78f9f5c836ad62081ad39cdebd689.png

В этой статье мы создадим интерактивную визуализацию алгоритма быстрой сортировки (QuickSort) с использованием библиотеки SFML и современных возможностей C++20. Этот проект поможет вам лучше понять, как работает один из самых популярных алгоритмов сортировки, и покажет, как можно комбинировать графику и алгоритмы для создания образовательных инструментов.

Зачем визуализировать алгоритмы?

Алгоритмы сортировки, такие как QuickSort, могут быть сложными для понимания, особенно для новичков.

Визуализация помогает:

  • Увидеть, как данные перемещаются и сравниваются на каждом шаге.

  • Понять концепции разбиения и рекурсии.

  • Сделать обучение более интерактивным и увлекательным.

Если вы хотите не только изучить алгоритмы, но и создать что-то наглядное и красивое, этот проект для вас!

Что нам понадобится?

SFML: Библиотека для работы с графикой, событиями и окнами. Скачать и установить.

Компилятор с поддержкой C++20: Например, GCC или Clang.

Базовые знания C++: Работа с векторами, лямбда-функциями и рекурсией.

Описание проекта

Цель

Создать программу, которая:

  • Генерирует случайный массив чисел.

  • Визуализирует его как набор столбцов.

  • Анимирует процесс сортировки с помощью QuickSort.

Особенности

Использование std: ranges из C++20 для удобной работы с диапазонами.

Рекурсивная реализация QuickSort с визуализацией на каждом шаге.

Простая, но эффективная анимация с задержкой для наглядности.

Код проекта

Подготовка

  1. Установите SFML и настройте ваш проект (например, через CMake или вручную подключите библиотеки).

  2. Убедитесь, что ваш компилятор поддерживает C++20 (флаг -std=c++20).

#include 
#include 
#include 
#include 
#include 
#include 

int main() {
    // Настройки окна
    sf::RenderWindow window(sf::VideoMode(1280, 720), "QuickSort Visualization");
    window.setFramerateLimit(60);

    // Генерация случайного массива чисел
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(10, 700);

    std::vector arr(150);
    for (auto& x : arr) x = dis(gen);

    // Функция быстрой сортировки с визуализацией процесса
    auto quickSort = [&](auto& range, int low, int high, auto& recur) mutable {
        if (low >= high) return; // Базовый случай рекурсии

        int pivot = range[high]; // Выбираем опорный элемент (последний в диапазоне)
        int i = low - 1;

        // Разделение элементов: меньшие идут влево, большие вправо
        for (int j = low; j < high; ++j) {
            if (range[j] <= pivot) {
                ++i;
                std::swap(range[i], range[j]);
            }
        }
        std::swap(range[i + 1], range[high]); // Устанавливаем опорный элемент на своё место
        int pi = i + 1; // Индекс опорного элемента

        // Рекурсивная сортировка левой и правой частей
        recur(range, low, pi - 1, recur);
        recur(range, pi + 1, high, recur);

        // Визуализация текущего состояния массива
        window.clear();
        float barWidth = static_cast(window.getSize().x) / arr.size();
        for (int k = 0; k < arr.size(); ++k) {
            sf::RectangleShape bar(sf::Vector2f(barWidth - 1, arr[k]));
            bar.setPosition(k * barWidth, window.getSize().y - arr[k]);
            bar.setFillColor(sf::Color::White);
            window.draw(bar);
        }
        window.display();
        std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Задержка для анимации
        };

    // Используем std::ranges для удобной работы с массивом
    auto range = std::ranges::subrange(arr.begin(), arr.end());
    bool sorting = true; // Флаг, чтобы сортировка выполнялась только один раз

    // Основной цикл программы
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) window.close(); // Закрытие окна
        }

        if (sorting) {
            quickSort(range, 0, arr.size() - 1, quickSort); // Запуск сортировки
            sorting = false; // Отключаем повторную сортировку
        }

        // Отрисовка финального состояния массива
        window.clear();
        float barWidth = static_cast(window.getSize().x) / arr.size();
        for (int i = 0; i < arr.size(); ++i) {
            sf::RectangleShape bar(sf::Vector2f(barWidth - 1, arr[i]));
            bar.setPosition(i * barWidth, window.getSize().y - arr[i]);
            bar.setFillColor(sf::Color::White);
            window.draw(bar);
        }
        window.display();
    }

    return 0;
}

Пояснения к коду

Генерация массива: Создаем вектор из 150 случайных чисел от 10 до 700 с помощью std: random_device и std: mt19937.

QuickSort: Реализован как лямбда-функция с рекурсией. На каждом шаге разбиения массива мы визуализируем текущее состояние.

Визуализация: Каждый элемент массива отображается как прямоугольник (sf: RectangleShape), высота которого пропорциональна значению элемента.

Анимация: Задержка в 50 миллисекунд (std: this_thread: sleep_for) между шагами сортировки создает эффект плавной анимации.

Как это работает?

  1. При запуске программы генерируется случайный массив, который отображается как набор столбцов в окне SFML.

  2. Алгоритм QuickSort начинает сортировку, и на каждом шаге разбиения массива окно обновляется, показывая текущее состояние.

  3. После завершения сортировки вы видите отсортированный массив.

Попробуйте запустить код и понаблюдать за процессом — это действительно увлекательно!

8c538aeb3c4575ba3011b424b370b0d6.gif

Расширяемость проекта

Хотите сделать проект еще интереснее? Вот несколько идей:

  • Добавьте другие алгоритмы сортировки (например, пузырьковую или сортировку слиянием) и сравните их визуально.

  • Включите интерактивные элементы: кнопки для запуска сортировки или изменения скорости анимации.

  • Экспериментируйте с цветами: выделяйте опорный элемент (pivot) другим цветом для наглядности.

Заключение

Визуализация алгоритмов — это мощный инструмент для обучения и отладки. С помощью SFML и C++20 вы можете создавать не только полезные, но и красивые образовательные проекты. Этот пример демонстрирует, как комбинировать графику, алгоритмы и современные возможности языка для создания интерактивных приложений.

Попробуйте улучшить этот проект: добавьте звуковые эффекты, измените стиль визуализации или реализуйте другой алгоритм. Делитесь своими идеями в комментариях — мне будет интересно узнать, что вы придумали!

Телеграмм канал — Программирование игр С++

Habrahabr.ru прочитано 18143 раза