https://github.com/gyunam-park/CPP_TOY_PROJECT
▼ 실행화면
순환문, 조건문, 입출력 그리고... 클래스..?
CPP에서 순환 문과 조건문, 입출력을 배우고 피라미드를 만드는 과제를 진행했다.
▼ 과제로 내어진 이미지
처음에는 교수님이 수열을 사용해보는 것도 좋다고 해서 '피보나치수열'인가?! 하고 짜 봤는데 예시 이미지는 '*'이 하나씩 늘어나는 거라서 결괏값이 달랐다..
아무튼 처음에는 for문 두 개로 다 구현을 했다. 그냥 그대로 과제를 마무리하고 정리를 할까 하다가.. 그래도 교수님의 미션인데 놓칠 수 없지 싶어서 for문 하나로 만들어보기로 했다.
▼ 그래서 탄생한 내 인생 최고의 괴랄한 코드
int currStar = 0;
for (int col = 0; col < colMax;)
{
if (currStar < (col + 1))
{
printf("*");
currStar++;
continue;
}
if (currStar == (col + 1))
{
printf("\n");
col++;
currStar = 0;
}
}
한눈에 봐도 이게 무슨 코드인지 잘 안 들어온다. (홀리 지저스 크리스피 치킨)
교수님이 문제를 내주신 의도와 이건 전혀 다를 것이다.
for문 두 개 쓰는 예제가 단순히 발상과 코딩이 쉬워서 많은 게 아니라 일단 한 번에 보기 좋아서 인 것 같다.
변수 명도 내 나름 내가 이해하기 쉬운 방법대로 쓰긴 했는데 나중에 갈아엎을 때 한눈에 들어오지 않는 걸 발견했다.
괜스레 굳이 다른 방법으로 짜 보고 싶어서 끙끙댄 게 아까워서 다른 형태의 피라미드들도 구현했다.
▼ 의외로 추가적인 구현은 어렵지 않았다.
int currWhite = colMax;
int currStar = 0;
for (int col = 0; col < colMax;)
{
if (currWhite > 0)
{
printf(" ");
currWhite--;
continue;
}
if (currStar < (col + 1))
{
printf("*");
printf(" ");
currStar++;
continue;
}
if (currStar == (col + 1))
{
printf("\n");
col++;
currStar = 0;
currWhite = colMax - col;
}
}
그렇게 다시 한번 코드를 다 완료하고 진짜 마무리하려다가 'CPP로 객체지향적으로 짜면 어떨까?'란 생각이 들었다.
난 아직도 C의 절차 지향적인 코드가 더 익숙하다. 왠지 이번에 객체지향적으로 짜보는 삽질을 해봐야 이후의 과제들도 객체지향적으로 짜 볼 생각이 계속 들 꺼 같아서 구글만 믿고 다시 처음부터 작성을 시작했다.
▼ 그렇게 인터넷 보고 짜기 시작한 App 클래스
class App
{
public:
AppState appState;
i32 pyramidType;
i32 collumNum;
i32 inputNum;
bool isAppRunning;
public:
App();
virtual ~App();
void Init();
void Clear();
void Draw();
void Update();
void GetPyramidType();
void GetCollumNumber();
void GetNextChoice();
void Input(i32& contents);
};
처음 보는 변 수형 일 i32는 내가 common.h 파일에 재정의한 변 수형이다.
App의 구조는 Init, Clear, Draw, Update로 가지고 가다가 나중에 좀 더 프로그램답게 만들어보려고 입력 부분을 넣다 보니 너저분 해졌다.
좀 더 객체와 객체끼리 데이터를 주고받는 걸 이해해야 할 필요가 있다고 느꼈다.
클래스를 처음 써보다 보니 무작정 매번 새 클래스를 만들어서 사용했다.
▼ 인간의 욕심은 끝이 없고 내 코드는 끝났다(?).
void App::Draw()
{
switch (pyramidType)
{
case HALF:
{
HalfPyramid half(collumNum);
half.Draw();
}
break;
case INVERTED_HALF:
{
InvertedHalfPyramid iHalf(collumNum);
iHalf.Draw();
}
break;
case HOLLOW_INVERTD_HALF:
{
HollowInvertedHalfPyramid iHollowHalf(collumNum);
iHollowHalf.Draw();
}
break;
case FULL:
{
FullPyramid full(collumNum);
full.Draw();
}
break;
case INVERTED_FULL:
{
InvertedFullPyramid iFull(collumNum);
iFull.Draw();
}
break;
case HOLLOW_FULL:
{
HollowFullPyramid hollowFull(collumNum);
hollowFull.Draw();
}
break;
default:
break;
}
}
만약 게임이었다면 정말 비효율적이지 않았을까? 란 생각이 든다.
어차피 안에서 새로 메모리를 할당하는 게 없긴 해서 큰 문제는 안 될 테지만 내가 해보고 싶었던 건 Pyramid 객체를 하나 만들어서 가지고 있다가 필요에 따라서 교체하는 걸 생각했었다.
근데 그게 잘 안 돼서(내가 몰라서) 결국 맨땅 헤딩식으로 작성해야 했다.
C도 그 나름의 콤팩트함이 좋은데 CPP도 클래스를 사용하다 보니 재밌는 구석이 있다.
▼ State Machine 이란 걸 공부해야 할 필요를 느꼈다.
void App::Update()
{
while (isAppRunning == true)
{
switch (appState)
{
case AppState::IDLE:
appState = AppState::GET_TYPE;
break;
case AppState::GET_TYPE:
GetPyramidType();
break;
case AppState::GET_NUM:
GetCollumNumber();
break;
case AppState::RESULT:
Draw();
GetNextChoice();
break;
default:
break;
}
system("@cls||clear");
}
}
일단 나름 프로그램의 상태를 관리하려고 switch문을 사용했다.
나중에 수업이 끝나고 뒤적여보니 FSM과 같이 상태를 관리하는 기법들이 있었는데 실제 게임 개발할 때에도 큰 도움이 될 것 같아서 주말에 시간 내서 살펴봐야겠다.
'<TOY PROJECT> > CPP_CONSOLE' 카테고리의 다른 글
2. 간단한 탑뷰 게임 (0) | 2021.01.27 |
---|---|
1. [CPP]특수문자 타일 맵 생성기 (0) | 2021.01.13 |
댓글