๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๊ฒŒ์ž„๊ฐœ๋ฐœ

BSP ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•œ ๋žœ๋ค ๋งต ์ƒ์„ฑ ใ…ก๋กœ๊ทธ๋ผ์ดํฌ

์•ž์„  ๋กœ๊ทธ๋ผ์ดํฌ ๋งต ์ƒ์„ฑ ๋ฐฉ์‹ ๊ธ€์„ ํ†ตํ•ด ํ˜„์žฌ ๊ฐ€์žฅ ๋ณดํŽธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋กœ๊ทธ๋ผ์ดํฌ ๋งต ์ƒ์„ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ BSP ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด์ œ, ์ด๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๋ฉฐ ๊ณต๋ถ€ํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

๋จผ์ €, BSP ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•œ ๋žœ๋ค ๋งต ์ƒ์„ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ ˆ์ฐจ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

  1. ๊ณต๊ฐ„์„ ๋‘ ๊ฐœ๋กœ ๊ณ„์†ํ•ด์„œ ๋‚˜๋ˆˆ๋‹ค. (๋‚˜๋ˆˆ ๊ณต๊ฐ„์„ ํŠธ๋ฆฌ๋กœ ๊ตฌ์„ฑ)
  2. ๋‚˜๋ˆˆ ๊ณต๊ฐ„์— ๊ณต๊ฐ„์„ ๋ฒ—์–ด๋‚˜์ง€ ์•Š๋Š” ํฌ๊ธฐ์˜ ๋ฐฉ์„ ๋งŒ๋“ ๋‹ค.
  3. ๋ฐฉ๋ผ๋ฆฌ ์„œ๋กœ ์ด์–ด์ค€๋‹ค.

 

1. ๊ณต๊ฐ„์„ ๋‘ ๊ฐœ๋กœ ๊ณ„์†ํ•ด์„œ ๋‚˜๋ˆˆ๋‹ค.

BSP ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์‹ค์งˆ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋‹จ๊ณ„๋กœ ์ด๋ฆ„์—์„œ๋„ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด Binary Space Partitioning, ์ฆ‰ ๊ณต๊ฐ„์„ ๋‘ ๊ฐœ๋กœ ๋‚˜๋ˆ„์–ด ํŠธ๋ฆฌ๋กœ ์ €์žฅํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค. BSP ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž์ฒด๋Š” ์–ด๋–ค ๋ชจ์–‘์˜ ๊ณต๊ฐ„์œผ๋กœ๋“  ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์ง€๋งŒ ์ €๋Š” Pixel Dungeon ๊ฒŒ์ž„๊ณผ ๊ฐ™์ด ์‚ฌ๊ฐํ˜•์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ๋˜์ „์„ ๋งŒ๋“ค๊ณ ์ž ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ๊ฐํ˜•์œผ๋กœ ๊ณต๊ฐ„์„ ๋‚˜๋ˆ„๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์„ ๊ทธ๋ฆผ์œผ๋กœ ๋‚˜ํƒ€๋‚ด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํŠธ๋ฆฌ๋กœ ์ €์žฅํ•˜๋Š” ๊ณผ์ •์—์„œ ๊ฐ ๋…ธ๋“œ์— ๊ณต๊ฐ„์˜ ์™ผ์ชฝ ์ƒ๋‹จ ์œ„์น˜ ์ •๋ณด์™€ ๊ณต๊ฐ„์˜ ๊ฐ€๋กœ, ์„ธ๋กœ ๊ธธ์ด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ผ๋‹จ ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ ํด๋ž˜์Šค์™€ ์œ„์น˜, ๊ณต๊ฐ„ ํฌ๊ธฐ๋ฅผ ์ €์žฅํ•  ๊ตฌ์กฐ์ฒด๋ฅผ ๋จผ์ € ์ •์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

struct Rect
{
    int x; int y;
    int width; int height;
};

class Node
{
    public:
        Node* leftNode;
        Node* rightNode;
        Rect rect;
    
    public:
        Node(int x, int y, int width, int height);
};

Node::Node(int x, int y, int width, int height)
{
    rect.x = x; rect.y = y;
    rect.width = width; rect.height = height;
}

์œ„์น˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” Rect ๊ตฌ์กฐ์ฒด์—๋Š” ๊ณต๊ฐ„์˜ ์™ผ์ชฝ ์ƒ๋‹จ ์œ„์น˜์ธ x, y ์ขŒํ‘œ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณ€์ˆ˜์™€ ์‚ฌ๊ฐํ˜•์œผ๋กœ ๋‚˜๋ˆˆ ๊ณต๊ฐ„์˜ ํฌ๊ธฐ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€๋กœ, ์„ธ๋กœ ๊ธธ์ด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณ€์ˆ˜๋„ ๊ฐ™์ด ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , ๋…ธ๋“œ์—๋Š” ์ž์‹ ์˜ ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” leftNode, rightNode๋ฅผ ์„ ์–ธํ•˜๊ณ  Rect๋ผ๋Š” ์œ„์น˜, ๊ณต๊ฐ„ ์ •๋ณด๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” rect ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์ด์ œ, ๊ณต๊ฐ„์„ ๋‚˜๋ˆŒ ์ง€๋„๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”๋ฐ ์—ฌ๊ธฐ์„œ๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ 2์ฐจ์› ๋ฐฐ์—ด๋กœ ํ‘œํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

#define mapWidth 60
#define mapHeight 60

int map[mapHeight][mapWidth];

 

