Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 게임 제작
- 정보처리기사
- 정처기 필기
- unity3d
- 3회차
- 게임
- 1인 게임
- 유니티3d
- 토이 프로젝트
- 자바스크립트
- 정처기
- 1인 게임 제작
- Vampire Survivors
- 유니티 3D
- 필기
- FPS
- 게임제작
- 1인 개발
- Unity
- Pong
- 1인 게임 개발
- portal
- 합격
- 게임 개발
- Unity #Unity2D #Portal
- 퐁
- 프로그래머스 #최소힙 #우선순위 큐
- Unity2D
- 자바스크립트 게임
- 유니티
Archives
- Today
- Total
Coding Feature.
SFML) 정렬 알고리즘 그래픽으로 구현하기. 본문
많은 사람들이 SFML과 같은 그래픽 라이브러리를 사용하면서 하는 것이 바로 알고리즘을 그래픽으로 구현해 가시화, 시뮬레이션 하는 것이다.
대표적으로 정렬 알고리즘을 많이 하는데 나도 직접 한번 구현해보기로 했다.
SFML에서 Rectangle 오브젝트를 가지고 긴 막대기로 각 Element의 value 값을 표시했다.
Element의 value 값이 클 수록 막대기는 위로 길쭉하게 나타나는 것이다.
그 다음 C++의 random 라이브러리를 이용해서 무작위로 섞고 정렬 알고리즘으로 다시 재정렬되는 과정을 그래픽화하였다.
#include <SFML/Graphics.hpp>
#include <iostream>
#include <random>
#include <chrono>
#include <vector>
#include <string>
// 정렬될 ELEMENT에 대한 정보.
#define ELEMENT_SIZE 100
#define ELEMENT_WIDTH 5
#define ELEMENT_HEIGHT_MULTIPLIER 2
#define BETWEEN_ELEMENT_SIZE 1
int elements[ELEMENT_SIZE] = {0, };
// Window에 대한 정보.
#define BELOW_BLANK_SIZE 300
#define ABOVE_BLACN_SIZE 50
#define WINDOW_SIZE_WIDTH (ELEMENT_WIDTH + BETWEEN_ELEMENT_SIZE) * (ELEMENT_SIZE + 2)
#define WINDOW_SIZE_HEIGHT ELEMENT_SIZE * ELEMENT_HEIGHT_MULTIPLIER + BELOW_BLANK_SIZE + ABOVE_BLACN_SIZE
// Text에 대한 정보.
sf::Font font;
sf::Text random_text;
sf::Text bubble_text;
sf::Text select_text;
#define TEXT_SIZE 24
#define GAP_BETWEEN_TEXT 10
sf::RenderWindow window(sf::VideoMode(WINDOW_SIZE_WIDTH, WINDOW_SIZE_HEIGHT), "Sorting Simulator");
std::vector<sf::RectangleShape> rect_vec;
// 각 Element에 대해서 그래픽으로 그림.
void DrawElements(int key_element) {
int i;
for (i = 0; i < ELEMENT_SIZE; i++) {
sf::RectangleShape rect(sf::Vector2f(ELEMENT_WIDTH, elements[i] * ELEMENT_HEIGHT_MULTIPLIER));
rect.setOrigin(0, elements[i] * ELEMENT_HEIGHT_MULTIPLIER);
rect.setPosition(sf::Vector2f(ELEMENT_WIDTH * 2 + i * (ELEMENT_WIDTH + BETWEEN_ELEMENT_SIZE), WINDOW_SIZE_HEIGHT - BELOW_BLANK_SIZE));
rect.setFillColor(sf::Color::Black);
if(i == key_element)
rect.setFillColor(sf::Color::Green);
window.draw(rect);
}
}
// Text에 대한 속성을 설정.
void SetText() {
random_text.setFont(font);
random_text.setString("RANDOMIZE");
random_text.setOutlineThickness(5);
random_text.setOutlineColor(sf::Color::Black);
random_text.setPosition(50, WINDOW_SIZE_HEIGHT - BELOW_BLANK_SIZE);
random_text.setCharacterSize(TEXT_SIZE);
bubble_text.setFont(font);
bubble_text.setString("BUBBLE SORT");
bubble_text.setOutlineThickness(5);
bubble_text.setOutlineColor(sf::Color::Black);
bubble_text.setPosition(50, WINDOW_SIZE_HEIGHT - BELOW_BLANK_SIZE + (TEXT_SIZE + GAP_BETWEEN_TEXT));
bubble_text.setCharacterSize(TEXT_SIZE);
select_text.setFont(font);
select_text.setString("SELECTION SORT");
select_text.setOutlineThickness(5);
select_text.setOutlineColor(sf::Color::Black);
select_text.setPosition(50, WINDOW_SIZE_HEIGHT - BELOW_BLANK_SIZE + (TEXT_SIZE + GAP_BETWEEN_TEXT) * 2);
select_text.setCharacterSize(TEXT_SIZE);
};
void DrawText() {
window.draw(random_text);
window.draw(bubble_text);
window.draw(select_text);
}
void BubbleSort() {
int i, j, temp;
sf::Event event;
for (i = 0; i < ELEMENT_SIZE - 1; i++) {
for (j = 0; j < ELEMENT_SIZE - i - 1; j++) {
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
return;
}
}
window.clear(sf::Color::White);
DrawElements(j);
DrawText();
window.display();
if (elements[j] > elements[j + 1]) {
temp = elements[j + 1];
elements[j + 1] = elements[j];
elements[j] = temp;
}
}
}
}
void SelectionSort() {
int i, j, least, temp;
sf::Event event;
for (i = 0; i < ELEMENT_SIZE - 1; i++) {
least = i;
for (j = i + 1; j < ELEMENT_SIZE; j++) {
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
return;
}
}
window.clear(sf::Color::White);
DrawElements(j);
DrawText();
window.display();
if (elements[j] < elements[least])
least = j;
}
if (i != least) {
temp = elements[least];
elements[least] = elements[i];
elements[i] = temp;
}
}
}
int main() {
int i;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
bool is_sorting_done = false;
std::default_random_engine engine(seed);
font.loadFromFile("Arial.ttf");
SetText();
for (i = 0; i < ELEMENT_SIZE; i++) {
elements[i] = i + 1;
}
std::shuffle(elements, elements + ELEMENT_SIZE, engine);
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
int mouse_x = sf::Mouse::getPosition(window).x;
int mouse_y = sf::Mouse::getPosition(window).y;
// randomize 버튼 클릭 시.
if (random_text.getGlobalBounds().contains(mouse_x, mouse_y)) {
std::cout << mouse_x << mouse_y;
std::shuffle(elements, elements + ELEMENT_SIZE, engine);
is_sorting_done = false;
}
// 버블 정렬 버튼 클릭 시.
if (bubble_text.getGlobalBounds().contains(mouse_x, mouse_y) && is_sorting_done == false) {
BubbleSort();
is_sorting_done = true;
}
// 선택 정렬 버튼 클릭 시.
if (select_text.getGlobalBounds().contains(mouse_x, mouse_y) && is_sorting_done == false) {
SelectionSort();
is_sorting_done = true;
}
}
window.clear(sf::Color::White);
DrawElements(-1);
DrawText();
window.display();
}
return 0;
}
Text의 속성을 처리하는 방식이 지저분한데, 아직 C++의 객체 지향에 익숙하지 않아서 나중에 좀 더 익숙해지면 다시 수정해야겠다.
결과.
보완할 점.
- 더 많은 정렬 알고리즘의 구현. (예를 들어, 퀵 정렬, 카운팅 정렬, 힙 정렬, 머지 소트 등)
- 경과 시간 표시로 성능을 수치화하여 비교해볼 수 있는 기능.
'Game Development > SFML' 카테고리의 다른 글
SFML) 모래와 물이 떨어지는 시뮬레이션 구현하기 in C++ (0) | 2023.09.03 |
---|---|
SFML로 DFS 시뮬레이션 해보기 in C++ (0) | 2023.09.02 |