강께르의 개발일지

[C++] 몬스터와 일대일 턴제 전투 게임_구조체로 수정 본문

연습

[C++] 몬스터와 일대일 턴제 전투 게임_구조체로 수정

강께르 2021. 6. 12. 23:53

1. 이것은 무엇인가?

 이 게임은 이전에 만들었던 몬스터와 일대일 턴제 전투 게임과 내용이 거의 다를 것이 없다. 다른 부분을 짚자면 기존 한 파일 내에 기본 자료형으로 구성되었던 것을 구조체로 수정해서 만들었다는 것이다. 수정하는 김에 한 파일에 몰아넣어 있어 가독성이 떨어지는 점을 고려해 분할 파일로 코드를 보기 좋게 바꾸려고 시도했다. 그리고 코드를 좀 더 분할하여 함수화하는 방향으로 가독성 좋게 보이는 방안을 고민해보았다.

 

2. 새로 알게 된 점

- 객체 지향 프로그래밍의 장점을 어느 정도 알 것 같다. 기존의 코드에서는 코드 내에서 연관성이 있는 함수들이어도 실제로 묶어주는 게 없이 제각기 선언되어 있어 코드를 짜는 본인도 간혹 이해하기 힘들 때가 있었다. 그런데 구조체로 연관 있는 변수를 멤버 변수로 선언하고 그와 관련된 함수를 멤버 함수로 정리하니 연관성 있는 것들은 한 구조체로 모이니 이해하기가 좋다는 것을 느꼈다. 하지만 대체적인 코딩 스타일을 듣자하니, 구조체에 멤버변수만 넣고 멤버함수를 넣는 일은 지양한다고 한다. 기억해두자.

- 데이터 관리가 용이한 것 같다. 두 개 이상의 연관 있는 매개변수를 넘기고자 할 때, 두 변수에 대한 매개변수를 선언해주는 불편함이 있는데 그것을 구조체의 멤버변수로 넣어 구조체 변수 자체를 매개변수로 넘겨줘 프로그래밍하는 본인 입장에서는 구조체 하나만 잘 신경쓰면 된다는 생각이 들었다. 이는 클래스를 배우면 이어질 것 같다.

- 분할 파일로 프로그래밍하는 것은 정말 좋은 것 같다. 한 파일 내에 500줄 좀 되는 코드가 구조체마다 관련 있는 파일로 모으고 헤더 파일 하나 만들고 메인 함수에 함수화된 코드를 집어 넣으니 메인 함수가 정말 직관적이고 이해되는 코드로 변한 것 같다.

- 그리고 구조체가 클래스의 특징을 어느정도 가지고 있다는 것에 놀랐다. 상속이 되거나... 그런 점들 말이다.

 

3. 코드

 3-1. header.h

- include, enum, struct, 함수 원형들을 이 파일에다가 작성하였다.

- Character 구조체는 Human 구조체와 Monster 구조체를 상속해줄 구조체이다. 두 하위 구조체가 공통적으로 가지고 있는 체력, 마나, 공격력, 치명타율, 회피율이라는 것을 가지고 있고, 초기화 역할을 해줄 SetStat()과 공격이 적중하면 공격력만큼 매개변수 Character의 체력을 감소시킬 BasicAtk()와 공격력을 배로 들어가게 하지만 명중률은 낮은 PowerAtk() 멤버 함수가 있다.

- Human 구조체와 Monster 구조체는 Character 구조체를 상속받아 그 기능을 확장하고 있다. 각자 const로 선언된 문자 배열이 있다. 그것들은 각자 다른 스킬명이 들어있는 문자 배열이다. 그리고 각 구조체는 서로 차별점을 두기 위해서 두 함수를 두었다.

- Human 구조체는 명중률은 높지만 공격력이 낮은 BottomAtk()와 감소된 체력을 다시 증가시키는 Heal()이라는 함수가 있다. Monster 구조체는 적중하기만 하면 정말 큰 데미지를 줄 수 있지만 치명타율도 낮고 명중률도 극도로 낮은 DashAtk()과 적의 회피율을 낮추는 Howl()이라는 함수가 있다.

- GameManager 구조체는 콘솔을 조작하거나, 사용자의 입력에 대한 처리를 하거나, 상황에 맞는 출력을 할 수 있게끔 관련 함수를 모아놓은 구조체이다. 게임의 종료 조건문에 사용될 m_isPlayerAlive, m_isMonsterAlive, m_isplay 변수가 있고, 플레이어의 선택 입력을 담을 m_playerChooseNum과 컴퓨터의 무작위 숫자를 선택이라고 가정하고 저장할 m_computerChooseNum이 있다.