๋งต๋„ ๋งŒ๋“ค์—ˆ๊ณ  ํŠธ๋ฆฌ๋ฅผ ์œ„ํ•œ ๋…ธ๋“œ์™€ ์œ„์น˜, ๊ณต๊ฐ„ ํฌ๊ธฐ๋ฅผ ์œ„ํ•œ ๊ตฌ์กฐ์ฒด๋„ ์„ ์–ธํ–ˆ์œผ๋‹ˆ ์ด์ œ ๋งต์„ ๋‘ ๊ฐœ๋กœ ๊ณ„์†ํ•ด์„œ ๋‚˜๋ˆ„๋Š” ํ•จ์ˆ˜๋ฅผ ํ•œ๋ฒˆ ์ƒ๊ฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๊ณต๊ฐ„์„ ๋‘ ๊ฐœ๋กœ ๋‚˜๋ˆŒ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”? ๋จผ์ € ์ตœ์ดˆ์˜ ๊ณต๊ฐ„์„ ๋‚˜ํƒ€๋‚ด๋Š” root ๋…ธ๋“œ๊ฐ€ ์žˆ์–ด์•ผ๊ฒ ์ง€์š”. ๊ทธ๋Ÿผ, ์ตœ์ดˆ์˜ ๊ณต๊ฐ„(๋…ธ๋“œ)์ธ root๋…ธ๋“œ์˜ ๊ณต๊ฐ„ ์œ„์น˜ ์ •๋ณด๋Š” ์™ผ์ชฝ ์ƒ๋‹จ ์ขŒํ‘œ๋ฅผ ์ €์žฅํ•˜๊ธฐ๋กœ ํ•˜์˜€์œผ๋‹ˆ (0, 0)์ด๊ณ  width, height์ด ๊ฐ๊ฐ 60์ž„์„ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ผ๋‹จ ์„ธ๋กœ๋กœ ๋ถ„ํ• ํ•ด 2๊ฐœ์˜ ๊ณต๊ฐ„์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค๊ณ  ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์™ผ์ชฝ์— ์žˆ๋Š” ๊ณต๊ฐ„(๋…ธ๋“œ)์™€ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋Š” ๊ณต๊ฐ„(๋…ธ๋“œ)์œผ๋กœ ๋‚˜๋‰˜๋Š”๋ฐ ๊ฐ๊ฐ ์œ„์น˜ ์ •๋ณด๋Š” (0,0), (n, 0)์ด๊ณ  width๋Š” root.width - right.width right.width, height์€ root.height์ž…๋‹ˆ๋‹ค.

 

์ด๋ฒˆ์—” ๊ฐ€๋กœ๋กœ ๋ถ„ํ• ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์œ„์ชฝ์— ์žˆ๋Š” ๊ณต๊ฐ„(๋…ธ๋“œ)์™€ ์•„๋ž˜์ชฝ์— ์žˆ๋Š” ๊ณต๊ฐ„(๋…ธ๋“œ)์œผ๋กœ ๋‚˜๋‰˜๋Š”๋ฐ ์œ„์ชฝ์— ์žˆ๋Š” ๊ณต๊ฐ„์ด ๋ฐฐ์—ด ์ƒ ๋” ์ž‘์€ ์ขŒํ‘œ์— ํ•ด๋‹นํ•˜๋ฏ€๋กœ ์™ผ์ชฝ์— ์žˆ๋Š” ๊ณต๊ฐ„์œผ๋กœ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ ์œ„์น˜ ์ •๋ณด๋Š” (0,0), (0, n)์ด๊ณ  width๋Š” root.width, height์€ root.height - right.height, right.height์ž…๋‹ˆ๋‹ค.

 

๋‚˜๋‰œ ๋…ธ๋“œ์— ๋Œ€ํ•ด์„œ๋„ ์ด ๋‘ ๊ฐ€์ง€ ๊ฐ€์ •์ด ๊ณ„์†ํ•ด์„œ ๋ฐ˜๋ณต๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐ์ด ๋“œ์‹œ๋‚˜์š”? ๊ทธ๋Ÿผ ์ด๋Š” ์žฌ๊ท€์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์žฌ๊ท€์˜ ๊ณผ์ •์—์„œ ์–ด๋–ค ๊ณต๊ฐ„์„ ๊ฐ€๋กœ ๋˜๋Š” ์„ธ๋กœ๋กœ ๋‚˜๋ˆ„์–ด์•ผ ํ•˜๋Š”์ง€๋Š” ์ •ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ๋‹จ์ˆœํ•˜๊ฒŒ ๊ธธ์ด๊ฐ€ ๊ธด ์ชฝ์— ๋Œ€ํ•ด ์ˆ˜์ง์œผ๋กœ ๋ถ„ํ• ํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๊ฐ€๋กœ๊ฐ€ ๋” ๊ธธ๋ฉด ์„ธ๋กœ๋กœ ์ž๋ฅด๊ณ  ์„ธ๋กœ๊ฐ€ ๋” ๊ธธ๋ฉด ๊ฐ€๋กœ๋กœ ์ž๋ฅด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹จ, ์ฝ˜์†”์— ์ถœ๋ ฅ ์‹œ ๊ฐ™์€ ํฌ๊ธฐ๋ผ๋„ ๊ฐ€๋กœ๋ณด๋‹ค ์„ธ๋กœ๊ฐ€ ๋” ์ปค๋ณด์ด๋ฏ€๋กœ ๊ฐ€๋กœ๋ž‘ ์„ธ๋กœ๊ฐ€ ๊ฐ™์€ ํฌ๊ธฐ๋ฉด ๊ฐ€๋กœ๋กœ ์ž๋ฅด๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์žฌ๊ท€์ ์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผํ•จ๋„ ์•Œ์•˜๊ณ  ๋‚˜๋ˆ„๋Š” ๊ธฐ์ค€๋„ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ๋‚˜๋ˆŒ๋•Œ n๊ณผ right.height ๋˜๋Š” right.width์„ ์ •ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•๋งŒ ์•Œ๋ฉด ๋˜๋Š”๋ฐ ์–˜๋Š” ๊ทธ๋ƒฅ ํŠน์ • ๋น„์œจ ์‚ฌ์ด์˜ ๊ฐ’์„ ๋žœ๋คํ•˜๊ฒŒ ๊ฐ€์ ธ์˜ค๋„๋ก ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์™œ ํŠน์ • ๋น„์œจ ์‚ฌ์ด์˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋ƒ๋ฉด, ๊ฐ’์ด ๋„ˆ๋ฌด ์ž‘๊ฑฐ๋‚˜ ํฌ๋ฉด ํ•œ ๊ณต๊ฐ„์€ ๋ฌด์šฉ์ง€๋ฌผ์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

