목차
- 과제 개요
- 리팩토링 전 문제점
- 내가 만든 함수 목록
- 주요 함수 설명
- main() 함수 변화
- 실행 결과
- 전체 코드 또는 소스 파일 안내
- 느낀 점 및 어려웠던 점
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
과제 개요
이번 과제는 10주차에 작성한 던전 게임 프로그램을 함수 단위로 분리하여 리팩토링하는 과제이다.
기존에는 대부분의 기능이 main() 함수 안에 작성되어 있어 코드가 길고 수정하기 어려웠다. 따라서 맵 생성, 오브젝트 배치, 입력 처리, 이동 처리, 충돌 검사, 결과 출력 등의 기능을 각각 함수로 분리하였다.
이를 통해 프로그램의 구조를 더 이해하기 쉽게 만들었으며, 특정 기능을 수정하거나 추가할 때도 편리하도록 개선하였다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
리팩토링 전 문제점
리팩토링 전에는 던전 게임의 대부분 기능이 main() 함수 안에 작성되어 있었다. 맵 생성, 오브젝트 배치, 사용자 입력, 이동 처리, 벽 검사, 보물 획득, 포탈 이동, 게임 종료 처리 등이 모두 한 곳에 모여 있어 코드가 길고 복잡하였다.
또한 특정 기능을 수정하려고 해도 main() 함수 내부에서 관련 코드를 직접 찾아야 했기 때문에 가독성이 떨어지고 유지보수가 어려웠다.
이를 개선하기 위해 기능별로 함수를 분리하여 코드의 역할을 명확하게 구분하였고, main() 함수는 전체 게임의 흐름만 담당하도록 리팩토링하였다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
내가 만든 함수 목록
| 함수 이름 | 반환형 | 매개변수 | 역할 | |
| 1 | initMap | void | map | 맵 생성 및 벽 배치 |
| 2 | placeObjects | void | map | 보물, 몬스터, 포탈 배치 |
| 3 | printTitle | void | score, turn, pX, pY | 게임 제목 및 상태 출력 |
| 4 | printMap | void | map, pY, pX | 던전 맵 출력 |
| 5 | inputCommand | char | 없음 | 사용자 이동 입력 |
| 6 | movePlayer | void | key, pY, pX, nY, nX | 플레이어 이동 위치 계산 |
| 7 | checkWall | int | map, nY, nX | 이동 위치가 벽인지 확인 |
| 8 | checkMonster | int | map, nY, nX | 몬스터 여부 확인 |
| 9 | updateScore | void | map, nY, nX, score | 보물 획득 시 점수 증가 |
| 10 | warpPortal | void | nY, nX | 포탈 이동 처리 |
| 11 | printResult | void | score, turn, clear | 게임 결과 출력 |
| 12 | checkInput | int | key | 입력값 유효성 검사 |
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
주요 함수 설명
1. 함수 이름 : movePlayer
역할 : 사용자가 입력한 방향에 따라 다음 이동 위치를 계산한다.
매개변수 :
- key : 사용자가 입력한 이동 키
- pY, pX : 현재 플레이어 위치
- nY, nX : 이동 후 위치를 저장할 변수
반환값 : 없음(void)
이 함수를 만든 이유 :
- 코드가 길어지고 가독성이 떨어지기 때문에 별도의 이동 기능 함수로 분리하여 이동 위치 계산만 담당하도록 하였다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
2. 함수 이름 : updateScore
역할 : 플레이어가 보물을 획득했을 때 점수를 증가시킨다.
매개변수 :
- map : 던전 맵 배열
- nY, nX : 플레이어가 이동한 위치
- score : 현재 점수
반환값 : 없음(void)
이 함수를 만든 이유 :
- 보물을 획득했을 때 점수를 증가시키고 보물을 맵에서 제거하는 기능을 한 곳에서 처리하기 위해 만들었다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
3. 함수 이름 : warpPortal
역할 : 플레이어가 포탈에 도착했을 때 다른 위치로 이동시킨다.
매개변수 :
- nY, nX : 플레이어의 이동 위치
반환값 : 없음(void)
이 함수를 만든 이유 :
- main() 함수의 복잡도를 줄이고 기능별 역할을 명확하게 구분하기 위해 만들었다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
main() 함수 변화
- 리팩토링 전
// ==========================================
// 1. 맵 초기화
// ==========================================
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
map[i][j] = '.';
}
}
// ==========================================
// 2. 바깥 벽 만들기
// ==========================================
for (i = 0; i < ROWS; i++) {
map[i][0] = '#';
map[i][COLS - 1] = '#';
}
for (j = 0; j < COLS; j++) {
map[0][j] = '#';
map[ROWS - 1][j] = '#';
}
// ==========================================
// 3. 내부 벽 만들기 (좌측 상단을 아예 가두는 벽 설계)
// ==========================================
// 좌측 상단을 완전히 밀봉하는 가로벽과 세로벽
for (j = 1; j < 14; j++) {
map[5][j] = '#'; // 5행을 가로지르는 가로벽
}
for (i = 1; i < 6; i++) {
map[i][14] = '#'; // 14열을 가로지르는 세로벽
}
// 기존 나머지 구역 벽들도 조화롭게 배치
for (j = 14; j < 25; j++) {
map[8][j] = '#';
}
for (i = 6; i < 13; i++) {
map[i][6] = '#';
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
- 리팩토링 후
//맵 생성 및 벽 배치
initMap(map);
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
실행 결과
- 게임 시작 화면

- 게임 진행 중 화면

- 게임 종료 화면

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
핵심 코드
1. movePlayer() 함수
void movePlayer(char key, int pY, int pX,
int* nY, int* nX) {
*nY = pY;
*nX = pX;
switch (key) {
case 'w':
case 'W':
(*nY)--;
break;
case 's':
case 'S':
(*nY)++;
break;
case 'a':
case 'A':
(*nX)--;
break;
case 'd':
case 'D':
(*nX)++;
break;
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
2. updateScore() 함수
void updateScore(char map[ROWS][COLS],
int nY, int nX,
int* score) {
if (map[nY][nX] == 'T') {
*score += 10;
map[nY][nX] = '.';
Beep(1000, 80);
Beep(1200, 80);
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
3. warpPortal() 함수
void warpPortal(int* nY, int* nX) {
if (*nY == 13 && *nX == 2) {
*nY = 2;
*nX = 11;
Beep(800, 150);
}
else if (*nY == 2 && *nX == 12) {
*nY = 13;
*nX = 3;
Beep(800, 150);
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
느낀 점 및 어려웠던 점
- 느낀점
함수 단위로 기능을 분리하면서 코드의 가독성이 향상되었고, 프로그램을 단계적으로 설계하는 방법을 익힐 수 있어서 좋았다.
- 함수로 분리하면서 가장 헷갈렸던 부분은 무엇인가?
함수로 분리하면서 가장 헷갈렸던 부분은 플레이어 위치와 점수처럼 변경되는 데이터를 함수 간에 전달하는 과정이었다. 포인터를 사용해서 함수 내부에서 변경한 값이 main() 함수에도 적용되도록 만들 수 있다는 점을 이해하게 되었다.
- main() 함수가 리팩토링 전보다 어떻게 달라졌는가?
리팩토링 전에는 대부분의 기능이 main() 함수 안에 작성되어 있어 코드가 길고 복잡했다. 리팩토링 후에는 기능별로 함수를 분리하여 main() 함수가 게임의 전체 흐름만 담당하도록 개선되었다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