실전 활용·미로 프로젝트

Jaemyeong Lee·2024년 10월 31일

게임 서버1

목록 보기
67/220

이 Part에서 다루는 것

  • 실전에서 배열/벡터/리스트를 선택하는 기준
  • C# ListLinkedList의 정확한 의미
  • 콘솔 미로 프로젝트 구성요소(Board, Pos, Direction, 루프)
  • Binary Tree 미로 생성 + 우수법(오른손법) 동작 원리

학습 목표

  • 요구사항(고정 크기/임의 접근/중간 삭제 빈도)에 맞춰 컨테이너를 선택할 수 있다.
  • 미로 프로젝트의 핵심 모듈과 데이터 흐름을 설명할 수 있다.
  • 우수법이 유효한 전제와 한계를 이해할 수 있다.

실전 선택: 배열 vs 동적배열 vs 연결리스트

구조언제 쓰나강점주의점
배열크기가 완전히 고정단순/빠른 인덱스 접근크기 변경 불가
동적 배열(vector)일반적인 기본 선택임의 접근 O(1), 사용 편의성중간 삽입/삭제 O(N)
연결 리스트노드 위치를 이미 잡고 중간 삭제가 많음위치 알고 있을 때 삽입/삭제 O(1)임의 접근 O(N), 캐시 비우호

실전 감각:

  • 대부분은 vector부터 시작하고, 병목이 명확할 때만 리스트를 검토합니다.

C# List vs LinkedList 혼동 정리

  • C# List<T>는 연결 리스트가 아니라 동적 배열입니다.
  • C# LinkedList<T>가 진짜 연결 리스트입니다.
  • 이름만 보고 자료구조 특성을 착각하면 성능 예측이 틀어집니다.

미로 프로젝트 기반 구성

PCH(Precompiled Header)

  • 자주 바뀌지 않는 헤더를 미리 컴파일해 빌드 시간 단축

Types 별칭

  • int32, uint64 같은 별칭으로 가독성과 플랫폼 일관성 확보

ConsoleHelper

  • 커서 이동/색상/커서 표시 여부 제어
  • enum class를 사용해 이름 충돌과 암시적 정수 변환 실수를 줄임

Board / Pos / Direction 설계

Board

  • 2차원 타일 배열로 맵 관리
  • TileType::WALL, TileType::EMPTY 등으로 의미를 명확히 표현

Pos

  • (y, x) 좌표 구조체
  • operator+, ==, != 등 기본 연산 제공

Direction

  • 보통 4방향(UP, LEFT, DOWN, RIGHT)
  • 방향 벡터 테이블로 이동 계산:
Pos front[4] = { {-1, 0}, {0, -1}, {1, 0}, {0, 1} };

Binary Tree 미로 생성(핵심 아이디어)

1) 초기화

  • 짝수 좌표는 벽, 홀수 좌표는 통로로 시작

2) 길 뚫기

  • 각 통로 칸에서 오른쪽/아래 중 하나를 선택해 벽을 뚫음
  • 경계(마지막 행/열)는 가능한 방향만 선택
for (int32 y = 0; y < _size; ++y) {
    for (int32 x = 0; x < _size; ++x) {
        if (x % 2 == 0 || y % 2 == 0) {
            _tile[y][x] = TileType::WALL;
        } else {
            _tile[y][x] = TileType::EMPTY;
            if (y == _size - 2) {
                _tile[y][x + 1] = TileType::EMPTY;
            } else if (x == _size - 2) {
                _tile[y + 1][x] = TileType::EMPTY;
            } else {
                if (rand() % 2 == 0) _tile[y][x + 1] = TileType::EMPTY;
                else                 _tile[y + 1][x] = TileType::EMPTY;
            }
        }
    }
}

특징:

  • 구현이 간단하고 빠르지만, 방향 편향(예: 우하향 경향)이 생길 수 있습니다.

우수법(오른손법) 경로 탐색

규칙(반복):

  1. 오른쪽이 열려 있으면 우회전 후 전진
  2. 아니면 앞이 열려 있으면 전진
  3. 둘 다 막히면 좌회전
bool CanGo(Pos pos)
{
    return _board->GetTileType(pos) == TileType::EMPTY;
}

중요 전제:

  • 우수법은 “벽을 따라 탈출 가능한 구조(보통 단일 연결 구조)”에서 유효합니다.
  • 모든 미로에서 최단 경로를 보장하지는 않습니다.

게임 루프와 시간 누적 이동

기본 루프:

while (true) {
    uint64 deltaTick = GetDeltaTime();
    _player->Update(deltaTick);
    _board->Render();
}

이동 업데이트에서 중요한 점:

  • sumTickMOVE_TICK보다 커졌을 때 0으로 만들면 잔여 시간이 사라질 수 있습니다.
  • 일반적으로는 sumTick -= MOVE_TICK 방식이 안정적입니다.
void Player::Update(uint64 deltaTick)
{
    if (_pathIndex >= _path.size())
        return;

    _sumTick += deltaTick;
    while (_sumTick >= MOVE_TICK && _pathIndex < _path.size()) {
        _sumTick -= MOVE_TICK;        // 잔여 시간 보존
        _pos = _path[_pathIndex++];
    }
}

구현 문제 vs 알고리즘

  • 실무에서는 “새 알고리즘 발명”보다
    기존 자료구조/로직을 안정적으로 조립하는 구현 문제가 훨씬 많습니다.
  • 그래서 미로 프로젝트 같은 조립형 과제는
    디버깅/설계/복잡도 감각을 키우기에 매우 좋습니다.

체크 질문 (스스로 답해보기)

  • 네 프로젝트에서 vector 대신 리스트를 써야 할 근거는 무엇인가?
  • Binary Tree 미로 생성의 장점과 한계는?
  • 우수법이 최단 경로를 보장하지 않는 이유는?

profile
李家네_공부방

0개의 댓글