์ œ๊ฐ€ ๊ตฌํ˜„ํ•œ ๋งต์„ ๋‘ ๊ฐœ๋กœ ๊ณ„์†ํ•ด์„œ ๋‚˜๋ˆ„๋Š” ํ•จ์ˆ˜, Divide๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

double minRatio = 0.4, maxRatio = 0.7;
int maxDepth = 4;

// low ~ high ์‚ฌ์ด์˜ ๊ฐ’ ๋ฐ˜ํ™˜
int random(int low, int high)
{
    return low + rand() % (high - low + 1);
}

void Divide(Node *node, int depth)
{
    if (depth == maxDepth) return;

    int maxLen = node->rect.width > node->rect.height ? node->rect.width : node->rect.height;
    int split = random(round(maxLen * minRatio), round(maxLen * maxRatio));

    if (node->rect.width >= node->rect.height)
    {
        node->leftNode = new Node(node->rect.x, node->rect.y, split, node->rect.height);
        node->rightNode = new Node(node->rect.x + split, node->rect.y, node->rect.width - split, node->rect.height);

		for (int i = node->leftNode->rect.y; i < node->leftNode->rect.y + node->leftNode->rect.height; i++)
            map[i][node->rightNode->rect.x] = 1;
    } else 
	{
        node->leftNode = new Node(node->rect.x, node->rect.y, node->rect.width, split);
        node->rightNode = new Node(node->rect.x, node->rect.y + split, node->rect.width, node->rect.height - split);

		for (int i = node->leftNode->rect.x; i < node->leftNode->rect.x + node->leftNode->rect.width; i++)
            map[node->rightNode->rect.y][i] = 1;
    }

    Divide(node->leftNode, depth + 1);
    Divide(node->rightNode, depth + 1);
}

// ๋งต์„ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜
void PrintMap()
{
    for (int i = 0; i < mapHeight; i++) {
        for (int j = 0; j < mapWidth; j++)
            cout << map[i][j];
        cout << endl;
    }
}

์ œ๋Œ€๋กœ ๋‚˜๋‰œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์ฃ ?

 

 

2. ๋‚˜๋ˆˆ ๊ณต๊ฐ„์„ ๋ฒ—์–ด๋‚˜์ง€ ์•Š๋Š” ํฌ๊ธฐ์˜ ๋ฐฉ์„ ๋งŒ๋“ ๋‹ค.

์ด์ œ ๊ณต๊ฐ„๋„ ๋‚˜๋ˆ„์—ˆ๊ณ  ๊ฐ ๊ณต๊ฐ„์˜ ์œ„์น˜ ์ •๋ณด์™€ ํฌ๊ธฐ ์ •๋ณด๋„ ์ €์žฅํ•ด๋†“์•˜์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•ด ๊ฐ ๊ณต๊ฐ„์— ๋ฐฉ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด์ „ ๊ณผ์ •์—์„œ ๋น„์œจ์„ ํ†ตํ•ด ๋‚˜๋ˆ„๋Š” ํฌ๊ธฐ๋ฅผ ์ •ํ•˜์˜€๋“ฏ์ด ๋ฐฉ์˜ ์œ„์น˜, ํฌ๊ธฐ ์ •๋ณด๋ฅผ ๋น„์œจ์— ์‚ฌ์ด์˜ ์ •์ˆ˜ ๊ฐ’์œผ๋กœ ๋žœ๋คํ•˜๊ฒŒ ์ •ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ณต๊ฐ„์„ ์–ด๋–ป๊ฒŒ ๋‚˜๋ˆ„์—ˆ๋“  ์ตœ์ข… leaf ๋…ธ๋“œ๋“ค ๋‚ด์— ๋ฐฉ์„ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋ฏ€๋กœ leaf ๋…ธ๋“œ๊ฐ€ ๋‚˜์˜ฌ๋•Œ๊นŒ์ง€ ์žฌ๊ท€ ํ˜ธ์ถœํ•ด์•ผ๊ฒ ๋„ค์š”.

 