- SetConsoleView()는 콘솔창의 크기를 출력할 텍스트들의 크기에 맞게끔 조정하며, 제목줄에 타이틀이 출력할 수 있도록 설정해놓는다.

- ShowStartText()는 cout만을 이용해서 프롤로그에 관련된 스토리 설정을 텍스트로 출력해주는 역할을 한다.

- ShowStat()는 매개변수로 들어올 구조체의 종류에 따라서 그들의 변수를 정보로 사용자에게 알려줄 역할을 한다. 그리고 이 ShowStat()는 ShowAll()에 의해서 두 구조체의 정보를 텍스트 출력으로 한꺼번에 제공할 것이다.

- ChoosePlayerNum()은 선택과 관련된 출력문을 제공하고 출력문을 보고 판단한 사용자가 한 입력을 결정하면 그 결정된 값을 m_playerChooseNum에 저장한다.

- 컴퓨터의 선택이라고 가정할 무작위 값은 저 아래에 있는 SetRandomNum()이다. 이 값의 반환값으로 무작위 값이 나올텐데 그것을 m_computerChooseNum에 저장할 것이다.

- 선택에 대한 값이 정해지면 함수 오버로딩이 된 각각의 함수를 호출할 것이다. CharacterAction()은 첫번째 매개변수로 들어온 구조체의 선택에 관련된 값에 따라 두번째 매개변수로 들어온 구조체의 변수에 영향을 줄 함수이다.

- CheckGameover()은 매개변수로 받은 구조체 변수의 값에 따라 GameManager의 멤버 변수인 isplay를 true로 둘지 false로 둘지 결정하여 게임 종료 조건을 고려하는 함수이다.

- ShowEndingText()는 멤버 변수 m_isPlayerAlive와 m_isMonsterAlive의 값에 따라 ShowDrawText(), ShowWinText(), ShowLoseText()를 출력할지 고려하는 함수이다.

- IsCorrectPercent()는 치명타율, 회피율과 같은 확률값이 성공했는지, 실패했는지 판단하는 함수이다.

- IsDead()는 매개변수로 받은 체력 관련 변수의 값이 1 미만이면 죽었다는 의미로 판단해줄 함수이다.

- 이것으로 프로그램 전반으로 쓰이는 모든 함수를 간략히 설명하였다. 다음은 간략하게 코드만 보여주면서 넘어가겠다.

#ifndef __BATTLE_H__
#define __BATTLE_H__

#include<iostream>
#include<Windows.h>
#include<ctime>

using namespace std;

enum STAT {
	HP,
	MP,
	ATK,
	CRI,
	EVD
};

enum SKILL {
	BAS = 1,
	SK1,
	SK2,
	SK3
};

struct Character
{
	int m_healthPoint;
	int m_manaPoint;
	int m_attackPoint;
	int m_criticalRate;
	int m_evadeRate;

	void SetStat(int*);
	void BasicAtk(Character&);
	void PowerAtk(Character&);
};

struct Human : Character
{
	const char* m_skill[4] = { "베기", "강타", "하단베기", "회복" };

	void BottomAtk(Character&);
	void Heal(void);
};

struct Monster : Character
{
	const char* m_skill[4] = { "둔기 휘두르기", "흉포한 일격", "돌진", "괴성" };

	void DashAtk(Character&);
	void Howl(Character&);
};

struct GameManager
{
	bool m_isPlayerAlive = true;
	bool m_isMonsterAlive = true;
	bool m_isPlay = true;

	int m_playerChooseNum = -1;
	int m_orcChooseNum = -1;	

	void SetConsoleView(void);

	void ShowStartText(void);

	void ShowAll(const Human player, const Monster monster);
	void ShowStats(const Human player, const char* str);
	void ShowStats(const Monster monster, const char* str);

	void ChoosePlayerNum(Human);
	void CharacterAction(Human&, Monster&);
	void CharacterAction(Monster&, Human&);

	void CheckGameover(Human, Monster);

	void ShowEndingText(Human&, Monster&);
	void ShowDrawText(void);
	void ShowWinText(void);
	void ShowLoseText(void);
};

bool IsCorrectPercent(int);
bool IsDead(int);
int SetRandomNum(void);

#endif

3-2. CharacterFunc.cpp

#include"header.h"

