4-3. 포인터 실습

Crat3 ㅣ 2023. 5. 11. 17:13

1. 포인터를 사용하지 않는 것과 포인터를 사용하는 것의 차이

포인터를 사용하지 않고 player를 구성하고, 포인터를 사용하여 monster를 구성해 본다.

struct StatInfo
{
    int hp; // 0
    int attack; // +4
    int defence; // +8
};

StatInfo라는 구조체 안에 hp, attack, defence 요소를 생성한다.

void EnterLobby();
StatInfo CreatePlayer();
void CreateMonster(StatInfo*); // 포인터를 사용하겠다고 선언

int main()
{
    EnterLobby();
    return 0;
}

이후 CreatePlayer는 구조체를 직접 이용한다고 선언하고, CreateMonster는 StatInfo 타입의 포인터를 사용하겠다고 선언한다.

void EnterLobby()
{
    cout << "로비에 입장하였습니다." << endl;

    StatInfo player;
    player.hp = 0xbbbbbbbb;
    player.attack = 0xbbbbbbbb;
    player.defence = 0xbbbbbbbb;
    // player의 각 요소가 이상한 값으로 대입되어있음.
    player = CreatePlayer();


    StatInfo monster;
    monster.hp = 0xbbbbbbbb;
    monster.attack = 0xbbbbbbbb;
    monster.defence = 0xbbbbbbbb;
    // monster의 각 요소가 이상한 값으로 대입되어있음.
    CreateMonster(&monster);
}

EnterLobby에서 플레이어(구조체 player)와 몬스터(구조체 monster)의 초기 스텟을 이상하게 변경하고 추후에 포인터를 사용하지 않고 / 사용하고 값을 변화시킨다.

StatInfo CreatePlayer()
{
    StatInfo ret;

    cout << "플레이어 생성" << endl;

    ret.hp = 100;
    ret.attack = 20;
    ret.defence = 2;

    return ret;
}

void CreateMonster(StatInfo* info) // info 라는 포인터를 생성
{
    cout << "몬스터 생성" << endl;
    info->hp = 40;
    info->attack = 8;
    info->defence = 2;
}

2. 코드 분석

(1) CreatePlayer 분석

스택 프레임 구조 :

[매개변수] [RET] [지역변수(temp(100, 10, 2), player(b, b, b))] -> [매개변수(&temp)] [RET] [지역변수(ret(100, 10, 2))]

이후 ret(100, 10, 2)의 값을 다시 temp(100, 10, 2)로 이동시키고

최종적으로 player의 값에 100, 10, 2를 대입하는 여러 번의 복사 과정을 일으킨다.

 

(2) CreateMonster 분석

스택 프레임 구조 :

[매개변수] [RET] [지역변수(monster(b, b, b))] -> [매개변수(&monster)] [RET] [지역변수]

monster의 주소에 직접 접근해서 각 요소를 직접 40, 8, 2로 변경한다.

 

(3) 구조체 사이의 복사

player = monster;

각 요소의 메모리를 찾아가서 일정 바이트만큼 이동시키는 동작이 3회 발생한다.

(최종적으로는 부하를 일으킬 수 있음)

 

3. 전투 파트

bool StartBattle(StatInfo* player, StatInfo* monster);

StartBattle이라는 함수를 선언하고, 구조체 StatInfo의 포인터를 두 개(플레이어, 몬스터) 만든다.

이때 Victory 변수를 이용해 승리 여부를 판단하게 한다.

Void EnterLobby()
    { //~~~
    bool victory = StartBattle(&player, &monster); // 포인터를 사용하기 위해서 주소값을 넣어줌
    if (victory)
        cout << "승리!" << endl;
    else
        cout << "패배!" << endl;
    }

이후 EnterBattle 함수에 전투를 구현한다.

bool StartBattle(StatInfo* player, StatInfo* monster)
{
    while (true)
    {
        int damage = player->attack - monster->defence;
        if (damage < 0)
            damage = 0;

        monster->hp -= damage;
        if (monster->hp < 0)
            monster->hp = 0;

        cout << "몬스터 HP : " << monster->hp << endl;

        if (monster->hp == 0)
            return true;

        damage = monster->attack - player->defence;
        if (damage < 0)
            damage = 0;

        cout << "플레이어 HP : " << player->hp << endl;
        player->hp -= damage;
        if (player->hp < 0)
            player->hp = 0;

        if (player->hp == 0)
            return false;

    }
}

이처럼 pointer를 사용하여 해당 메모리의 값을 직접 수정할 수 있다.

'기초 C++ 스터디 > 예제' 카테고리의 다른 글

4-13. 문자열 수정하기  (0) 2023.05.23
4-12. Text RPG 만들기(2)  (0) 2023.05.23
4-8. 로또 번호 생성기  (0) 2023.05.22
3-6. Text RPG 만들기  (0) 2023.05.10
2-3. 예제(별 찍기, 구구단)  (0) 2023.05.04