์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ์ ์€ ์œ„์น˜ ์ •๋ณด๋ฅผ ๋จผ์ € ๊ฒฐ์ •ํ•ด๋ฒ„๋ฆฌ๋ฉด ํฌ๊ธฐ ์ •๋ณด๋ฅผ ์ •ํ•˜๋Š” ๊ณผ์ •์—์„œ ๊ณต๊ฐ„์„ ๋ฒ—์–ด๋‚˜๊ฑฐ๋‚˜ ๋„ˆ๋ฌด ์ž‘์€ ๊ณต๊ฐ„์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ํฌ๊ธฐ ์ •๋ณด๋ฅผ ๋จผ์ € ๊ฒฐ์ •ํ•˜๊ณ  ํ›„์— ์œ„์น˜ ์ •๋ณด๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ์‹์ด ๋” ํŽธํ•  ๊ฒƒ ๊ฐ™๋„ค์š”.

 

์ €๋Š” ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

class Node
{
    public:
        Node* leftNode;
        Node* rightNode;
        Rect rect;
        Rect room; // ๋ฐฉ ์ •๋ณด ์ €์žฅ์„ ์œ„ํ•œ ๋ณ€์ˆ˜ ์ถ”๊ฐ€
    
    public:
        Node(int x, int y, int width, int height);
};

Rect GenerateRoom(Node* node, int depth)
{
    Rect rect;

    if (depth == maxDepth)
    {
        rect.width = random(round(node->rect.width * minRatio), round(node->rect.width * maxRatio));
        rect.height = random(round(node->rect.height * minRatio), round(node->rect.height * maxRatio));

        rect.x = random(node->rect.x + 1, node->rect.x + (node->rect.width-rect.width));
        rect.y = random(node->rect.y + 1, node->rect.y + (node->rect.height-rect.height));
    } else
    {
        node->leftNode->room = GenerateRoom(node->leftNode, depth + 1);
        node->rightNode->room = GenerateRoom(node->rightNode, depth + 1);
    }

    return rect;
}

// ๋ฐฉ์„ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜
void PrintRoom(Node* node, int depth)
{
    if (depth == maxDepth)
    {
        for (int j = node->room.y; j < node->room.y + node->room.height; j++)
            for (int i = node->room.x; i < node->room.x + node->room.width; i++)
                map[j][i] = 3;
    } else {
        PrintRoom(node->leftNode, depth + 1);
        PrintRoom(node->rightNode, depth + 1);
    }
}

๋ฐฉ์„ ์˜๋ฏธํ•˜๋Š” 3์ด ๊ณต๊ฐ„์„ ๋ฒ—์–ด๋‚˜์ง€ ์•Š๊ณ  ์ž˜ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ ๋ฒˆ ๋Œ๋ ค๋ณด๋ฉด ์•„์‹œ๊ฒ ์ง€๋งŒ ๊ณ„์† ๋žœ๋คํ•˜๊ฒŒ ๋ฐฉ์ด ์ƒ์„ฑ๋จ์„ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

3. ๋ฐฉ๋ผ๋ฆฌ ์„œ๋กœ ์ด์–ด์ค€๋‹ค.

์‚ฌ์‹ค ๊ฐ€์žฅ ์• ๋ฅผ ๋จน์—ˆ๋˜ ๊ตฌ๊ฐ„์ž…๋‹ˆ๋‹ค. ๋จผ์ €, ์ €๋Š” ์ด๋Ÿฐ์‹์œผ๋กœ ๊ธธ์„ ๋งŒ๋“ค๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

 

 

๋ณด์‹œ๋ฉด ๊ฐ€๋กœ์™€ ์„ธ๋กœ ๊ฒฝ๋กœ๊ฐ€ ๋ชจ์–‘์€ ๊ฐ™์ง€๋งŒ ๋ฐฐ์—ด๋กœ ํ‘œํ˜„ํ•˜๋ ค๋ฉด x, y ์ขŒํ‘œ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ‘œํ˜„๋จ์„ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ€๋กœ๋กœ ์ด์–ด์ฃผ๋Š” ํ•จ์ˆ˜์™€ ์„ธ๋กœ๋กœ ์ด์–ด์ฃผ๋Š” ํ•จ์ˆ˜๋กœ ๋‚˜๋ˆ„์–ด ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธธ์„ 3๋‹จ๊ณ„๋กœ ๋‚˜๋ˆ„์–ด ์™ผ์ชฝ ๋ฐฉ๋ถ€ํ„ฐ ๊บพ์ด๋Š” ๊ตฌ๊ฐ„๊นŒ์ง€๋ฅผ 1๋‹จ๊ณ„, ๊บพ์ด๋Š” ๊ตฌ๊ฐ„์„ 2๋‹จ๊ณ„, ๊บพ์ด๋Š” ๊ตฌ๊ฐ„๋ถ€ํ„ฐ ์˜ค๋ฅธ์ชฝ ๋ฐฉ๊นŒ์ง€๋ฅผ 3๋‹จ๊ณ„๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