void Character::SetStat(int* stat)
{
	m_healthPoint = stat[STAT::HP];
	m_manaPoint = stat[STAT::MP];
	m_attackPoint = stat[STAT::ATK];
	m_criticalRate = stat[STAT::CRI];
	m_evadeRate = stat[STAT::EVD];
}

// 일반 공격
void Character::BasicAtk(Character& enemy)
{
	srand((unsigned int)time(NULL));
	bool isCrit = IsCorrectPercent(m_criticalRate);
	bool isEvd = IsCorrectPercent(enemy.m_evadeRate);
	int atkPoint;

	if (!isEvd)
	{
		if (isCrit)
		{
			cout << "치명적인 공격!!!" << endl;
			atkPoint = m_attackPoint * 2;
		}
		else
			atkPoint = m_attackPoint;
		enemy.m_healthPoint -= atkPoint;
		cout << atkPoint << " 데미지를 주었다!" << endl;
	}
	else
	{
		cout << "공격을 했으나" << endl;
		cout << "재빠르게 피했다!" << endl;
	}
}

// 강한 공격(강타, 흉포한 일격) / 크리 4배 데미지, 일반 2배 데미지
// 하지만 상대방의 회피율을 2배로 하여 명중률이 1/2로 감소한 효과
void Character::PowerAtk(Character& enemy)
{
	srand((unsigned int)time(NULL));
	bool isCrit = IsCorrectPercent(m_criticalRate);
	bool isEvd = IsCorrectPercent((enemy.m_evadeRate * 2) % 100);
	int atkPoint;

	if (!isEvd)
	{
		if (isCrit)
		{
			cout << "치명적인 공격!!!" << endl;
			atkPoint = m_attackPoint * 4;
		}
		else
			atkPoint = m_attackPoint * 2;
		enemy.m_healthPoint -= atkPoint;
		cout << atkPoint << " 데미지를 주었다!" << endl;
	}
	else
	{
		cout << "강하게 무기를 휘둘렀으나" << endl;
		cout << "가까스로 피했다!" << endl;
	}
}

3-3. HumanFunc.cpp

#include"header.h"

// 플레이어의 하단 공격 / 치명율이 1/2이지만 적 회피율도 1/2
// 명중률이 2배이지만 데미지도 1/2 확정적인 데미지용으로 사용
void Human::BottomAtk(Character& enemy)
{
	srand((unsigned int)time(NULL));
	bool isCrit = IsCorrectPercent(m_criticalRate / 2);
	bool isEvd = IsCorrectPercent(enemy.m_evadeRate / 2);
	int atkPoint;

	if (!isEvd)
	{
		if (isCrit)
		{
			cout << "치명적인 공격!!!" << endl;
			atkPoint = m_attackPoint;
		}
		else
			atkPoint = m_attackPoint / 2;
		enemy.m_healthPoint -= atkPoint;
		cout << atkPoint << " 데미지를 주었다!" << endl;
	}
	else
	{
		cout << "공격을 했으나" << endl;
		cout << "육중한 몸을 던져 피했다.!" << endl;
	}
}

// 플레이어의 회복
// 따로 회복계수로 healStat과 실패확률로 10을 부여함.
// 치명율도 적용하여 대량으로 회복도 가능하게 만듦
void Human::Heal()
{
	srand((unsigned int)time(NULL));
	const int healStat = 3;
	bool isCrit = IsCorrectPercent(m_criticalRate);
	bool isFail = IsCorrectPercent(10);
	int healPoint;
	if (m_healthPoint == 20)
		cout << "하지만 지금 다친 곳이 없다." << endl;
	else if (!isFail)
	{
		if (isCrit)
		{
			cout << "상당한 효과의 치유!!!" << endl;
			healPoint = healStat * 3;
		}
		else
			healPoint = healStat;
		m_healthPoint += healPoint;
		if (m_healthPoint >= 20)
			m_healthPoint = 20;
		cout << healPoint << " 만큼 치유하였다." << endl;
	}
	else
	{
		cout << "치유하려 했으나" << endl;
		cout << "별 효과가 없다..." << endl;
	}
}

3-4. MonsterFunc.cpp

#include"header.h"

