📌 오른손 법칙이란?

오른손 법칙(Right-Hand Rule)은 미로 탐색 알고리즘 중 하나로,

"항상 벽에 오른손을 대고 이동한다"는 규칙을 따릅니다.

🔁 우선순위

  • ① 오른쪽 방향으로 갈 수 있는지 확인
  • ② 현재 바라보는 방향으로 전진 가능 여부
  • ③ 그렇지 않으면 왼쪽으로 회전

시계 방향 회전이 아닌, 반시계 방향 기준 열거형이므로,
"오른쪽"은 _dir - 1, "왼쪽"은 _dir + 1로 계산됩니다.


🧱 미로 초기화 및 탐색 흐름

1️⃣ 플레이어 초기화 (Player::Init)

void Player::Init(Board* board)
{
    _pos = board->GetEnterPos(); // 시작 위치 설정
    _board = board;

    Pos pos = _pos;
    _path.clear();  // 경로 초기화
    _path.push_back(pos);

    Pos dest = board->GetExitPos(); // 목적지 설정

    Pos front[4] = {
        { -1, 0 }, // UP
        { 0, -1 }, // LEFT
        { 1, 0 },  // DOWN
        { 0, 1 }   // RIGHT
    };

    while (pos != dest)
    {
        int32 newDir = (_dir - 1 + DIR_COUNT) % DIR_COUNT;
        if (CanGo(pos + front[newDir]))
        {
            _dir = newDir;                 // 오른쪽으로 회전
            pos += front[_dir];           // 한 보 전진
            _path.push_back(pos);         // 경로 저장
        }
        else if (CanGo(pos + front[_dir]))
        {
            pos += front[_dir];           // 전진
            _path.push_back(pos);
        }
        else
        {
            _dir = (_dir + 1) % DIR_COUNT; // 왼쪽 회전
        }
    }
}

🧠 핵심 요약

요소설명
_dir현재 방향 (0~3)
front[4]방향 벡터 (UP, LEFT, DOWN, RIGHT)
_path계산된 경로를 저장하는 벡터
CanGo()해당 좌표가 EMPTY인지 검사

⏱️ 일정 시간마다 플레이어 위치 갱신 (Player::Update)

void Player::Update(uint64 deltaTick)
{
    if (_pathIndex >= _path.size())
        return;

    _sumTick += deltaTick;
    if (_sumTick >= MOVE_TICK)
    {
        _sumTick = 0;
        _pos = _path[_pathIndex]; // 다음 위치 이동
        _pathIndex++;
    }
}
  • deltaTick: ::GetTickCount64()로 계산한 프레임 경과 시간
  • MOVE_TICK: 100ms로 설정 → 0.1초마다 한 칸씩 이동
  • _pos: 실제 현재 위치, _path[_pathIndex]에서 단계별 참조

🧪 CanGo 함수

bool Player::CanGo(Pos pos)
{
    TileType tileType = _board->GetTileType(pos);
    return tileType == TileType::EMPTY;
}
  • 해당 좌표가 빈 공간(EMPTY)일 경우에만 true 반환
  • 벽(WALL) 또는 범위 초과인 경우 false

🎨 콘솔 미로 출력 (Board::Render)

void Board::Render()
{
    ConsoleHelper::SetCursorPosition(0, 0);
    ConsoleHelper::ShowConsoleCursor(false);

    for (int32 y = 0; y < 25; y++)
    {
        for (int32 x = 0; x < 25; x++)
        {
            ConsoleColor color = GetTileColor(Pos{ y, x });
            ConsoleHelper::SetCursorColor(color);
            cout << "■";
        }
        cout << endl;
    }
}

색상 기준

타일색상
🔴 RED
🟢 GREEN
플레이어🟡 YELLOW
출구🔵 BLUE

🧱 미로 생성 (Binary Tree 방식)

void Board::GenerateMap()
{
    for (int32 y = 0; y < _size; y++)
    {
        for (int32 x = 0; x < _size; x++)
        {
            _tile[y][x] = (x % 2 == 0 || y % 2 == 0) ? TileType::WALL : TileType::EMPTY;
        }
    }

    for (int32 y = 0; y < _size; y++)
    {
        for (int32 x = 0; x < _size; x++)
        {
            if (x % 2 == 0 || y % 2 == 0)
                continue;

            if (y == _size - 2 && x == _size - 2)
                continue;

            if (y == _size - 2)
            {
                _tile[y][x + 1] = TileType::EMPTY;
                continue;
            }

            if (x == _size - 2)
            {
                _tile[y + 1][x] = TileType::EMPTY;
                continue;
            }

            const int32 randValue = rand() % 2;
            if (randValue == 0)
                _tile[y][x + 1] = TileType::EMPTY;
            else
                _tile[y + 1][x] = TileType::EMPTY;
        }
    }
}
  • 격자 형태로 기본 벽을 구성
  • 각 홀수 좌표에서 우측 또는 하단 방향으로 무작위로 길을 뚫는 구조
  • Binary Tree 알고리즘 기반

🧵 Main 함수 (게임 실행 루프)

int main()
{
    ::srand(static_cast<unsigned>(time(nullptr)));
    board.Init(25, &player);
    player.Init(&board);

    uint64 lastTick = 0;

    while (true)
    {
        const uint64 currentTick = ::GetTickCount64();
        const uint64 deltaTick = currentTick - lastTick;
        lastTick = currentTick;

        player.Update(deltaTick);
        board.Render();
    }
}

🎯 전체 흐름 요약

  1. 미로(Board)를 생성하고 플레이어를 입구에 배치
  2. 오른손 법칙을 기반으로 경로를 _path에 저장
  3. deltaTick 단위로 일정 시간마다 플레이어 이동
  4. 콘솔에 실시간 경로가 렌더링됨

✨ 오른손 법칙 장단점 정리

구분설명
✅ 장점구현이 간단하고 벽에 붙어 있으면 반드시 탈출 가능
⚠️ 단점순환이 없는 미로에서만 보장됨, 최단 경로 아님
➕ 확장성DFS, BFS, A* 등 다른 알고리즘으로 대체 가능

profile
李家네_공부방

0개의 댓글