๋จผ์ €, ๊ฐ€๋กœ๋กœ ๋ถ„ํ•  ๋œ ๊ณต๊ฐ„ ์† ๋ฐฉ ๋‘ ๊ฐœ๋ฅผ ์ด์–ด์ค€๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๋‹จ๊ณ„๋ณ„๋กœ ํ•œ๋ฒˆ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ 1๋‹จ๊ณ„์—์„œ ์™ผ์ชฝ ๋ฐฉ์€ ํ•ญ์ƒ ๋ฐฉ์˜ ์•„๋ž˜์ชฝ์—์„œ ๊ธธ์ด ์ด์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ, y ์ขŒํ‘œ๋Š” ๊ณ ์ •๋˜๊ฒ ๋„ค์š”. ํ•˜์ง€๋งŒ x ์ขŒํ‘œ๋Š” ์ƒ๊ด€์ด ์—†์ฃ ? ๊ทธ๋ž˜์„œ ์ €๋Š” ์ค‘์•™์œผ๋กœ ๊ณ ์ •์‹œ์ผœ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์™ผ์ชฝ ๋ฐฉ์€ ์ค‘๊ฐ„ ์•„๋ž˜ ์ขŒํ‘œ๊ฐ€ ํ•ญ์ƒ (room.x + (room.width/2), room.y + room.height)์œผ๋กœ ์ •ํ•ด์ ธ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ขŒํ‘œ์—์„œ ๊บพ์ด๋Š” ๊ตฌ๊ฐ„๊นŒ์ง€ y์ขŒํ‘œ๋งŒ 1์”ฉ ์ฆ๊ฐ€์‹œ์ผœ์ฃผ๋ฉด ๋  ๊ฑฐ ๊ฐ™๋„ค์š”. ๊ทผ๋ฐ ์ด์ œ ๊บพ์ด๋Š” ๊ตฌ๊ฐ„ ์ขŒํ‘œ๋ฅผ ์–ด๋–ป๊ฒŒ ์ •ํ•ด์ค˜์•ผ ํ• ์ง€ ๋ชจ๋ฅด๊ฒ ๋”๊ตฐ์š”.. ๊ทธ๋Ÿฐ๋ฐ ๊ฐ‘์ž๊ธฐ ์•„๊นŒ 1๋‹จ๊ณ„์—์„œ ์“ฐ์ธ split ๋ณ€์ˆ˜๊ฐ€ ์ƒ๊ฐ์ด ๋‚ฌ์Šต๋‹ˆ๋‹ค. ์™ผ์ชฝ ๋ฐฉ ์ค‘๊ฐ„ ์ขŒํ‘œ์—์„œ rect.y + split๋งŒํผ ๊ธธ์„ ๊ทธ๋ ธ๋‹ค๊ฐ€ (1๋‹จ๊ณ„) rect.y + split์—์„œ ๊บพ์ด๋Š” ๊ตฌ๊ฐ„์„ ๋งŒ๋“ค๋ฉด ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค๋”๊ตฐ์š”.

 

2๋‹จ๊ณ„๋„ ๊ทธ๋Ÿผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„์ด ๋˜๊ฒ ๋„ค์š”. y ์ขŒํ‘œ๋Š” ์ด๋ฏธ ์•Œ์•˜๊ณ , x ์ขŒํ‘œ๋งŒ ์™ผ์ชฝ x ์ขŒํ‘œ์—์„œ ์˜ค๋ฅธ์ชฝ x ์ขŒํ‘œ๋กœ ์ด๋™์‹œ์ผœ์ฃผ๋ฉด ๋˜๋Š”๋ฐ ์™ผ์ชฝ x ์ขŒํ‘œ๊ฐ€ ๋” ์ž‘์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ํด ์ˆ˜๋„ ์žˆ์ž–์•„์š”? ๊ทธ๋ž˜์„œ ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ x ์ขŒํ‘œ๋ฅผ ๋น„๊ตํ•ด์„œ ์ž‘์€ ์ชฝ์˜ x ์ขŒํ‘œ์—์„œ ํฐ ์ชฝ์˜ x ์ขŒํ‘œ๋กœ ์ด๋™์‹œํ‚ค๋ฉด์„œ ๊ธธ์„ ๊ทธ๋ฆฌ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

3๋‹จ๊ณ„๋Š” 1๋‹จ๊ณ„์™€ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„์ด ๋ฉ๋‹ˆ๋‹ค. ์˜ค๋ฅธ์ชฝ ๋ฐฉ์€ ํ•ญ์ƒ ์ค‘์•™ ์œ„ ์ขŒํ‘œ์—์„œ ๊ธธ์„ ๊ทธ๋ฆฌ๋ฉฐ ์ค‘์•™ ์ขŒํ‘œ๋Š” (room.x + (room.width/2), room.y)์ž…๋‹ˆ๋‹ค. x ์ขŒํ‘œ๋Š” ๊ณ ์ •ํ•œ์ฑ„ rect.y + split๋ถ€ํ„ฐ room.y๊นŒ์ง€ ๊ทธ๋ฆฌ๋ฉด ๋˜๊ฒ ๊ตฐ์š”. ์„ธ๋กœ๋กœ ๋ถ„ํ•  ๋œ ๊ฒฝ์šฐ๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด ์‰ฝ๊ฒŒ ํ•ด๊ฒฐ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์ด์ œ ์ด ๋‘ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ธธ์„ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ €๋Š” leaf ๋…ธ๋“œ๋ถ€ํ„ฐ ํŠธ๋ฆฌ๋ฅผ ํƒ€๊ณ  ๊ฐ€๋ฉด์„œ ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ์— ๊ธธ์„ ์ด์–ด์ฃผ๋Š” ๋ฐฉ์‹์„ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ €ํฌ๋Š” ๋ฐฉ ์ •๋ณด๋ฅผ leaf ๋…ธ๋“œ์—๋งŒ ์ €์žฅํ•˜๊ณ  ๋ถ€๋ชจ ๋…ธ๋“œ๋“ค์—๋Š” ์ €์žฅํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌ๋ฉด ๋ฌธ์ œ๋Š” ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ leaf ๋…ธ๋“œ๋งŒ ๊ธธ์ด ์ด์–ด์ ธ์„œ ๊ฒฐ๊ตญ ๋ชจ๋“  ๋ฐฉ์ด ์—ฐ๊ฒฐ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ์• ์ดˆ์— ๋ฐฉ์„ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜ GenerateRoom์—์„œ ๋ถ€๋ชจ ๋…ธ๋“œ์— ๊ฐ leaf ๋…ธ๋“œ์— ์ƒ์„ฑ๋œ ๋ฐฉ ์ •๋ณด ์ค‘ ํ•˜๋‚˜๋ฅผ ์ €์žฅํ•˜๋„๋ก ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ €๋Š” else ๋ฌธ์— ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ ๋ฐฉ ์ •๋ณด ์ค‘ ๋žœ๋คํ•˜๊ฒŒ ์„ ํƒํ•˜์—ฌ ์ด๋ฅผ ๋ถ€๋ชจ์—๊ฒŒ ๋„˜๊ฒจ์ฃผ๋Š” ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์‚ด์ง ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์ด์ œ leaf ๋…ธ๋“œ๊นŒ์ง€ ๊ฐ„ ํ›„ ํŠธ๋ฆฌ๋ฅผ ํƒ€๊ณ  ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ์„œ๋กœ ๊ธธ์„ ์ด์–ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ์™„์„ฑ์ž…๋‹ˆ๋‹ค. ๋‹จ, ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๊ธธ์„ ์ด์–ด์ฃผ๋Š” ๊ณผ์ •์—์„œ ๋ฐฉ์„ ํ†ต๊ณผํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์–ด์„œ ๋ฐฉ ์ •๋ณด๋ฅผ ์ด์šฉํ•ด ๊ธธ์„ ์ด์–ด ์ค€ ๋’ค ๋จผ์ € ์ถœ๋ ฅํ•˜๊ณ  ๋ฐฉ์„ ์ถœ๋ ฅํ•˜๋Š” ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

