AI 레이싱 게임 구현해보기(매우 간단)

주환서·2026년 1월 25일
post-thumbnail

1. 개요

  • C++ 콘솔 환경에서 동작하는 AI 레이싱 게임을 구현해보기!

1.1. 기본 게임 규칙

  • 자동차는 총 1대가 존재한다. (+a 5대까지 구현해보기)
  • 각 자동차는 출발 지점에서 목적지까지 이동한다.
  • 결승선에 가장 먼저 도착한 자동차가 우승.

1.2. 이벤트

  • 2초마다 한 번씩 이벤트가 발생.
  1. 일반 속도 증가
  2. 부스터 사용
  3. 옆 차와 충돌

1.3. 화면 출력 예시

1.4. 구현 요소

① GameManager 클래스 (필수 구현)

게임의 전체적인 흐름과 객체들을 관리하는 중추적인 역할을 합니다.

  • 상태 관리: 트랙의 길이, 카(Car) 객체, 이벤트 매니저를 소유하고 관리합니다.
  • 출력 기능: 매 루프마다 트랙과 자동차의 현재 위치를 콘솔에 실시간으로 출력합니다.
  • 승리 판정: 자동차가 트랙 끝에 도달했는지 체크하고, 도달 시 레이스 종료 문구를 출력하며 루프를 탈출합니다.

② EventManager 클래스 (필수 구현)

게임 중 발생하는 무작위 요소들을 전담하여 처리합니다.

  • 확률 로직: 특정 확률에 따라 아래 이벤트 중 하나를 차량에 적용합니다.
    • 속도 업: 일시적으로 이동 거리 증가
    • 속도 다운: 일시적으로 이동 거리 감소
    • 부스트: 큰 폭의 이동 거리 증가
    • 충돌: 이동 정지 또는 패널티 부여
  • 적용: 발생한 이벤트를 자동차 객체의 상태 값에 반영합니다.

2. 구현 결과

// ** Main 소스 파일 **

#include "GameManager.h"

int main() 
{
    const int TRACK_LIMIT = 50;

    // RacingCar 객체 생성
    RacingCar myCar(1, "주환서", TRACK_LIMIT);

    // GameManager에 객체 주소 전달
    GameManager game(&myCar, TRACK_LIMIT);

    // 게임 시작
    game.StartReady();
    game.Run();

    return 0;
}

// ** RacingCar 클래스 헤더파일 **

#pragma once
#include <iostream>
#include <string>

class RacingCar 
{
private:
    int position;
    int num;
    std::string racerName;
    int trackLength;

public:
    RacingCar(int n, std::string name, int length);
    void Render();
    void Move(int distance);
    int GetPosition();
};

// ** RacingCar 클래스 소스파일 **

#include "RacingCar.h"
#include <Windows.h>

using namespace std;

RacingCar::RacingCar(int n, string name, int length)
    : num(n), racerName(name), position(0), trackLength(length) {
}

void RacingCar::Render() 
{
    system("cls");
    cout << "AI 레이싱 게임" << endl;
    cout << "드라이버: " << racerName << " (" << num << "번)" << endl;
    cout << "-----------------------------------------------------" << endl;

    cout << "|";
    for (int i = 0; i < trackLength; i++) 
    {
        if (i == position) cout << "ㅁ>";
        else cout << "=";
    }
    cout << "|" << endl;
    cout << "-----------------------------------------------------" << endl;
}

void RacingCar::Move(int distance) 
{
    position += distance;
    if (position < 0) position = 0;
    if (position > trackLength - 1) position = trackLength - 1;
}

int RacingCar::GetPosition() 
{
    return position;
}

// ** EventManager 클래스 헤더파일 **

#pragma once

class EventManager 
{
public:
    EventManager();
    int GenerateEvent();
};

// ** EventManager 클래스 소스파일 **

#include "EventManager.h"
#include <iostream>
#include <ctime>

EventManager::EventManager() 
{
    srand(static_cast<unsigned int>(time(NULL)));
}

int EventManager::GenerateEvent() 
{
    int probability = rand() % 100;

    if (probability < 10) 
    {
        std::cout << "캐스터 : 아차! 장애물에 걸려 미끄러집니다. (-2)" << std::endl;
        return -2;
    }
    else if (probability < 30) 
    {
        std::cout << "캐스터 : 부스터 가동!! 엄청난 속도입니다! (+10)" << std::endl;
        return 10;
    }
    else 
    {
        std::cout << "캐스터 : 속도를 높입니다! (+6)" << std::endl;
        return 6;
    }
}

// ** GameManager 클래스 헤더파일 **

#pragma once
#include "RacingCar.h"
#include "EventManager.h"

class GameManager 
{
private:
    RacingCar* player;
    EventManager eventMgr;
    int trackLength;

public:
    GameManager(RacingCar* car, int length);
    void StartReady();
    void Run();
};

// ** GameManager 클래스 소스파일 **

#include "GameManager.h"
#include <iostream>
#include <Windows.h>
#include <conio.h>

GameManager::GameManager(RacingCar* car, int length)
    : player(car), trackLength(length) {
}

void GameManager::StartReady() 
{
    std::cout << "========================================" << std::endl;
    std::cout << "레이싱 게임을 시작하려면 's'를 누르세요!" << std::endl;
    std::cout << "========================================" << std::endl;

    while (true) 
    {
        char input = _getch();
        if (input == 's' || input == 'S') 
        {
            std::cout << "\n게임을 시작합니다!" << std::endl;
            Sleep(1000);
            break;
        }
    }
}

void GameManager::Run() 
{
    while (true) 
    {
        player->Render();

        if (player->GetPosition() >= trackLength - 1) 
        {
            std::cout << "\n[축하합니다!] 결승선에 도착했습니다! 우승!" << std::endl;
            break;
        }

        int moveDist = eventMgr.GenerateEvent();
        player->Move(moveDist);

        Sleep(1500);
    }
}

3. 구현 과정

  1. 우선 RacingCar, EventManager, GameManager 세 가지를 클래스로 설정했습니다.
  2. 이 과정에서 따로 클래스를 헤더 파일소스 파일로 분류하여 헤더 파일에는 각각의 변수와 함수이름들을 설정하고 소스 파일에는 자세한 함수의 내용들을 정리해서 가독성을 높히고 효율성을 높여 보았습니다.

4. 개선 계획

  • 우선 차와 도로를 1개만 구현을 했습니다. 이것을 여러개로 늘려 구현을 하는 것이 목표입니다.

0개의 댓글