// 오크의 돌진 공격
// 플레이어의 회피율을 3배 올려 명중하기 힘들게 만들지만
// 데미지는 기본 데미지의 4배로 들어가 일단 적중하면 치명타
void Monster::DashAtk(Character& enemy)
{
	srand((unsigned int)time(NULL));
	bool isCrit = IsCorrectPercent(m_criticalRate);
	bool isEvd = IsCorrectPercent((enemy.m_evadeRate * 3) % 100);
	int atkPoint;

	if (!isEvd)
	{
		if (isCrit)
		{
			cout << "치명적인 돌진 공격!!!" << endl;
			atkPoint = m_attackPoint * 5;
		}
		else
			atkPoint = m_attackPoint * 4;
		enemy.m_healthPoint -= atkPoint;
		cout << atkPoint << " 데미지를 주었다!" << endl;
	}
	else
	{
		cout << "기세 좋게 달려왔으나" << endl;
		cout << "옆으로 굴러 피했다!" << endl;
	}
}

// 오크의 괴성 공격
// 회피 감소 계수 reduceEvd를 선언
// 그에 따라서 치명율이나 일반 성공 시 플레이어의
// 회피율을 감소시킨다.
void Monster::Howl(Character& enemy)
{
	bool isCrit = IsCorrectPercent(m_criticalRate);
	bool isFail = IsCorrectPercent(enemy.m_evadeRate);
	const int reduceEvd = 5;
	int atkPoint;
	if (enemy.m_evadeRate < 1)
		cout << "더 이상 낮출 회피율이 없다." << endl;
	else if (!isFail)
	{
		if (isCrit)
		{
			cout << "상당히 듣기 싫은 괴성!" << endl;
			atkPoint = reduceEvd * 2;
		}
		else
			atkPoint = reduceEvd;
		enemy.m_evadeRate += atkPoint;
		cout << atkPoint << " 만큼 회피율이 감소했다." << endl;
	}
	else
	{
		cout << "뭐라 꽥꽥거리는데" << endl;
		cout << "거슬리지는 않다..." << endl;
	}
}

3-5. GameManagerFunc.cpp

#include"header.h"
// 윈도우 콘솔창 크기 조절 및 타이틀
void GameManager::SetConsoleView()
{
	system("mode con:cols=65 lines=30");
	system("title Figthing with Orc");
}

void GameManager::ChoosePlayerNum(Human player)
{
	// 플레이어 행동 선택 관련 구문
	cout << endl;
	cout << "=================================================================" << endl;
	cout << "\t\t전사여, 자네의 행동을 고르시게." << endl;
	cout << "1." << player.m_skill[SKILL::BAS - 1] << "\t\t2." << player.m_skill[SKILL::SK1 - 1]
		<< "\t\t3." << player.m_skill[SKILL::SK2 - 1] << "\t\t4." << player.m_skill[SKILL::SK3 - 1] << endl;
	cout << "전사의 선택 : ";
	cin >> m_playerChooseNum;
	while (!(m_playerChooseNum > 0 && m_playerChooseNum < 5))
	{
		cout << "미안하지만, 전사는 그 행동을 모릅니다." << endl;
		cout << "전사의 선택 : ";
		cin >> m_playerChooseNum;
	}
	cout << "=================================================================" << endl;
}

void GameManager::CharacterAction(Human& player, Monster& orc)
{// 플레이어 행동 관련 구문
	switch (m_playerChooseNum)
	{
	case SKILL::BAS:
		cout << "전사의 " << player.m_skill[0] << " 공격!" << endl;
		Sleep(1000);
		cout << "오크에게 ";
		player.BasicAtk(orc);
		break;
	case SKILL::SK1:
		cout << "전사의 " << player.m_skill[1] << " 공격!" << endl;
		Sleep(1000);
		cout << "오크에게 ";
		player.PowerAtk(orc);
		break;
	case SKILL::SK2:
		cout << "전사의 " << player.m_skill[2] << " 공격!" << endl;
		Sleep(1000);
		cout << "오크에게 ";
		player.BottomAtk(orc);
		break;
	case SKILL::SK3:
		cout << "전사의 " << player.m_skill[3] << " 스킬!" << endl;

		Sleep(1000);
		player.Heal();
		break;
	}
	cout << endl;
	Sleep(1500);
}

void GameManager::CharacterAction(Monster& orc, Human& player)
{
	// 오크 행동 관련 구문
	switch (m_orcChooseNum)
	{
	case SKILL::BAS:
		cout << "오크의 " << orc.m_skill[0] << " 공격!" << endl;
		Sleep(1000);
		cout << "전사에게 ";
		orc.BasicAtk(player);
		break;
	case SKILL::SK1:
		cout << "오크의 " << orc.m_skill[1] << " 공격!" << endl;
		Sleep(1000);
		cout << "전사에게 ";
		orc.PowerAtk(player);
		break;
	case SKILL::SK2:
		cout << "오크의 " << orc.m_skill[2] << " 공격!" << endl;
		Sleep(1000);
		cout << "전사에게 ";
		orc.DashAtk(player);
		break;
	case SKILL::SK3:
		cout << "오크의 " << orc.m_skill[3] << " 공격!" << endl;
		Sleep(1000);
		cout << "전사에게 ";
		orc.Howl(player);
		break;
	}
}