Rect GenerateRoom(Node* node, int depth)
{
    if (depth == maxDepth)
    {
        ... // ์ด์ „๊ณผ ๊ฐ™์•„์„œ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
    } else
    {
        ...
        if (random(0, 2)) // ๋žœ๋คํ•˜๊ฒŒ ์„ ํƒํ•˜์—ฌ ๋ถ€๋ชจ์—๊ฒŒ ์™ผ์ชฝ ํ˜น์€ ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ์˜ ๋ฐฉ ์ •๋ณด๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.
            rect = node->leftNode->room;
        else
            rect = node->rightNode->room;
    }
	...
}


void RoomSplitHorizon(Node* node) // ์„ธ๋กœ๋กœ ๋ถ„ํ• ๋œ ๊ณต๊ฐ„์˜ ๊ธธ ์ด์–ด์ค„ ๋•Œ ์‚ฌ์šฉ
{
    int lCenterY = node->leftNode->room.y + node->leftNode->room.height;
    int lCenterX = node->leftNode->room.x + (node->leftNode->room.width/2);

    int rCenterY = node->rightNode->room.y;
    int rCenterX = node->rightNode->room.x + (node->rightNode->room.width/2);

    for (int y = lCenterY; y <= node->leftNode->rect.y + node->leftNode->split; y++)
        map[y][lCenterX] = 7;

    int from = lCenterX <= rCenterX ? lCenterX : rCenterX;
    int to = lCenterX <= rCenterX ? rCenterX : lCenterX;

    for (int x = from; x <= to; x++)
        map[node->leftNode->rect.y + node->leftNode->split][x] = 7;

    for (int y = node->leftNode->rect.y + node->leftNode->split; y < rCenterY; y++)
        map[y][rCenterX] = 7;
}

void RoomSplitVertical(Node* node) // ๊ฐ€๋กœ๋กœ ๋ถ„ํ• ๋œ ๊ณต๊ฐ„์˜ ๊ธธ ์ด์–ด์ค„ ๋•Œ ์‚ฌ์šฉ
{
    int lCenterY = node->leftNode->room.y + (node->leftNode->room.height/2);
    int lCenterX = node->leftNode->room.x + node->leftNode->room.width;

    int rCenterY = node->rightNode->room.y + (node->rightNode->room.height/2);
    int rCenterX = node->rightNode->room.x;

    for (int x = lCenterX; x <= node->leftNode->rect.x + node->leftNode->split; x++)
        map[lCenterY][x] = 7;

    int from = lCenterY <= rCenterY ? lCenterY : rCenterY;
    int to = lCenterY <= rCenterY ? rCenterY : lCenterY;

    for (int y = from; y <= to; y++)
        map[y][node->leftNode->rect.x + node->leftNode->split] = 7;

    for (int x = node->leftNode->rect.x + node->leftNode->split; x < rCenterX; x++)
        map[rCenterY][x] = 7;
}

void GeneratePath(Node* node, int depth) // ๊ธธ ์ƒ์„ฑ
{
    if (depth == maxDepth) return;

    GeneratePath(node->leftNode, depth + 1);
    GeneratePath(node->rightNode, depth + 1);

    if (node->leftNode->rect.x == node->rightNode->rect.x)
        RoomSplitHorizon(node);
    else
        RoomSplitVertical(node);
}

์ด์ œ ๊ฐ ๋‹จ๊ณ„๋ฅผ ์ ์ ˆํžˆ ์„ž์–ด์ฃผ๋ฉด ์ตœ์ข… ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

/*
    ๋žœ๋คํ•œ ๋งต์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์ ˆ์ฐจ์  ์ฝ˜ํ…์ธ  ์ƒ์„ฑ (PCG) ๋ฐฉ์‹์˜ BSP ์•Œ๊ณ ๋ฆฌ์ฆ˜ (C++)
    0 -> ํ—ˆ๊ณต void
    3 -> ๋˜์ „ dungeon
    7 -> ๊ธธ path
*/