void GameManager::CheckGameover(Human player, Monster orc)
{
	// 게임 오버 판단 구문
	m_isPlayerAlive = IsDead(player.m_healthPoint);
	m_isMonsterAlive = IsDead(orc.m_healthPoint);
	m_isPlay = m_isPlayerAlive && m_isMonsterAlive;
	Sleep(1500);
	system("cls");
}

void GameManager::ShowEndingText(Human& player, Monster& orc)
{
	// 게임 엔딩 문구 출력
	if ((!m_isPlayerAlive) && (!m_isMonsterAlive))
	{
		player.m_healthPoint = 0;
		orc.m_healthPoint = 0;
		ShowAll(player, orc);
		ShowDrawText();
	}
	else if (!m_isMonsterAlive)
	{
		orc.m_healthPoint = 0;
		ShowAll(player, orc);
		ShowWinText();
	}
	else if (!m_isPlayerAlive)
	{
		player.m_healthPoint = 0;
		ShowAll(player, orc);
		ShowLoseText();
	}
}

// 플레이어, 몬스터의 정보 출력
void GameManager::ShowAll(const Human player, const Monster monster)
{
	ShowStats(player, "전 사");
	ShowStats(monster, "오 크");
}

// 게임 시작 출력 문구
void GameManager::ShowStartText(void)
{
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "===============F====i====g====h====t===i===n===g=================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=====================w====i=====t====h===========================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "==================O==========r==========c========================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;
	cout << "=================================================================" << endl;

	Sleep(3000);
	system("cls");
	Sleep(2000);
	cout << "======================= 냄새 나는 구덩이 ========================" << endl << endl;
	Sleep(2000);
	cout << "냄새나는 구덩이에 발을 들여놓았다. 기분 나쁜 곳이다..." << endl << endl;
	Sleep(2000);
	cout << "찐득한 진흙이 내 군화를 뒤덮고," << endl << endl;
	Sleep(2000);
	cout << "끔찍한 악취는 내 정신을 놓게 만든다." << endl << endl;
	Sleep(3000);
	system("cls");
	cout << "======================= 냄새 나는 구덩이 ========================" << endl << endl;
	Sleep(2000);
	cout << "저기 뒤룩뒤룩 꿈틀거리는 뒷모습은 아마 산 자들이라면 " << endl << "증오하는 오크일 것이다. " << endl << endl;
	Sleep(2000);
	cout << "굳이 혐오스러운 저 괴물과 칼을 맞댈 필요는 없다. 조심히 지나가자." << endl << endl;
	Sleep(2000);
	system("cls");
	cout << "======================= 냄새 나는 구덩이 ========================" << endl << endl;
	Sleep(2000);
	cout << "저벅..." << endl;
	Sleep(2000);
	cout << "저벅..." << endl;
	Sleep(2000);
	cout << "저벅..." << endl << endl;
	Sleep(2000);
	cout << "첨벙!" << endl;
	Sleep(2000);
	system("cls");
	cout << "======================= 냄새 나는 구덩이 ========================" << endl << endl;
	Sleep(2000);
	cout << "이런 들켰다! 싸울 수 밖에 없다!" << endl;
	Sleep(2000);
	system("cls");
}

// 주어진 구조체 타입에 따라 함수 오버로딩 적용 / 출력내용은 비슷하지만 출력하고자하는 구조체 변수 타입이 다르다.
void GameManager::ShowStats(const Human player, const char* str)
{
	cout << "=================================================================" << endl;
	cout << "============================= " << str << " =============================" << endl;
	cout << "============================ H P : " << player.m_healthPoint << " ===========================" << endl;
	cout << "============================ M P : " << player.m_manaPoint << " ===========================" << endl;
	cout << "=================================================================" << endl;
}

void GameManager::ShowStats(const Monster monster, const char* str)
{
	cout << "=================================================================" << endl;
	cout << "============================= " << str << " =============================" << endl;
	cout << "============================ H P : " << monster.m_healthPoint << " ===========================" << endl;
	cout << "============================ M P : " << monster.m_manaPoint << " ===========================" << endl;
	cout << "=================================================================" << endl;
}