#include <iostream>
#include <cmath>
#include <stdlib.h>
#include <time.h>

using namespace std;

#define mapWidth 60
#define mapHeight 60

int map[mapHeight][mapWidth];
int maxDepth = 4;
double minRatio = 0.4, maxRatio = 0.7; // ๋ฐฉ์˜ ํฌ๊ธฐ์™€ ๊ฐ™์€ ๋žœ๋ค ์š”์†Œ์— ์‚ฌ์šฉ๋˜๋Š” ์ตœ์†Œ, ์ตœ๋Œ€ ๋น„์œจ

// ๋ฐฐ์—ด ๋‚ด ์œ„์น˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ์กฐ์ฒด
// ์™ผ์ชฝ ์ƒ๋‹จ ์œ„์น˜์— ํ•ด๋‹นํ•จ
struct Rect
{
    int x; int y;
    int width; int height;
};

class Node
{
    public:
        Node* leftNode;
        Node* rightNode;
        Rect rect;
        Rect room;
        int split;
    
    public:
        Node(int x, int y, int width, int height, int split);
};

Node::Node(int x, int y, int width, int height, int split)
{
    rect.x = x; rect.y = y;
    rect.width = width; rect.height = height;
    this->split = split;
}

// void initMap()  // ๋งต์˜ ๊ฐ€์žฅ์ž๋ฆฌ๋ฅผ 1๋กœ ๋ฐ”๊พผ๋‹ค.
// {
//     for (int i = 0; i < mapHeight; i++) {
//         for (int j = 0; j < mapWidth; j++) {
//             if (i == 0 || i == mapHeight-1)
//                 map[i][j] = 1;
//             else {
//                 map[i][0] = 1;
//                 map[i][mapWidth-1] = 1;
//             }
//         }
//     }
// }

void PrintMap()
{
    for (int i = 0; i < mapHeight; i++) {
        for (int j = 0; j < mapWidth; j++)
            cout << map[i][j];
        cout << endl;
    }
}

int random(int low, int high) // low ~ high ๋ฒ”์œ„์˜ ๋žœ๋ค ์ •์ˆ˜ ํ•˜๋‚˜๋ฅผ ๋ฝ‘๋Š”๋‹ค.
{
    return low + rand() % (high - low + 1);
}

void Divide(Node *node, int depth) // ๊ณต๊ฐ„์„ ๋‚˜๋ˆ„๋ฉด์„œ ํŠธ๋ฆฌ ์ƒ์„ฑํ•จ
{
    if (depth == maxDepth) return;

    // width์™€ height ์ค‘ ๊ธด ์ชฝ์„ ์„ ํƒํ•ด์„œ width๋ฉด ์„ธ๋กœ๋กœ ๋ถ„ํ• , height์ด๋ฉด ๊ฐ€๋กœ๋กœ ๋ถ„ํ• 
    int maxLen = node->rect.width > node->rect.height ? node->rect.width : node->rect.height;
    // ๋„ˆ๋ฌด ์ž‘๊ฑฐ๋‚˜ ํฐ ๋ฐฉ์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ๋น„์œจ์„ ์ •ํ•ด์„œ ๋žœ๋ค ์ถ”์ถœ
    int split = random(round(maxLen * minRatio), round(maxLen * maxRatio));

    if (node->rect.width >= node->rect.height) // ํ˜„์žฌ ๋…ธ๋“œ์˜ ๊ฐ€๋กœ๊ฐ€ ๋” ํฌ๋‹ค๋ฉด, ์„ธ๋กœ๋กœ ๋‚˜๋ˆˆ๋‹ค.
    {
        // width, height์ด ๊ฐ™์€ ํฌ๊ธฐ๋ผ๋„ ์ถœ๋ ฅ ์‹œ์—๋Š” height์ด ๋” ํฌ๊ฒŒ ์ถœ๋ ฅ๋˜๋ฏ€๋กœ, ๊ฐ™์€ ํฌ๊ธฐ๋ผ๋„ ์„ธ๋กœ๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด ๋‚ซ๋‹ค. ์•ˆ๊ทธ๋Ÿฌ๋ฉด ๋ฐฉ์ด ๋” ์ž‘์•„๋ณด์ž„
        node->leftNode = new Node(node->rect.x, node->rect.y, split, node->rect.height, split);
        node->rightNode = new Node(node->rect.x + split, node->rect.y, node->rect.width - split, node->rect.height, split);

        // for (int i = node->leftNode->rect.y; i < node->leftNode->rect.y + node->leftNode->rect.height; i++)
        //     map[i][node->rightNode->rect.x] = 1;
    } else {                                   // ํ˜„์žฌ ๋…ธ๋“œ์˜ ์„ธ๋กœ๊ฐ€ ๋” ํฌ๋‹ค๋ฉด, ๊ฐ€๋กœ๋กœ ๋‚˜๋ˆˆ๋‹ค.
        node->leftNode = new Node(node->rect.x, node->rect.y, node->rect.width, split, split);
        node->rightNode = new Node(node->rect.x, node->rect.y + split, node->rect.width, node->rect.height - split, split);

        // for (int i = node->leftNode->rect.x; i < node->leftNode->rect.x + node->leftNode->rect.width; i++)
        //     map[node->rightNode->rect.y][i] = 1;
    }

    Divide(node->leftNode, depth + 1);
    Divide(node->rightNode, depth + 1);
}