// 둘 다 동시에 체력을 잃었을 경우
void GameManager::ShowDrawText()
{
	Sleep(2000);
	cout << endl;
	cout << "\"혼자 가지는 않겠다!!! 비열한 오크!\"" << endl;
	Sleep(1000);
	cout << "전사의 칼을 타고 초록색 피가 전사의 손을 적십니다." << endl;
	Sleep(1000);
	cout << "전사도 자신의 가슴팍에 차가운 날붙이가 들어온 것을 느낍니다." << endl;
	Sleep(1000);
	cout << "치열하게 싸웠지만 장렬하게 두 생명은" << endl;
	Sleep(1000);
	cout << "더러운 진흙 속에 사라집니다..." << endl;
	Sleep(1000);
	cout << "Game Over..." << endl << endl;
	cout << "=================================================================" << endl;
}

// 몬스터가 체력이 없을 경우
void GameManager::ShowWinText()
{
	Sleep(2000);
	cout << endl;
	cout << "더러운 오크는 내게 상대도 안된다!" << endl;
	Sleep(1000);
	cout << "전사는 냄새 나는 구덩이, 그 속으로 천천히" << endl;
	Sleep(1000);
	cout << "더 깊숙이 발걸음을 옮겼다..." << endl;
	Sleep(1000);
	cout << "To be continue..." << endl << endl;
	cout << "=================================================================" << endl;
}

// 플레이어의 체력이 없을 경우
void GameManager::ShowLoseText()
{
	Sleep(2000);
	cout << endl;
	cout << "내 모험은 여기가 끝인 것 같네..." << endl;
	Sleep(1000);
	cout << "전사의 몸은 질척거리는 진흙 위로 떨어졌습니다." << endl;
	Sleep(1000);
	cout << "진흙은 마치 살아 있다는 듯, 점점 그 몸을 삼킵니다." << endl;
	Sleep(1000);
	cout << "아무도 그가 여기 있었다는 것을 모를 정도로..." << endl;
	Sleep(1000);
	cout << "Game Over..." << endl << endl;
	cout << "=================================================================" << endl;
}

3-6. MathFunc.cpp

- 수치 계산, 판단과 관련하여 모아놓은 함수를 이곳에 정의하였다.

#include"header.h"

// 일정 확률을 매개변수로 전달하면 그 확률에 들어맞는지 판단하는 함수
bool IsCorrectPercent(int val)
{
	return val > (rand() % 100);
}

// 체력이 0이면 false, 죽었다고 알리는 함수
bool IsDead(int hp)
{
	bool result = true;
	if (hp < 1)
		result = false;
	return result;
}

// 1부터 num까지의 값이 결정되는 함수
int SetRandomNum()
{
	int num = 4;
	return (rand() % num) + 1;
}

3-7. Main.cpp

#include "header.h"

int main(void)
{				
	GameManager gameManager;
	gameManager.SetConsoleView();

	Human player;
	int playerStat[] = { 20, 10, 5, 15, 20 };
	player.SetStat(playerStat);

	Monster orc;
	int orcStat[] = { 30, 10, 3, 11, 20 };
	orc.SetStat(orcStat);

	//ShowStartText();
	while (gameManager.m_isPlay)
	{
		gameManager.ShowAll(player, orc);				// 플레이어, 적 정보 그리기
		gameManager.ChoosePlayerNum(player);			// 플레이어 입력
		gameManager.CharacterAction(player, orc);		// 플레이어 입력에 따른 행동 계산, 출력
		gameManager.m_orcChooseNum = SetRandomNum();	// 컴퓨터 입력
		gameManager.CharacterAction(orc, player);		// 컴퓨터 입력에 따른 행동 계산, 출력
		gameManager.CheckGameover(player, orc);			// 게임오버인지 계산
		gameManager.ShowEndingText(player, orc);		// 게임오버일 경우 엔딩 텍스트 출력
	}
	return 0;
}

4. 결과

- 결과는 이전에 올린 결과물과 다를 것이 1도 없다. 단지 코드에 대한 변경점을 기술한 글이므로 이것으로 마무리하겠다.

'연습' 카테고리의 다른 글

[C++] 슬라이드 퍼즐 게임  (0) 2021.06.14
[C++] 빙고 게임_미완성  (0) 2021.06.13
[C++] 숫자야구 게임  (0) 2021.06.08
[C++] 몬스터와 일대일 턴제 전투 게임  (0) 2021.06.08
[C++] 숫자 맞추기 게임  (0) 2021.06.04