void PrintRoom(Node* node, int depth)
{
    if (depth == maxDepth)
    {
        for (int j = node->room.y; j < node->room.y + node->room.height; j++)
            for (int i = node->room.x; i < node->room.x + node->room.width; i++)
                map[j][i] = 3;
    } else {
        PrintRoom(node->leftNode, depth + 1);
        PrintRoom(node->rightNode, depth + 1);
    }
}

Rect GenerateRoom(Node* node, int depth)
{
    Rect rect;

    if (depth == maxDepth)
    {
        // ๋‚˜๋‰œ ๊ณต๊ฐ„์˜ ํฌ๊ธฐ๋ฅผ ๋ฒ—์–ด๋‚˜์ง€ ์•Š๋Š” ์„ ์—์„œ width, height, x, y๋ฅผ ๋žœ๋คํ•˜๊ฒŒ ์ •ํ•ด์ค€๋‹ค.
        rect.width = random(round(node->rect.width * minRatio), round(node->rect.width * maxRatio));
        rect.height = random(round(node->rect.height * minRatio), round(node->rect.height * maxRatio));

        rect.x = random(node->rect.x + 1, node->rect.x + (node->rect.width-rect.width));
        rect.y = random(node->rect.y + 1, node->rect.y + (node->rect.height-rect.height));
    } else
    {
        node->leftNode->room = GenerateRoom(node->leftNode, depth + 1);
        node->rightNode->room = GenerateRoom(node->rightNode, depth + 1);

        if (random(0, 2)) // ๋žœ๋คํ•˜๊ฒŒ ์„ ํƒํ•˜์—ฌ ๋ถ€๋ชจ์—๊ฒŒ ์™ผ์ชฝ ํ˜น์€ ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ์˜ ๋ฐฉ ์ •๋ณด๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.
            rect = node->leftNode->room;
        else
            rect = node->rightNode->room;
    }

    return rect;
}

void RoomSplitHorizon(Node* node) // ์„ธ๋กœ๋กœ ๋ถ„ํ• ๋œ ๊ณต๊ฐ„์˜ ๊ธธ ์ด์–ด์ค„ ๋•Œ ์‚ฌ์šฉ
{
    int lCenterY = node->leftNode->room.y + node->leftNode->room.height;
    int lCenterX = node->leftNode->room.x + (node->leftNode->room.width/2);

    int rCenterY = node->rightNode->room.y;
    int rCenterX = node->rightNode->room.x + (node->rightNode->room.width/2);

    for (int y = lCenterY; y <= node->leftNode->rect.y + node->leftNode->split; y++)
        map[y][lCenterX] = 7;

    int from = lCenterX <= rCenterX ? lCenterX : rCenterX;
    int to = lCenterX <= rCenterX ? rCenterX : lCenterX;

    for (int x = from; x <= to; x++)
        map[node->leftNode->rect.y + node->leftNode->split][x] = 7;

    for (int y = node->leftNode->rect.y + node->leftNode->split; y < rCenterY; y++)
        map[y][rCenterX] = 7;
}

void RoomSplitVertical(Node* node) // ๊ฐ€๋กœ๋กœ ๋ถ„ํ• ๋œ ๊ณต๊ฐ„์˜ ๊ธธ ์ด์–ด์ค„ ๋•Œ ์‚ฌ์šฉ
{
    int lCenterY = node->leftNode->room.y + (node->leftNode->room.height/2);
    int lCenterX = node->leftNode->room.x + node->leftNode->room.width;

    int rCenterY = node->rightNode->room.y + (node->rightNode->room.height/2);
    int rCenterX = node->rightNode->room.x;

    for (int x = lCenterX; x <= node->leftNode->rect.x + node->leftNode->split; x++)
        map[lCenterY][x] = 7;

    int from = lCenterY <= rCenterY ? lCenterY : rCenterY;
    int to = lCenterY <= rCenterY ? rCenterY : lCenterY;

    for (int y = from; y <= to; y++)
        map[y][node->leftNode->rect.x + node->leftNode->split] = 7;

    for (int x = node->leftNode->rect.x + node->leftNode->split; x < rCenterX; x++)
        map[rCenterY][x] = 7;
}

void GeneratePath(Node* node, int depth) // ๊ธธ ์ƒ์„ฑ
{
    if (depth == maxDepth) return;

    GeneratePath(node->leftNode, depth + 1);
    GeneratePath(node->rightNode, depth + 1);

    if (node->leftNode->rect.x == node->rightNode->rect.x)
        RoomSplitHorizon(node);
    else
        RoomSplitVertical(node);
}

int main(void)
{
    srand(time(NULL)); // ๋‚œ์ˆ˜ ์ƒ์„ฑ
    Node* root = new Node(0, 0, mapWidth, mapHeight, 0); // ํŠธ๋ฆฌ์˜ root ๋…ธ๋“œ ์ƒ์„ฑ
    memset(map, 0, sizeof(map));

    Divide(root, 0);
    GenerateRoom(root, 0);
    GeneratePath(root, 0);

    // ๊ณต๊ฐ„ ์ •๋ณด๋กœ ๊ธธ์„ ๊ทธ๋ ค์ฃผ๊ณ , ๋ฐฉ์„ ๊ทธ๋ ค์ฃผ์–ด ๋ฐฉ์„ ํ†ต๊ณผํ•˜๋Š” ๊ธธ์ด ๋ณด์ด์ง€ ์•Š๋„๋ก ํ•จ
    PrintRoom(root, 0);
    PrintMap();

    return 0;
}