Contents
- 1. 소개글
- 2. 개발�리
- 3. Version 0.1 - 프로그램ì�˜ 가장 ì¶”ìƒ�ì � 단계
- 4. Version 0.2 - Refinement
- 5. Version 0.3 - Refinement More
- 6. Version 0.4 - Implementation : Input
- 7. Version 0.5 - Implementation : ScheduledWalk
- 8. Version 0.6 - Implementation : Output & ì „ì²´ì �
- 9. Test & 버그 분�
- 10. 최종 테스트들� 만족시키는 코드
- 11. 마무리 소스
1. 소개글 ¶
ë�°ë¸”ìŠ¤ìº í”„2002때 소개했었ë�˜ StructuredProgramming 기법ì�„ 처ì�Œë¶€í„° ë��까지 진행하는 모습ì�„ 보여드립니다. 중간ì—� 버그가 ë°œìƒ�í•˜ê³ , ê·¸ 버그를 ìˆ˜ì •í•œ 소스를 그대로 실어봅니다. 그대로 ë”°ë�¼í•´ë³´ì…”ë�„ 좋ì�„듯. 단, 중간 삽질과 컴파ì�¼ ì—�러ì—� ê²�먹지만 ì•Šìœ¼ì‹ ë‹¤ë©´. ^^;
Spec 과 Test Case 는 RandomWalk2 � 있습니다.
2. 개발ì›�리 ¶
StructuredProgramming 기법으로 StepwiseRefinement 하였습니다. ë¬¸ì œë¥¼ TopDown 스타ì�¼ë¡œ 계ì†� ìž¬ì •ì�˜í•˜ì—¬ 뼈대를 ë§Œë“ ë‹¤ì�Œ, Depth First (트리ì—�서 깊ì�´ ìš°ì„ ) 로 가장 ìž‘ì�€ 모듈들ì�„ ë¨¼ì € 하나하나 구현해 나갔습니다. 중반부터는 UnitTest 코드를 삽입하기를 시ë�„, 중후반부터는 UnitTest Code를 ë¨¼ì € ë§Œë“¤ê³ í”„ë¡œê·¸ëž¨ 코드를 나중ì—� 작성하였습니다.
3. Version 0.1 - 프로그램ì�˜ 가장 ì¶”ìƒ�ì � 단계 ¶
ë§� 그대로. ì „í˜•ì �ì�¸ '프로그램' 입니다. 'ìž…ë ¥ì�„ ë°›ê³ , 처리해서 ì¶œë ¥í•œë‹¤.' ë�¼ëŠ”;
~cpp
int main ()
{
Input ();
Process ();
Output ();
return 0;
}
void Input () {
}
void Process () {
}
void Output () {
}
Process () 는 그리 명확하지 ëª»í•˜ë‹¤ê³ ìƒ�ê°�, 약간 ë�” 구체ì �으로 ì�´ë¦„ì�„ 바꿨습니다.
~cpp
int main ()
{
Input ();
ScheduledWalk ();
Output ();
return 0;
}
void ScheduledWalk () {
}
4. Version 0.2 - Refinement ¶
위까진 프로그램ì�˜ 트리중 1ì°¨ ë ˆë²¨ì�´ê² ê³ , ì�´ë¥¼ 조금씩 ìž¬ì •ì�˜í•´ë‚˜ê°”습니다. 컴파ì�¼ ì—�러는 ê±°ì�˜ ë� 무시를..~ 어차피 뼈대ì�´ë¯€ë¡œ. 컴파ì�¼ ì—�러나 무한루프 등ì�´ ë¬¸ì œê°€ ë°œìƒ�하는 경우엔 ì�¼ë‹¨ void 형으로 리턴값ì�„ ì �거나 return false; ì‹�으로 채워넣습니다. ì�¼ë‹¨ì�€ 뼈를 잡는게 ë�” 중요하므로.
~cpp
void Input() {
InputBoardSize();
InputStartRoachPosition();
InputRoachJourney();
}
void InputBoardSize() {
}
void InputStartRoachPosition() {
}
void InputRoachJourney() {
}
void ScheduledWalk() {
while (!IsFinished()) {
Move();
}
}
BOOL IsFinished() {
return IsJourneyEnd() || IsAllBoardChecked();
}
void Move() {
}
void Output() {
OutputMoveCount();
OutputBoardStatus();
}
void OutputMoveCount() {
}
void OutputBoardStatus() {
}
5. Version 0.3 - Refinement More ¶
ì�´ì •ë�„까지 ì§„í–‰ë�˜ëŠ”ë�° 한 15ë¶„ì •ë�„ ê±¸ë ¸êµ°ìš”. 아마 연습ì�´ 충분하다면 10분내로ë�„ ê°€ëŠ¥í• ë“¯.~ì�´ 코드는 아무런 하는 ì�¼ì�´ 없으니까요.~
~cpp
typedef int BOOL;
void Input();
void InputBoardSize();
void InputStartRoachPosition();
void InputRoachJourney();
void ScheduledWalk();
BOOL IsFinished();
BOOL IsJourneyEnd();
BOOL IsAllBoardChecked();
void MoveNext();
void Output();
void OutputMoveCount();
void OutputBoardStatus();
int main()
{
Input();
ScheduledWalk();
Output();
return 0;
}
void Input() {
InputBoardSize();
InputStartRoachPosition();
InputRoachJourney();
}
void InputBoardSize() {
}
void InputStartRoachPosition() {
}
void InputRoachJourney() {
}
void ScheduledWalk() {
while (!IsFinished()) {
MoveNext();
}
}
BOOL IsFinished() {
return IsJourneyEnd() || IsAllBoardChecked();
}
BOOL IsJourneyEnd() {
return false;
}
BOOL IsAllBoardChecked() {
return false;
}
void MoveNext() {
}
void Output() {
OutputMoveCount();
OutputBoardStatus();
}
void OutputMoveCount() {
}
void OutputBoardStatus() {
}
여기까지가 지난번 ë�°ë¸”ìŠ¤ìº í”„2002 때 ê·¸ë ¸ì—ˆë�˜ HIPO 뼈대를 코드로 옮긴 것입니다.
ì�´ 답ì�´ 완벽한 답ì�€ 아니며, HIPO ì�´í›„ 바로 프로그램 완성까지ì�˜ 길ì—�는 약간 거리가 있습니다. (왜ëƒ�. ì�´ Top-Down Design ì�˜ 결과가 완벽하다ë�¼ê³ ë§�í• ìˆ˜ëŠ” 없으니까요. 하지만, ë¬¸ì œì™€ ì „ë°˜ì � 프로그램 ë””ìž�ì�¸, í�° 밑그림ì�„ ê·¸ë¦¬ê³ ì�´í•´í•˜ëŠ”ë�° ë�„움ì�„ 줌ì—�는 분명합니다. )
ì�´ 답ì�´ 완벽한 답ì�€ 아니며, HIPO ì�´í›„ 바로 프로그램 완성까지ì�˜ 길ì—�는 약간 거리가 있습니다. (왜ëƒ�. ì�´ Top-Down Design ì�˜ 결과가 완벽하다ë�¼ê³ ë§�í• ìˆ˜ëŠ” 없으니까요. 하지만, ë¬¸ì œì™€ ì „ë°˜ì � 프로그램 ë””ìž�ì�¸, í�° 밑그림ì�„ ê·¸ë¦¬ê³ ì�´í•´í•˜ëŠ”ë�° ë�„움ì�„ 줌ì—�는 분명합니다. )
(Hierarchy Input-Process-Output) � 경우엔 다�과 같습니다. (그림 첨부 필요)
6. Version 0.4 - Implementation : Input ¶
10분 휴� - 1시 55분까지. 커피 보충등등;
ì�´ì •ë�„ë©´ 처ì�Œì—� ìƒ�ê°�í•´ë‘” 뼈대가 ë‚˜ì™”ë‹¤ê³ ìƒ�ê°�ë�©ë‹ˆë‹¤. (즉, 추후 ë�” 세분화시켜서 나눌 수 있긴 하지만, ì�´ì •ë�„ì—�서ë�„ 바로 구현으로 들어가는ë�° 별 ë¬¸ì œê°€ ì—†ì�„ 것ì�´ë�¼ê³ ìƒ�ê°�ë� ì •ë�„)
ì�´ì •ë�„ë©´ 처ì�Œì—� ìƒ�ê°�í•´ë‘” 뼈대가 ë‚˜ì™”ë‹¤ê³ ìƒ�ê°�ë�©ë‹ˆë‹¤. (즉, 추후 ë�” 세분화시켜서 나눌 수 있긴 하지만, ì�´ì •ë�„ì—�서ë�„ 바로 구현으로 들어가는ë�° 별 ë¬¸ì œê°€ ì—†ì�„ 것ì�´ë�¼ê³ ìƒ�ê°�ë� ì •ë�„)
그럼. 하나씩 구현� 해 들어갑니다.
ì–´ë–¤ 함수 ë˜�는 모듈 부터 구현ì�„ 해야 í• ê¹Œ ê¶�리했었습니다. 어차피 ê°� 모듈부분ì—�ì„ ê·¸ ì�¸ìž�를 구체ì �으로 명시시키지 않았습니다. ì�´ì¯¤ì—�서 DFD를 ê·¸ë¦¬ê³ ë�°ì�´í„°ì�˜ í��름ì—� 대해 í‘œí˜„í• ìˆ˜ë�„ ìžˆê² ì§€ë§Œ, ì €ëŠ” ì�¼ë‹¨ 소스 ìž�ì²´ì—� ì´›ì �ì�„ 맞췄습니다. 그래서 필요하면 ì�¸ìž�를 하나씩 ë�” ì¶”ê°€í•˜ê³ , 필요없어졌다 ì‹¶ì�Œ ì�¸ìž�를 ì‚ì œí•˜ëŠ” ì‹�으로 ì ‘ê·¼í–ˆìŠµë‹ˆë‹¤. 그래서 따로 HIPO 다ì�´ì–´ê·¸ëž¨ì—� Argument 를 넘기는 부분ì�„ 표현해ë‘�ì§€ 않았습니다. (워낙 ìž�주 소스를 ê³ ì¹œ 관계로. 하지만, 시간ì�´ ë§Žì�´ 걸린 ì�¼ì�€ 아니였습니다.~)
구현 순서ì—� 대해서 ì›�ì¹™ì�´ 있으면 좋ì�„것ì�´ëž€ íŒ�단하ì—� 다ì�Œê³¼ ê°™ì�€ ì›�ì¹™ì�„ ì„¸ì› ìŠµë‹ˆë‹¤.
- 순차ì �으로 - 왼쪽 -> 오른쪽 순서로. 실행 순서ì—� ë”°ë�¼ 구현한다. (실행 순서와 ìƒ�관없ì�´ ë�…립ì �으로 따로 ìƒ�ê°�하여 êµ¬í˜„í• ìˆ˜ 있습니다. ì�´ëŠ” UnitTest 참조)
- Depth-Module First. -> 깊ì�´ê°€ 가장 깊ì�´ì—� 있는 것들ì�´ 쉬운 ë¬¸ì œì�¼ 것ì�´ë�¼ íŒ�단, 깊ì�´ê°€ 깊ì�€ 모듈부터 구현하기로 했습니다. (ì�¼ìž¥ì�¼ë‹¨ì�¸ë�°, ê·¸ ëŒ€ì‹ ìž˜ëª» ì ‘ê·¼í•˜ë©´ Bottom-Up ì�´ ë�˜ì–´ë²„릴 수ë�„ 있기 때문ì—�.. ì�´ 경우 해당 함수가 하는 ì�¼ì�„ 명확하게 해줄 필요가 ìžˆë‹¤ê³ ìƒ�ê°�ë�©ë‹ˆë‹¤. ì „ì²´ 구조 ë‚´ì—�서ì�˜ ì—í• ì�„ ìžŠì–´ì„ ì•ˆë�˜ê² ì£ .)
~cpp
void InputBoardSize() {
}
ì�´ 함수가 하는 ì�¼ì�€ ë§� 그대로 Board ì�˜ Size 를 Input. íŒ� í�¬ê¸°ë¥¼ ìž…ë ¥ë°›ëŠ” 부분입니다. scanf 나 cin 등으로 간단하게 êµ¬í˜„í• ìˆ˜ ìžˆê² ì£ .
~cpp
void InputBoardSize() {
int boardRow;
int boardCol;
scanf("%d%d", &boardRow, &boardCol);
printf ("%d, %d \n", boardRow, boardCol);
}
ì�´ 부분ì—� ëŒ€í•´ì„ ë‹¤ë¥¸ Visual C++ ì�„ ì—°ë’¤, 따로 êµ¬í˜„í•´ë³´ê³ ìž˜ ìž‘ë�™í•˜ë©´ 본 소스ì—� ë¶™ì�¼ 수 있습니다. ìž…ë ¥ì�´ 잘 받아지는군요. ì�´ ìž…ë ¥ì—� 대해서 ë�°ì�´í„°ë¥¼ ë„˜ê²¨ì£¼ê³ ë„˜ê²¨ì£¼ê³ í•´ì•¼ê² êµ°ìš”.
ìž…ë ¥ë�°ì�´í„°ë¥¼ 받아서 처리하는 방법ì—�는 ë‘�가지가 ìžˆê² ìŠµë‹ˆë‹¤. 하나는 리턴값ì�„ 넘겨주는 방법, 하나는 ì�¸ìž�로 해당 변수ì�˜ í�¬ì�¸í„° ë˜�는 ë ˆí�¼ëŸ°ìŠ¤ë¥¼ ë°›ì�€ë’¤, ê·¸ 변수ì�˜ ê°’ì�„ 변화시켜주는 방법. (scanf 함수가 그러한 방법ì�´ì§€ìš”.) ì—¬ê¸°ì„ ê°„ë‹¨í•˜ê²Œ 리턴값ì�„ 넘겨주는 방법ì�„ ì�´ìš©í–ˆìŠµë‹ˆë‹¤. int 형 ë‘�ê°œ 변수를 리턴하는 것ì�´ë�¼ë©´ 구조체를 ì�´ìš©í•˜ëŠ” 것ì�´ ë�” 간단하리ë�¼ëŠ” íŒ�단ì—�서입니다.
~cpp
typedef struct __IntegerPair { // return ì�„ 하기 위한 구조체 ì„ ì–¸
int n1;
int n2;
} IntPair;
IntPair InputBoardSize(); // void InputBoardSize() ì—�서 IntPair InputBoardSize() 로 리턴값ì�´ 바뀌었습니다. 어차피 처ì�Œì—� ë§Œë“ í”„ë¡œí† íƒ€ìž…ë“¤ì�€ ë§� 그대로 '뼈' ì�´ê¸°ì—�.
IntPair InputBoardSize() {
IntPair size;
int boardRow;
int boardCol;
scanf("%d%d", &boardRow, &boardCol);
size.n1 = boardRow;
size.n2 = boardCol;
0 return size;
}
리턴값� 잘 넘어오는지 테스트해볼까요?
~cpp
#include <stdio.h>
typedef int BOOL;
typedef struct __IntegerPair {
int n1;
int n2;
} IntPair;
IntPair InputBoardSize();
void Input();
IntPair InputBoardSize() {
IntPair size;
int boardRow;
int boardCol;
scanf("%d%d", &boardRow, &boardCol);
size.n1 = boardRow;
size.n2 = boardCol;
return size;
}
void Input() {
IntPair testReceiver;
testReceiver = InputBoardSize();
printf ("Board Size value : %d, %d \n", testReceiver.n1, testReceiver.n2);
}
Input ì—�서 테스트해본 ê²°ê³¼ ê°’ì�´ 잘 ì¶œë ¥ë�˜ëŠ”êµ°ìš”. 그럼, 계ì†�해서 Inputì�˜ 다른 함수들ì�¸ InputStartRoachPosition(), InputRoachJourney() ì—� 대해 계ì†� 구현ì�„ í•´ë³´ì£ .
~cpp
IntPair InputStartRoachPosition() {
IntPair position;
int startRow;
int startCol;
scanf("%d%d", &startRow, &startCol);
position.n1 = startRow;
position.n2 = startCol;
return position;
}
InputRoachJourney() 는 String 문ìž�ì—´ì�¸ 관계로 좀 다르게 구현했습니다. 아까 ë§�한, 메모리 í�¬ì�¸í„°ë¥¼ 넘겨서 ê°’ì�„ ì €ìž¥í•˜ëŠ” ë°©ì‹�ì—� ì†�합니다. ë°°ì—´ì�€ ë˜�다른 í�¬ì�¸í„°ì™€ 다름없기ì—�, ì�´ë ‡ê²Œ 쓸 수 있습니다.
~cpp
void InputRoachJourney(PSTR journey) {
scanf ("%s", journey);
}
사실 ì�´ 방법ì�€ 위험합니다. char [] ì�¼ journey ì�˜ 사ì�´ì¦ˆë¥¼ ëª¨ë¥´ê³ ìžˆê¸° 때문ì�´ì£ . ë§Œì�¼ journey ì—�서 ìž…ë ¥ë°›ì�€ ì—¬ì •ì�˜ í�¬ê¸°ê°€ í�´ 경우 메모리ì—�러를 ë°œìƒ�시킬 수 있습니다. 하지만, ì�¼ë‹¨ì�€ 성능ì�€ 따지지 ì•Šê³ '가장 간단하게 ë�Œì•„가는 소스' 를 ìƒ�ê°�하기 위해 그냥 ì €ë ‡ê²Œ 남겨둬봅니다. ì›�래ë�¼ë©´ ë°°ì—´ì�˜ 최대값보다 ë�” í�° ì—¬ì •ì�´ 나왔ì�„ 경우ì�˜ 처리 등ì�„ ìƒ�ê°�해야 합니다. 단, ì�´ ë¬¸ì œì—� ëŒ€í•´ì„ InputRoachJourney () 함수 내로 ì§€ì—화가 ì–´ëŠ�ì •ë�„ 가능합니다. 여기서는 Structured Programming ì‹�으로 ì ‘ê·¼í•˜ë ¤ëŠ” 것ì�´ 목ì �ì�´ì—¬ì„œ, 세부ì �ì�¸ ë¬¸ì œì—� 대해서는 좀 ë�œ ì‹ ê²½ì�¼ìŠµë‹ˆë‹¤.
Input 부분 Implementation 1차 완료� 모습� �러했습니다.
~cpp
#include <stdio.h>
typedef char* PSTR;
const int MAX_JOURNEY_LENGTH = 1000;
typedef struct __IntegerPair {
int n1;
int n2;
} IntPair;
void Input();
IntPair InputBoardSize();
IntPair InputStartRoachPosition();
void InputRoachJourney(PSTR journey);
void Input() {
IntPair testReceiver;
testReceiver = InputBoardSize();
printf ("Board Size value : %d, %d \n", testReceiver.n1, testReceiver.n2);
testReceiver = InputStartRoachPosition();
printf ("Start Position value : %d, %d \n", testReceiver.n1, testReceiver.n2);
char testJourney[MAX_JOURNEY_LENGTH]="";
InputRoachJourney(testJourney);
printf ("Journey : %s \n", testJourney);
}
IntPair InputBoardSize() {
IntPair size;
int boardRow;
int boardCol;
scanf("%d%d", &boardRow, &boardCol);
size.n1 = boardRow;
size.n2 = boardCol;
return size;
}
IntPair InputStartRoachPosition() {
IntPair position;
int startRow;
int startCol;
scanf("%d%d", &startRow, &startCol);
position.n1 = startRow;
position.n2 = startCol;
return position;
}
void InputRoachJourney(PSTR journey) {
scanf ("%s", journey);
}
현재 ì‹¤ì œ 구현부분ì�˜ 프로세스는 다ì�Œê³¼ 같습니다. ì�´ 작업들ì�´ ì–´ëŠ�ì •ë�„ 노가다작업화(?) ë�˜ì–´ê°€ëŠ” 모습ì�´ ë³´ì�¼ê²�니다.
1. êµ¬í˜„í•˜ë ¤ëŠ” 함수 ì„ íƒ�
2. 구현. 필요한 변수가 �길때마다 하나씩 ��로 넘겨받기.
3. return ê°’ì—� 대해 ì„¤ì •. 때ì—� ë”°ë�¼ 구조체ì�˜ ì„ ì–¸.
4. 함수 호출뒤 return 값� 대해서 printf나 cout 등으로 결과값� 확�해보기.
2. 구현. 필요한 변수가 �길때마다 하나씩 ��로 넘겨받기.
3. return ê°’ì—� 대해 ì„¤ì •. 때ì—� ë”°ë�¼ 구조체ì�˜ ì„ ì–¸.
4. 함수 호출뒤 return 값� 대해서 printf나 cout 등으로 결과값� 확�해보기.
다ì�Œì�€ Input 함수 안ì—�서 얻어낸 ë�°ì�´í„°ë“¤ì�„ main 함수까지 ë�Œì–´ì˜¬ë¦½ë‹ˆë‹¤. ì�´ì œ ScheduedWalk 모듈ì—� ìž…ë ¥ë�œ ë�°ì�´í„°ë¥¼ 보내줄 준비가 ë�˜ì—ˆìŠµë‹ˆë‹¤.
~cpp
#include <stdio.h>
typedef int BOOL;
typedef char* PSTR;
const int MAX_JOURNEY_LENGTH = 1000;
typedef struct __IntegerPair {
int n1;
int n2;
} IntPair;
typedef struct __InputDataStructure {
IntPair boardSize;
IntPair roachPosition;
char journey[MAX_JOURNEY_LENGTH];
} InputData;
InputData Input();
IntPair InputBoardSize();
IntPair InputStartRoachPosition();
void InputRoachJourney(PSTR journey);
int main()
{
InputData inputData;
inputData = Input();
// For Input() Testing....
printf ("Board Size value : %d, %d \n", inputData.boardSize.n1, inputData.boardSize.n2);
printf ("Start Position value : %d, %d \n", inputData.roachPosition.n1, inputData.roachPosition.n2);
printf ("Journey : %s \n", inputData.journey);
ScheduledWalk();
Output();
return 0;
}
InputData Input() {
InputData inputData;
inputData.boardSize = InputBoardSize();
inputData.roachPosition = InputStartRoachPosition();
InputRoachJourney(inputData.journey);
return inputData;
}
IntPair InputBoardSize() {
IntPair size;
int boardRow;
int boardCol;
scanf("%d%d", &boardRow, &boardCol);
size.n1 = boardRow;
size.n2 = boardCol;
return size;
}
IntPair InputStartRoachPosition() {
IntPair position;
int startRow;
int startCol;
scanf("%d%d", &startRow, &startCol);
position.n1 = startRow;
position.n2 = startCol;
return position;
}
void InputRoachJourney(PSTR journey) {
scanf ("%s", journey);
}
�로서 Input 부분� �단 완성했습니다.
7. Version 0.5 - Implementation : ScheduledWalk ¶
다ì�Œ 모듈 - ScheduledWalk() ê´€ë ¨. Depth First ì—� ìž…ê°�하여. ê·¸ë¦¬ê³ ì�´ì¯¤ì—�서 TestDrivenDevelopment 를 약간 가미해봅시다.
(ê´€ë ¨ 페ì�´ì§€ 참조, ë˜�는 TestFirstProgramming, UnitTest)
(ê´€ë ¨ 페ì�´ì§€ 참조, ë˜�는 TestFirstProgramming, UnitTest)
해당 함수 모듈ì�´ 완료ë�˜ì—ˆì�„ 것ì�´ë�¼ ê°€ì •í•˜ê³ ì½”ë“œë¥¼ 작성해봅니다. 여기서는 IsFinished() ì—� ì�¼ë‹¨ 주목. (가장 깊ì�€ 단계ì�¸ IsJourneyEnd 와 IsAllBoardChecked 를 실행해주는 부분ì�´ë¯€ë¡œ)
~cpp
BOOL IsFinished() {
// ì�¼ì¢…ì�˜ Test Code. 프로그램ì�´ 완료ë�˜ì—ˆë‹¤ê³ í–ˆì�„때 ì œê°€ ì›�하는 ìƒ�황입니다.
char journey = "111122222"; // ì—¬ì •ë�°ì�´í„°ë¥¼ '111122222' 를 받았다 ê°€ì •í•˜ê³
int currentPosition = 1; // 현재ì�˜ ì—¬ì •ì‹¤í–‰ 위치는 ë‘�번째(0,1,..) 즉, '1' 입니다. ì „ì²´ 사ì�´ì¦ˆëŠ” 9.
assert (IsJourneyEnd(journey, currentPosition) == false); // 즉, ì�´ 경우면 ì—¬ì •ì�€ ë��나지 않았ì�Œì�„ '단언' 합니다.
// return IsJourneyEnd() || IsAllBoardChecked();
return true;
}
BOOL IsJourneyEnd() { // 아� 구현 안했습니다.
return true;
}
BOOL IsAllBoardChecked() { // 아� 구현 안�.
return true;
}
실행해보면, assert 부분ì—�서 ì—�러가 ë‚ ê²�니다. 그러면서 assert 부분과 ê´€ë ¨í•œ 코드 ë�¼ì�¸ì�„ 표시해ì¤�니다. 즉, ì œê°€ ì›�하는 ìƒ�황ì�„ ê°€ì •í•˜ê³ Test 코드를 ë§Œë“ ë’¤, ê·¸ Test 를 í†µê³¼í• ë•Œê¹Œì§€ 코드를 작성하면 ë�˜ê² ì£ . 추후 ë”가가 ìž‘ë�™ì�´ ì�´ìƒ�하다ë�¼ê³ 한다면,
- ì�¼ë‹¨ 해당 ë¬¸ì œì�¼ 모듈ì�„ ì²´í�¬í•œë‹¤.
- Test Code 를 확�해본다.
- ì‹¤ì œ 함수 모듈ì�„ 확ì�¸í•´ë³¸ë‹¤.
코드를 작성합니다.
~cpp
BOOL IsJourneyEnd(PSTR journey, int currentPosition) {
return strlen(journey) <= (UINT)currentPosition;
}
테스트를 ì �ì°¨ ëŠ˜ë ¤ê°‘ë‹ˆë‹¤.
~cpp
BOOL IsFinished() {
char journey[MAX_JOURNEY_LENGTH] = "111122222";
int currentPosition = 1;
assert (IsJourneyEnd(journey, currentPosition) == false);
currentPosition = 9;
assert (IsJourneyEnd(journey, currentPosition) == false);
currentPosition = 10;
assert (IsJourneyEnd(journey, currentPosition) == true);
// return IsJourneyEnd() || IsAllBoardChecked();
return true;
}
IsAllBoardChecked ì—� 대해서ë�„ 테스트를 ë„£ì–´ì£¼ê³ , 구현ì�„ 합니다.
~cpp
BOOL IsFinished() {
/* ---------------- IsJourney Test Case ----------------
char journey[MAX_JOURNEY_LENGTH] = "111122222";
int currentPosition = 1;
assert (IsJourneyEnd(journey, currentPosition) == false);
currentPosition = 9;
assert (IsJourneyEnd(journey, currentPosition) == false);
currentPosition = 10;
assert (IsJourneyEnd(journey, currentPosition) == true);
---------------- IsJourney Test Case ---------------- */
/* ---------------- IsAllBoardChecked Test Case ----------------
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 1;
}
}
assert (IsAllBoardChecked(board, 10, 10) == true);
board[0] = 0;
assert (IsAllBoardChecked(board, 10, 10) == false);
---------------- IsAllBoardChecked Test Case ---------------- */
char journey[MAX_JOURNEY_LENGTH] = "111122222";
int currentPosition = 10; // for true condition
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 1;
}
}
int maxRow = 10;
int maxCol = 10;
return IsJourneyEnd(journey, currentPosition) || IsAllBoardChecked(board, maxRow, maxCol);
}
BOOL IsJourneyEnd(PSTR journey, int currentPosition) {
return strlen(journey) < (UINT)currentPosition;
}
BOOL IsAllBoardChecked(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
if (board[i*maxRow+j] <= 0) return false;
}
}
return true;
}
2시 34분중; ìž ì‹œ ì‚¬ì •ìƒ�ê¹€.
3시. 작업 재개.
MoveNext ì—� 대해서 ìž¬ì •ì�˜ë¥¼ 해봅시다.
~cpp
void MoveNext() {
GetMoveVector();
MoveRoach();
IncrementBoardBlockCount();
}
void GetMoveVector() {
}
void MoveRoach() {
}
void IncrementBoardBlockCount() {
}
Prototype 쪽 표현시 �으로 깊�를 주어봤습니다. 소스 스타�� 대해서는 �해하기 좋� 스타�로 표현�.~
~cpp
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef int BOOL;
typedef char* PSTR;
typedef unsigned int UINT;
const int MAX_JOURNEY_LENGTH = 1000;
typedef struct __IntegerPair {
int n1;
int n2;
} IntPair;
typedef struct __InputDataStructure {
IntPair boardSize;
IntPair roachPosition;
char journey[MAX_JOURNEY_LENGTH];
} InputData;
InputData Input();
IntPair InputBoardSize();
IntPair InputStartRoachPosition();
void InputRoachJourney(PSTR journey);
void ScheduledWalk();
BOOL IsFinished(PSTR journey, int currentPosition, int* board, int maxRow, int maxCol);
BOOL IsJourneyEnd(PSTR journey, int currentPosition);
BOOL IsAllBoardChecked(int* board, int maxRow, int maxCol);
void MoveNext();
void GetMoveVector();
void MoveRoach();
void IncrementBoardBlockCount();
void Output();
void OutputMoveCount();
void OutputBoardStatus();
.
.
.
� �후부터 해당 함수 구현� 대한 프로세스는 다�과 같습니다.
1. í�¬ê±°ë‚˜ ê·¸ 기능ì�´ ì• ë§¤ ë˜�는 모호한 함수/모듈ì—� 대해서 ìž¬ì •ì�˜ 하기.
2. 해당 모듈ì�´ 완성ë�˜ì—ˆë‹¤ëŠ” ê°€ì • 하ì—� Test Case 를 ìƒ�ê°�해보기.
3. Test Case 작성.
4. 구현. Test Case 통과 여부 확�하기.
5. Test Case 를 ëŠ˜ë ¤ë³´ê¸°. (ì�´ 사ì�´ì¦ˆì—� ë”°ë�¼ 구현ì�˜ 난ì�´ë�„ê°€ 있습니다. 테스트와 다ì�Œ 테스트 작성과ì�˜ 시간ì�´ 길어질수ë¡� ì–´ë µìŠµë‹ˆë‹¤. ê·¸ ë§Œí�¼ ìƒ�ê°�ì�„ ì¶”ìƒ�ì �으로 한다는 뜻ì�¼ 수 있으니까요.)
2. 해당 모듈ì�´ 완성ë�˜ì—ˆë‹¤ëŠ” ê°€ì • 하ì—� Test Case 를 ìƒ�ê°�해보기.
3. Test Case 작성.
4. 구현. Test Case 통과 여부 확�하기.
5. Test Case 를 ëŠ˜ë ¤ë³´ê¸°. (ì�´ 사ì�´ì¦ˆì—� ë”°ë�¼ 구현ì�˜ 난ì�´ë�„ê°€ 있습니다. 테스트와 다ì�Œ 테스트 작성과ì�˜ 시간ì�´ 길어질수ë¡� ì–´ë µìŠµë‹ˆë‹¤. ê·¸ ë§Œí�¼ ìƒ�ê°�ì�„ ì¶”ìƒ�ì �으로 한다는 뜻ì�¼ 수 있으니까요.)
GetMoveVector � 대해 구현합니다.
~cpp
void MoveNext() {
testGetMoveVector();
/*
GetMoveVector(journey, currnetPosition);
MoveRoach();
IncrementBoardBlockCount();
*/
}
IntPair GetMoveVector(char* journey, int currentPosition) {
IntPair moveVector;
// vector - row move vector, col move vector.
int MOVE_VECTOR_PAIR_ROW[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int MOVE_VECTOR_PAIR_COL[8] = { 0, 1, 1, 1, 0, -1, -1, -1};
int moveVectorPairIndex = journey[currentPosition] - '0';
moveVector.n1 = MOVE_VECTOR_PAIR_ROW[moveVectorPairIndex];
moveVector.n2 = MOVE_VECTOR_PAIR_COL[moveVectorPairIndex];
return moveVector;
}
void testGetMoveVector() {
char journey[MAX_JOURNEY_LENGTH] = "247";
IntPair nextMoveVector;
nextMoveVector = GetMoveVector(journey, 0);
assert (nextMoveVector.n1 == 0);
assert (nextMoveVector.n2 == 1);
nextMoveVector = GetMoveVector(journey, 1);
assert (nextMoveVector.n1 == 1);
assert (nextMoveVector.n2 == 0);
nextMoveVector = GetMoveVector(journey, 2);
assert (nextMoveVector.n1 == -1);
assert (nextMoveVector.n2 == -1);
}
MoveRoach � 대한 Test Case � 작성.
~cpp
void MoveRoach() {
}
void testMoveRoach() {
IntPair currentRoachPosition;
IntPair moveVector;
currentRoachPosition.n1 = 0;
currentRoachPosition.n2 = 0;
// case move type '2':
moveVector.n1 = 0;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 1);
// One More Time..~
moveVector.n1 = 0;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 2);
}
Test Case � 대해 만족하는 가장 간단한 MoveRoach 를 �단 구현해봅니다. 본래� Requirement � 경우 해당 �� 최대범위를 넘어가면
반대편으로 워프를 해야 하지만, ì�´ì—� 대해서 ì•„ì§� 구현ì�„ 하지 않으면 ë�˜ì£ . 추후 ì�´ì—� 대한 Test Case를 ìž‘ì„±í•˜ê³ êµ¬í˜„í•˜ë©´ ë�©ë‹ˆë‹¤.
반대편으로 워프를 해야 하지만, ì�´ì—� 대해서 ì•„ì§� 구현ì�„ 하지 않으면 ë�˜ì£ . 추후 ì�´ì—� 대한 Test Case를 ìž‘ì„±í•˜ê³ êµ¬í˜„í•˜ë©´ ë�©ë‹ˆë‹¤.
~cpp
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector) {
IntPair updatedRoachPosition;
updatedRoachPosition.n1 = currentRoachPosition.n1 + moveVector.n1;
updatedRoachPosition.n2 = currentRoachPosition.n2 + moveVector.n2;
return updatedRoachPosition;
}
ê·¸ë¦¬ê³ í•´ë‹¹ 테스트를 만족하는지 실행해봅니다.그러면 ì�´ì œ 아까 ê³ ë ¤í•˜ì§€ 않았ë�˜ 사í•ì�¸ íŒ�ì�˜ 범위를 넘겼ì�„ 때ì—� 대한 워프부분ì—� 대해 Test Case 를 추가해봅니다.
~cpp
void testMoveRoach() {
.
.
.
// Checking Boundary Warp.
int maxCol = 10;
int maxRow = 10;
currentRoachPosition.n1 = 9;
currentRoachPosition.n2 = 9;
moveVector.n1 = 1;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector, maxCol, maxRow);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 0);
}
비슷한 방법으로 IncrementBoardBlockCount 를 구현합니다.~cpp
void IncrementBoardBlockCount(int* board, IntPair roachPosition, int maxRow, int maxCol) {
assert (roachPosition.n1 < maxRow);
assert (roachPosition.n2 < maxCol);
board[roachPosition.n1*maxRow + roachPosition.n2]++;
}
void testIncrementBoardBlockCount() {
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 0;
}
}
IntPair currentRoachPosition;
currentRoachPosition.n1 = 1;
currentRoachPosition.n2 = 1;
IncrementBoardBlockCount(board, currentRoachPosition, 10, 10);
assert (board[1*10+1] == 1);
}
3시 52분부터 4시까지 휴�;
4시 5분. 재개~
4시 5분. 재개~
ì „ì²´ MoveNext ì—� 대해서 Test Case를 작성합니다. 그러면서 필요한 ì�¸ìž�들ì�„ ìƒ�ê°�í•´ë‚´ê³ , 채워갑니다. MoveNext ì—�서 필요한 ì�¸ìž�들ì�€ GetMoveVector 와 MoveRoach, IncrementBoardBlockCount ì—�서 필요한 ì�¸ìž�들ì�˜ ì´� ì§‘í•©ì�´ ë�©ë‹ˆë‹¤.
~cpp
IntPair MoveNext(IntPair currentRoachPosition, PSTR journey, int currentJourneyPosition, int* board, int maxRow, int maxCol) {
testGetMoveVector();
testMoveRoach();
testIncrementBoardBlockCount();
IntPair updatedRoachPosition;
/*
아� 구현 부분� 없습니다.
*/
return updatedRoachPosition;
}
void testMoveNext() {
IntPair currentRoachPosition;
char journey[] = "222";
int maxRow = 10;
int maxCol = 10;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[i*maxRow+j] = 0;
}
}
currentRoachPosition.n1 = 9;
currentRoachPosition.n2 = 9;
int currentJourneyPosition = 0;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 0);
assert (board[0*maxRow+0] == 1);
}
MoveNext 부분 test case 를 pass 하기 위해 ì‹¤ì œ 구현ì�„ 합니다. ì�´ë¯¸ 구현해둔 GetMoveVector, MoveRoach, IncrementBoardBlockCount 들ì�„ 조합하는 ì�¼ë§Œ 하면 ë�©ë‹ˆë‹¤.
~cpp
IntPair MoveNext(IntPair currentRoachPosition, PSTR journey, int currentJourneyPosition, int* board, int maxRow, int maxCol) {
testGetMoveVector();
testMoveRoach();
testIncrementBoardBlockCount();
IntPair updatedRoachPosition;
IntPair moveVector = GetMoveVector(journey, currentJourneyPosition);
updatedRoachPosition = MoveRoach(currentRoachPosition, moveVector, maxRow, maxCol);
IncrementBoardBlockCount(board, updatedRoachPosition, maxRow, maxCol);
return updatedRoachPosition;
}
void testMoveNext() {
IntPair currentRoachPosition;
char journey[] = "333";
int maxRow = 10;
int maxCol = 10;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[i*maxRow+j] = 0;
}
}
currentRoachPosition.n1 = 9;
currentRoachPosition.n2 = 9;
int currentJourneyPosition = 0;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 0);
assert (board[0*maxRow+0] == 1);
currentJourneyPosition = 1;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 1);
assert (currentRoachPosition.n2 == 1);
assert (board[1*maxRow+1] == 1);
currentJourneyPosition = 2;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 2);
assert (currentRoachPosition.n2 == 2);
assert (board[2*maxRow+2] == 1);
}
대ë§�ì�˜ ScheduledWalk (). 여기서 ìž ì‹œ 테스트ì—� 따른 구현ì�„ 했는ë�°ë�„ ì—�러가 나네요. 왜 그럴까?
{{{~cpp
int ScheduledWalk(int* board, int maxRow, int maxCol, IntPair startRoachPosition, PSTR journey) {
testIsFinished();
testMoveNext();
int currentJourneyPosition = 0;
IntPair currentRoachPosition = startRoachPosition;
int totalMoveCount = 0;
IncrementBoardBlockCount(board, currentRoachPosition, maxRow, maxCol);
while (!IsFinished(journey, currentJourneyPosition, board, maxRow, maxCol)) {
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
totalMoveCount++;
currentJourneyPosition++;
}
return totalMoveCount;
}
void testScheduledWalk() {
char journey[MAX_JOURNEY_LENGTH] = "22222"; // ì—¬ì •ì�„ '22222' 를 ë°›ì•˜ë‹¤ê³ ê°€ì •í–ˆìŠµë‹ˆë‹¤.
int maxCol = 10; // � 사�즈는 10, 10
int maxRow = 10;
IntPair startRoachPosition;
startRoachPosition.n1 = 0; // Roach � 시작 ��트는 0,0
startRoachPosition.n2 = 0;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[i*maxRow+j] = 0;
}
}
int totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey); // ì „ì²´ ì�´ë�™ 기대수는
printf ("total move count : %d \n", totalMoveCount);
assert (totalMoveCount == 5); // 5 ê°€ 나와야 합니다. ê·¼ë�° 여기까지 작성한 바로는 6ì�´ ë‚˜ì˜¤ì£ .
}
왜 그럴까요? 버그가 무엇ì�¸ê°€ë¥¼ ë¨¼ì € 파악해ë´�야 í•˜ê² ì£ .
1. ScheduledWalk �서� 오류는 totalMoveCount � 값� 다르다는 것�다.
2. totalMoveCount � 값� 다르다는 것� while 루프 조건� 틀리다는 뜻�다.
3. while 루프 조건� 틀리다는 뜻� IsFinished() 가 올바르지 않았다�는 뜻�다.
4. IsFinished() 가 잘못�었다는 뜻� IsJourneyEnd, IsAllBoardChecked 둘 중 하나 ��� 잘못�었다는 뜻�다.
하지만, 위ì�˜ 모듈들ì�€ Test Case를 다 만족ì�„ 시켜줬습니다. 그럼 Test Case ìž�체를 ì�˜ì‹¬í•´ë´�ì•¼ê² ì£ ?
{{{~cpp
void testIsJourney() {
char journey[MAX_JOURNEY_LENGTH] = "111122222";
int currentPosition = 1;
assert (IsJourneyEnd(journey, currentPosition) == false);
currentPosition = 9; // <---- ì „ì²´ ë°°ì—´ì�€ 9ê°œ. 0번부터 시작하므로 8번까지여야 함.
assert (IsJourneyEnd(journey, currentPosition) == false); // <--- ê³ ë¡œ ì�´ê±´ true!
currentPosition = 10;
assert (IsJourneyEnd(journey, currentPosition) == true);
}
}}}
ê·¸ë ‡ë‹¤ë©´, 틀린 ìƒ�ê°�ì�„ 맞다ë�¼ê³ ê°€ì •í•˜ê³ ë§Œë“¤ì–´ì§„ IsJourneyEnd ë˜�한 틀린 함수가 ë�˜ê² êµ°ìš”. ì�´ë¥¼ ìˆ˜ì •í•˜ê³ , 해당 소스ë�„ ìˆ˜ì •í•©ë‹ˆë‹¤. ê·¸ë¦¬ê³ ê³„ì†� 프로그램ì�„ ë�Œë ¤ë´…니다. ê·¸ë¦¬ê³ Test Case를 추가합니다.
{{{~cpp
void testScheduledWalk() {
char journey[MAX_JOURNEY_LENGTH] = "22222";
int maxCol = 10;
int maxRow = 10;
IntPair startRoachPosition;
startRoachPosition.n1 = 0;
startRoachPosition.n2 = 0;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[i*maxRow+j] = 0;
}
}
int totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey);
printf ("total move count : %d \n", totalMoveCount);
assert (totalMoveCount == 5);
assert (board[0*maxRow+0] == 1);
assert (board[0*maxRow+1] == 1);
assert (board[0*maxRow+2] == 1);
assert (board[0*maxRow+3] == 1);
assert (board[0*maxRow+4] == 1);
assert (board[0*maxRow+5] == 1);
}
}}}
=== Version 0.6 - Implementation : Output & ì „ì²´ì � ===
여기까지 완료�었다면 ScheduledWalk � 완료�군요. 그럼 Output � 간단하게 구현합니다.
ì•„ì§� Acceptance TestCase 를 거치지 않ì�€ 1ì°¨ 완료 ë²„ì „ì�€ 다ì�Œê³¼ 같습니다.
{{{~cpp
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef int BOOL;
typedef char* PSTR;
typedef unsigned int UINT;
const int MAX_JOURNEY_LENGTH = 1000;
typedef struct __IntegerPair {
int n1; // Row 와 관계�것들.
int n2; // Col 와 관계�것들.
} IntPair;
typedef struct __InputDataStructure {
IntPair boardSize;
IntPair roachPosition;
char journey[MAX_JOURNEY_LENGTH];
} InputData;
InputData Input();
IntPair InputBoardSize();
IntPair InputStartRoachPosition();
void InputRoachJourney(PSTR journey);
void testInput();
void InitializeArray(int* board, int maxRow, int maxCol);
int ScheduledWalk(int* board, int maxRow, int maxCol, IntPair startRoachPosition, PSTR journey);
BOOL IsFinished(PSTR journey, int currentPosition, int* board, int maxRow, int maxCol);
BOOL IsJourneyEnd(PSTR journey, int currentPosition);
BOOL IsAllBoardChecked(int* board, int maxRow, int maxCol);
void testIsJourney();
void testIsAllBoardCheck();
IntPair MoveNext(IntPair currentRoachPosition, PSTR journey, int currentJourneyPosition, int* board, int maxRow, int maxCol);
IntPair GetMoveVector(char* journey, int currentPosition);
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector, int maxRow, int maxCol);
void IncrementBoardBlockCount(int* board, IntPair roachPosition, int maxRow, int maxCol);
void testGetMoveVector();
void testMoveRoach();
void testIncrementBoardBlockCount();
void testIsFinished();
void testMoveNext();
void testScheduledWalk();
void Output(int totalMoveCount, int* board, int maxRow, int maxCol);
void OutputMoveCount(int totalMaxCount);
void OutputBoardStatus(int* board, int maxRow, int maxCol);
int main()
{
/* ------------- excute test code -------------
testInput();
testScheduledWalk();
------------- excute test code ------------- */
InputData inputData = Input();
int maxRow = inputData.boardSize.n1;
int maxCol = inputData.boardSize.n2;
int* board = new int[maxRow * maxCol];
InitializeArray(board, maxRow, maxCol);
IntPair startRoachPosition = inputData.roachPosition;
char journey[MAX_JOURNEY_LENGTH]="";
strcpy(journey, inputData.journey);
int totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey);
Output(totalMoveCount, board, maxRow, maxCol);
delete board;
return 0;
}
void InitializeArray(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[i*maxRow+j] = 0;
}
}
}
InputData Input() {
InputData inputData;
inputData.boardSize = InputBoardSize();
inputData.roachPosition = InputStartRoachPosition();
InputRoachJourney(inputData.journey);
InputEndCode();
return inputData;
}
void testInput() {
InputData inputData;
inputData = Input();
// For Input() Testing....
printf ("Board Size value : %d, %d \n", inputData.boardSize.n1, inputData.boardSize.n2);
printf ("Start Position value : %d, %d \n", inputData.roachPosition.n1, inputData.roachPosition.n2);
printf ("Journey : %s \n", inputData.journey);
}
IntPair InputBoardSize() {
IntPair size;
int boardRow;
int boardCol;
scanf("%d%d", &boardRow, &boardCol);
size.n1 = boardRow;
size.n2 = boardCol;
return size;
}
IntPair InputStartRoachPosition() {
IntPair position;
int startRow;
int startCol;
scanf("%d%d", &startRow, &startCol);
position.n1 = startRow;
position.n2 = startCol;
return position;
}
void InputRoachJourney(PSTR journey) {
scanf ("%s", journey);
}
void InputEndCode() {
int endCode;
scanf("%d", &endCode);
}
int ScheduledWalk(int* board, int maxRow, int maxCol, IntPair startRoachPosition, PSTR journey) {
testIsFinished();
testMoveNext();
int currentJourneyPosition = 0;
IntPair currentRoachPosition = startRoachPosition;
int totalMoveCount = 0;
IncrementBoardBlockCount(board, currentRoachPosition, maxRow, maxCol);
while (!IsFinished(journey, currentJourneyPosition, board, maxRow, maxCol)) {
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
totalMoveCount++;
currentJourneyPosition++;
}
return totalMoveCount;
}
void testScheduledWalk() {
char journey[MAX_JOURNEY_LENGTH] = "22222";
int maxCol = 10;
int maxRow = 10;
IntPair startRoachPosition;
startRoachPosition.n1 = 0;
startRoachPosition.n2 = 0;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[i*maxRow+j] = 0;
}
}
int totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey);
printf ("total move count : %d \n", totalMoveCount);
assert (totalMoveCount == 5);
assert (board[0*maxRow+0] == 1);
assert (board[0*maxRow+1] == 1);
assert (board[0*maxRow+2] == 1);
assert (board[0*maxRow+3] == 1);
assert (board[0*maxRow+4] == 1);
assert (board[0*maxRow+5] == 1);
}
void testIsFinished() {
// Test Data.
char journey[MAX_JOURNEY_LENGTH] = "22";
int currentPosition = 0;
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 0;
}
}
int maxRow = 10;
int maxCol = 10;
int roachPositionRow = 0;
int roachPositionCol = 0;
assert(IsFinished(journey, currentPosition, board, maxRow, maxCol) == false);
}
BOOL IsFinished(PSTR journey, int currentPosition, int* board, int maxRow, int maxCol) {
testIsJourney();
testIsAllBoardCheck();
return IsJourneyEnd(journey, currentPosition) || IsAllBoardChecked(board, maxRow, maxCol);
}
BOOL IsJourneyEnd(PSTR journey, int currentPosition) {
return strlen(journey) <= (UINT)currentPosition;
}
void testIsJourney() {
char journey[MAX_JOURNEY_LENGTH] = "111122222";
int currentPosition = 1;
assert (IsJourneyEnd(journey, currentPosition) == false);
currentPosition = 9;
assert (IsJourneyEnd(journey, currentPosition) == true);
currentPosition = 10;
assert (IsJourneyEnd(journey, currentPosition) == true);
}
BOOL IsAllBoardChecked(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
if (board[i*maxRow+j] <= 0) return false;
}
}
return true;
}
void testIsAllBoardCheck() {
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 1;
}
}
assert (IsAllBoardChecked(board, 10, 10) == true);
board[0] = 0;
assert (IsAllBoardChecked(board, 10, 10) == false);
}
IntPair MoveNext(IntPair currentRoachPosition, PSTR journey, int currentJourneyPosition, int* board, int maxRow, int maxCol) {
testGetMoveVector();
testMoveRoach();
testIncrementBoardBlockCount();
IntPair updatedRoachPosition;
IntPair moveVector = GetMoveVector(journey, currentJourneyPosition);
updatedRoachPosition = MoveRoach(currentRoachPosition, moveVector, maxRow, maxCol);
IncrementBoardBlockCount(board, updatedRoachPosition, maxRow, maxCol);
return updatedRoachPosition;
}
void testMoveNext() {
IntPair currentRoachPosition;
char journey[] = "333";
int maxRow = 10;
int maxCol = 10;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[i*maxRow+j] = 0;
}
}
currentRoachPosition.n1 = 9;
currentRoachPosition.n2 = 9;
int currentJourneyPosition = 0;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 0);
assert (board[0*maxRow+0] == 1);
currentJourneyPosition = 1;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 1);
assert (currentRoachPosition.n2 == 1);
assert (board[1*maxRow+1] == 1);
currentJourneyPosition = 2;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 2);
assert (currentRoachPosition.n2 == 2);
assert (board[2*maxRow+2] == 1);
}
IntPair GetMoveVector(char* journey, int currentJourneyPosition) {
IntPair moveVector;
// vector - row move vector, col move vector.
int MOVE_VECTOR_PAIR_ROW[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int MOVE_VECTOR_PAIR_COL[8] = { 0, 1, 1, 1, 0, -1, -1, -1};
int moveVectorPairIndex = journey[currentJourneyPosition] - '0';
moveVector.n1 = MOVE_VECTOR_PAIR_ROW[moveVectorPairIndex];
moveVector.n2 = MOVE_VECTOR_PAIR_COL[moveVectorPairIndex];
return moveVector;
}
void testGetMoveVector() {
char journey[MAX_JOURNEY_LENGTH] = "247";
IntPair nextMoveVector;
nextMoveVector = GetMoveVector(journey, 0);
assert (nextMoveVector.n1 == 0);
assert (nextMoveVector.n2 == 1);
nextMoveVector = GetMoveVector(journey, 1);
assert (nextMoveVector.n1 == 1);
assert (nextMoveVector.n2 == 0);
nextMoveVector = GetMoveVector(journey, 2);
assert (nextMoveVector.n1 == -1);
assert (nextMoveVector.n2 == -1);
}
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector, int maxRow, int maxCol) {
IntPair updatedRoachPosition;
updatedRoachPosition.n1 = (currentRoachPosition.n1 + moveVector.n1) % maxRow;
updatedRoachPosition.n2 = (currentRoachPosition.n2 + moveVector.n2) % maxCol;
return updatedRoachPosition;
}
void testMoveRoach() {
IntPair currentRoachPosition;
IntPair moveVector;
currentRoachPosition.n1 = 0;
currentRoachPosition.n2 = 0;
// case move type '2':
moveVector.n1 = 0;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector, 10, 10);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 1);
// One More Time..~
moveVector.n1 = 0;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector, 10, 10);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 2);
// Checking Boundary Warp.
int maxCol = 10;
int maxRow = 10;
currentRoachPosition.n1 = 9;
currentRoachPosition.n2 = 9;
moveVector.n1 = 1;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector, maxRow, maxCol);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 0);
}
void IncrementBoardBlockCount(int* board, IntPair roachPosition, int maxRow, int maxCol) {
assert (roachPosition.n1 < maxRow);
assert (roachPosition.n2 < maxCol);
board[roachPosition.n1*maxRow + roachPosition.n2]++;
}
void testIncrementBoardBlockCount() {
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 0;
}
}
IntPair currentRoachPosition;
currentRoachPosition.n1 = 1;
currentRoachPosition.n2 = 1;
IncrementBoardBlockCount(board, currentRoachPosition, 10, 10);
assert (board[1*10+1] == 1);
}
void Output(int totalMoveCount, int* board, int maxRow, int maxCol) {
OutputMoveCount(totalMoveCount);
OutputBoardStatus(board, maxRow, maxCol);
}
void OutputMoveCount(int totalMaxCount) {
printf ("%d\n", totalMaxCount);
printf ("\n");
}
void OutputBoardStatus(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
printf ("%d ", board[maxRow*i+j]);
}
printf ("\n");
}
}
}}}
=== Test & 버그 분� ===
ìž�. ì�´ì œ 슬슬 ["RandomWalk2/TestCase"] ì—� 있는 ["AcceptanceTest"] ì�˜ 경우가 ë�˜ëŠ” 예들ì�„ 하나하나 실행해봅니다.
{{{~cpp
F:\WorkingTemp\ScheduledWalk\Debug>ScheduledWalk
5 5
0 0
22224444346
999
11
2 1 1 1 2
1 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
본래 기대값 :
2 1 1 1 1
1 0 0 0 2
0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
}}}
오호ë�¼ 버그ì�´êµ°ìš”. ê²°ê³¼ ìž�ì²´ì—� ì´›ì �ì�„ 맞춰봅시다. 마지막 6ì—� 대한 ì�´ë�™ì�´ 마치 1ì—� 대한 ì�´ë�™ì²˜ëŸ¼ ë�˜ì–´ë²„ë ¸êµ°ìš”. ì�¼ë‹¨, 바로 ì�˜ì‹¬ë�˜ëŠ” 것으로는 6번ì—� 대한 ì�´ë�™ë¶€ë¶„. ì�´ë�™ë°©í–¥ë²¡í„°ë¥¼ ê²°ì •í•´ì£¼ëŠ” 루틴ì�„ 찾아보면 GetMoveVector ì�´ë¯€ë¡œ ì�´ë¶€ë¶„ì�´ 첫번째 ì�˜ì‹¬ì�„ ë°›ê² êµ°ìš”.
{{{~cpp
IntPair GetMoveVector(char* journey, int currentJourneyPosition) {
IntPair moveVector;
// vector - row move vector, col move vector.
int MOVE_VECTOR_PAIR_ROW[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int MOVE_VECTOR_PAIR_COL[8] = { 0, 1, 1, 1, 0, -1, -1, -1};
int moveVectorPairIndex = journey[currentJourneyPosition] - '0';
moveVector.n1 = MOVE_VECTOR_PAIR_ROW[moveVectorPairIndex];
moveVector.n2 = MOVE_VECTOR_PAIR_COL[moveVectorPairIndex];
return moveVector;
}
}}}
ì�Œ.. Vector ìž�체로는 별 ë¬¸ì œì—†ì–´ ë³´ì�´ë„¤ìš”. ê·¸ë ‡ë‹¤ë©´ 다ì�Œì�€ ì‹¤ì œ Roach를 ì�´ë�™ì‹œí‚¤ëŠ” Position ê³¼ ê´€ë ¨ë�œ MoveRoach 부분ì�„ ì‚´íŽ´ë³´ì£ . (여기서는 반드시 ì�´ë�™ë°©í–¥ì�„ ê²°ì •í•˜ëŠ” 함수와 ì‹¤ì œ ì�´ë�™ì‹œí‚¤ëŠ” 함수ì—� ì´›ì �ì�„ 맞춰야 합니다. board ë°°ì—´ì�˜ ê°’ì�´ update ê°€ ë�˜ê¸° ìœ„í•´ì„ ì–´ë– ì–´ë– í•œ ê°’ì—� ì˜�í–¥ì�„ 받는지를 ë¨¼ì € 머릿ì†�ì—� ê·¸ë ¤ì•¼ ê² ì£ .) 그림ì�´ 안 ê·¸ë ¤ì§€ëŠ” 경우ì—�는 Debugger 와 Trace, break point 를 ì�´ìš©í• 수 있습니다. 하지만, 구조화를 잘 시켜놓았ì�„ 경우 해당 ë¬¸ì œë°œìƒ�시 버그 예ìƒ�부분ì�´ ì–´ëŠ�ì •ë�„ 그림ì�´ ê·¸ë ¤ì§‘ë‹ˆë‹¤.
{{{~cpp
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector, int maxRow, int maxCol) {
IntPair updatedRoachPosition;
updatedRoachPosition.n1 = (currentRoachPosition.n1 + moveVector.n1) % maxRow;
updatedRoachPosition.n2 = (currentRoachPosition.n2 + moveVector.n2) % maxCol;
return updatedRoachPosition;
}
}}}
ì�´ 부분ì—� 대해서 í�½ í•˜ê³ ê¹¨ìš°ì¹¨ì�„ 얻었는ë�°; (ì•„ì�´ë””ì–´ê°€ ë– ì˜¤ë¥´ì§€ 않ì�„때 ì�´ 부분ì�´ 잘못ë�˜ì—ˆì�Œì�„ ì•Œë ¤ë©´ Debugger 를 ì�¨ì•¼ê² ì£ .)
바로 indexê°€ -1 ì�´ ë�˜ì—ˆì�„ 경우ì�´ì£ . 그러므로 Modular 연산으로 ê³„ì‚°í• ìˆ˜ 없다.
row 1, col 0 ì—�서 row 0, col -1 ì�„ ë�”í–ˆì�„ 경루를 ìƒ�ê°�한다면 row 1, col -1 입니다. -1 ì—� 대해 modular 5를 한다면? 다름아닌 4ê°€ 나옵니다. 즉, 1, 4 ê°€ ë�˜ì–´ë²„ë¦¬ì£ .
ì�¼ë‹¨ main ()ì�„ test code 실행 모드로 ë°”ê¾¸ê³ .
{{{~cpp
int main()
{
/* ------------- excute test code -------------
testInput();
testScheduledWalk();
------------- excute test code ------------- */
/*
InputData inputData = Input();
int maxRow = inputData.boardSize.n1;
int maxCol = inputData.boardSize.n2;
int* board = new int[maxRow * maxCol];
InitializeArray(board, maxRow, maxCol);
IntPair startRoachPosition = inputData.roachPosition;
char journey[MAX_JOURNEY_LENGTH]="";
strcpy(journey, inputData.journey);
int totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey);
Output(totalMoveCount, board, maxRow, maxCol);
delete board;
*/
testScheduledWalk();
return 0;
}
}}}
MoveRoach 코드를 ì�¼ë‹¨ì�€ 가장 쉬운 코드로 ê³ ì³�봤습니다.
{{{~cpp
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector, int maxRow, int maxCol) {
IntPair updatedRoachPosition;
updatedRoachPosition.n1 = (currentRoachPosition.n1 + moveVector.n1);
updatedRoachPosition.n2 = (currentRoachPosition.n2 + moveVector.n2);
if (updatedRoachPosition.n1 >= maxRow) updatedRoachPosition.n1 = 0;
else if (updatedRoachPosition.n1 < 0) updatedRoachPosition.n1 = maxRow-1;
if (updatedRoachPosition.n2 >= maxCol) updatedRoachPosition.n2 = 0;
else if (updatedRoachPosition.n2 < 0) updatedRoachPosition.n2 = maxCol-1;
return updatedRoachPosition;
}
}}}
ì�¼ë‹¨ assert 문 걸어놓ì�€ 부분ì—� ëŒ€í•´ì„ ok.
{{{~cpp
5 5
0 0
22224444346
999
11
2 1 1 1 1
1 0 0 0 2
0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
Press any key to continue
}}}
ì�¼ë‹¨ Test Case 하나ì—� ëŒ€í•´ì„ ok. 계ì†� 테스트를 í•´ 나갑니다.
["RandomWalk2/TestCase"] � 대해서� ok.
["RandomWalk2/TestCase2"] � Test1,2,3 � 대해서 ok. 오. 그럼 ���� 테스트가 �미가 없�까요?
여기� 복병� 있었으니..
Test4 � 대해서는
{{{~cpp
5 4
0 0
2224444666
999
10
1 1 1 1
0 0 0 1
0 0 0 1
0 0 0 1
1 1 1 1
}}}
ê·¸ë¦¬ê³ ìž˜ëª»ë�œ ì—°ì‚° 오류.
�하는 기대값�
{{{~cpp
10
1 1 1 1 0
0 0 0 1 0
0 1 0 1 0
1 1 1 1 0
}}}
["RandomWalk2/TestCase"] ì—�서 멈췄다면 í�°ì�¼ë‚ ë»” 했군요. 테스트는 ìž�주 해줄수ë¡� ê·¸ 프로그램ì�˜ ì‹ ìš©ë�„를 높여ì¤�니다. ì�¼ì¢…ì�˜ Quality Assurance ë�¼ê³ í•´ì•¼ê² ì£ .
ì�¼ë‹¨ 아웃풋 ë§Œì�„ ë‘�ê³ ë³¸ë‹¤ë©´, ë°°ì—´ ìž�ì²´ì�˜ 행과 ì—´ì�˜ í�¬ê¸°ê°€ 뒤집혔군요. ê·¸ë ‡ë‹¤ë©´ ê·¸ì—� 따른 ì—�러 가능성 높ì�Œ. ê·¸ë ‡ë‹¤ê³ í•œë‹¤ë©´, ë°°ì—´ì—� ê°’ì�„ ì¦�가시키는 IncrementBoardBlockCount() ì—� ì—�러가능성ì�´ ë†’ê² ìŠµë‹ˆë‹¤.
{{{~cpp
void IncrementBoardBlockCount(int* board, IntPair roachPosition, int maxRow, int maxCol) {
assert (roachPosition.n1 < maxRow);
assert (roachPosition.n2 < maxCol);
board[roachPosition.n1*maxRow + roachPosition.n2]++; // <--- maxRow 가 아닌 maxCol �여야 한다.
}
}}}
ì�Œ? ì�´ëŸ° 계산ì�´ ì�´ 프로그램 ë‚´ì—�서 굉장히 ë§Žì�´ ë‚˜ì˜¤ì£ . 2ì°¨ì›� ë�™ì �ë°°ì—´ì�„ 1ì°¨ì›� 배열로 구현해줬기 때문ì—�. 오호ë�¼..
(그 밖� 1차� 배열로 계산했었� 부분들� 찾기 위해 Search �서 '*maxRow+' 로 검색해봤습니다. 13군� 나오�군요;;)
여기서 ì–»ì�„ 수 있는 êµ�훈 - ì�´ëŸ° 변환 부분ì�€ ì°¨ë�¼ë¦¬ 함수로 만들ìž�는 ê²�니다. -_-; ì�´ 경우 OO Language ë�¼ë©´ 1ì°¨ì›� ë°°ì—´ì�„ ì�´ìš©í•œ 2ì°¨ì›� ë°°ì—´ í�´ëž˜ìŠ¤ë¥¼ 만들어 쓰는 것ì�´ 가장 편합니다. ë¬¸ì œë¥¼ 해당 ë°°ì—´ í�´ëž˜ìФ 내로 ì§€ì—í™” 시킬 수 ìžˆì£ . 여기서는 ì�¼ë‹¨ C로 ë§Œë“¤ì—ˆë‹¤ê³ ê°€ì •í•˜ê³ ë°°ì œí•©ë‹ˆë‹¤.
{{{~cpp
int _2to1(int row, int col, int maxCol) {
return maxCol*row + col;
}
}}}
중간� ["NewTestsForOldBugs"] � ��.
=== 최종 테스트들� 만족시키는 코드 ===
최종 테스트 (["RandomWalk2/TestCase"], ["RandomWalk2/TestCase2"]) 를 만족시키는 코드.
{{{~cpp
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef int BOOL;
typedef char* PSTR;
typedef unsigned int UINT;
const int MAX_JOURNEY_LENGTH = 1000;
typedef struct __IntegerPair {
int n1; // Row 와 관계�것들.
int n2; // Col 와 관계�것들.
} IntPair;
typedef struct __InputDataStructure {
IntPair boardSize;
IntPair roachPosition;
char journey[MAX_JOURNEY_LENGTH];
} InputData;
InputData Input();
IntPair InputBoardSize();
IntPair InputStartRoachPosition();
void InputRoachJourney(PSTR journey);
void InputEndCode();
void testInput();
void InitializeArray(int* board, int maxRow, int maxCol);
int ScheduledWalk(int* board, int maxRow, int maxCol, IntPair startRoachPosition, PSTR journey);
BOOL IsFinished(PSTR journey, int currentPosition, int* board, int maxRow, int maxCol);
BOOL IsJourneyEnd(PSTR journey, int currentPosition);
BOOL IsAllBoardChecked(int* board, int maxRow, int maxCol);
void testIsJourney();
void testIsAllBoardCheck();
IntPair MoveNext(IntPair currentRoachPosition, PSTR journey, int currentJourneyPosition, int* board, int maxRow, int maxCol);
IntPair GetMoveVector(char* journey, int currentPosition);
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector, int maxRow, int maxCol);
void IncrementBoardBlockCount(int* board, IntPair roachPosition, int maxRow, int maxCol);
void testGetMoveVector();
void testMoveRoach();
void testIncrementBoardBlockCount();
void testIsFinished();
void testMoveNext();
void testScheduledWalk();
void Output(int totalMoveCount, int* board, int maxRow, int maxCol);
void OutputMoveCount(int totalMaxCount);
void OutputBoardStatus(int* board, int maxRow, int maxCol);
int _2to1(int row, int col, int maxCol) {
return maxCol*row+col;
}
int main()
{
/* ------------- excute test code -------------
testInput();
testScheduledWalk();
------------- excute test code ------------- */
InputData inputData = Input();
int maxRow = inputData.boardSize.n1;
int maxCol = inputData.boardSize.n2;
int* board = new int[maxRow * maxCol];
InitializeArray(board, maxRow, maxCol);
IntPair startRoachPosition = inputData.roachPosition;
char journey[MAX_JOURNEY_LENGTH]="";
strcpy(journey, inputData.journey);
int totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey);
Output(totalMoveCount, board, maxRow, maxCol);
delete board;
return 0;
}
void InitializeArray(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[_2to1(i,j,maxCol)] = 0;
}
}
}
InputData Input() {
InputData inputData;
inputData.boardSize = InputBoardSize();
inputData.roachPosition = InputStartRoachPosition();
InputRoachJourney(inputData.journey);
InputEndCode();
return inputData;
}
void testInput() {
InputData inputData;
inputData = Input();
// For Input() Testing....
printf ("Board Size value : %d, %d \n", inputData.boardSize.n1, inputData.boardSize.n2);
printf ("Start Position value : %d, %d \n", inputData.roachPosition.n1, inputData.roachPosition.n2);
printf ("Journey : %s \n", inputData.journey);
}
IntPair InputBoardSize() {
IntPair size;
int boardRow;
int boardCol;
scanf("%d%d", &boardCol, &boardRow);
size.n1 = boardRow;
size.n2 = boardCol;
return size;
}
IntPair InputStartRoachPosition() {
IntPair position;
int startRow;
int startCol;
scanf("%d%d", &startRow, &startCol);
position.n1 = startRow;
position.n2 = startCol;
return position;
}
void InputRoachJourney(PSTR journey) {
scanf ("%s", journey);
}
void InputEndCode() {
int endCode;
scanf("%d", &endCode);
}
int ScheduledWalk(int* board, int maxRow, int maxCol, IntPair startRoachPosition, PSTR journey) {
testIsFinished();
testMoveNext();
int currentJourneyPosition = 0;
IntPair currentRoachPosition = startRoachPosition;
int totalMoveCount = 0;
IncrementBoardBlockCount(board, currentRoachPosition, maxRow, maxCol);
while (!IsFinished(journey, currentJourneyPosition, board, maxRow, maxCol)) {
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
totalMoveCount++;
currentJourneyPosition++;
}
return totalMoveCount;
}
void testScheduledWalk() {
char journey[MAX_JOURNEY_LENGTH] = "22222";
int maxCol = 10;
int maxRow = 10;
IntPair startRoachPosition;
startRoachPosition.n1 = 0;
startRoachPosition.n2 = 0;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[_2to1(i,j,maxCol)] = 0;
}
}
int totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey);
printf ("total move count : %d \n", totalMoveCount);
assert (totalMoveCount == 5);
assert (board[_2to1(0,0,maxCol)] == 1);
assert (board[_2to1(0,1,maxCol)] == 1);
assert (board[_2to1(0,2,maxCol)] == 1);
assert (board[_2to1(0,3,maxCol)] == 1);
assert (board[_2to1(0,4,maxCol)] == 1);
assert (board[_2to1(0,5,maxCol)] == 1);
}
void testIsFinished() {
// Test Data.
char journey[MAX_JOURNEY_LENGTH] = "22";
int currentPosition = 0;
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 0;
}
}
int maxRow = 10;
int maxCol = 10;
int roachPositionRow = 0;
int roachPositionCol = 0;
assert(IsFinished(journey, currentPosition, board, maxRow, maxCol) == false);
}
BOOL IsFinished(PSTR journey, int currentPosition, int* board, int maxRow, int maxCol) {
testIsJourney();
testIsAllBoardCheck();
return IsJourneyEnd(journey, currentPosition) || IsAllBoardChecked(board, maxRow, maxCol);
}
BOOL IsJourneyEnd(PSTR journey, int currentPosition) {
return strlen(journey) <= (UINT)currentPosition;
}
void testIsJourney() {
char journey[MAX_JOURNEY_LENGTH] = "111122222";
int currentPosition = 1;
assert (IsJourneyEnd(journey, currentPosition) == false);
currentPosition = 9;
assert (IsJourneyEnd(journey, currentPosition) == true);
currentPosition = 10;
assert (IsJourneyEnd(journey, currentPosition) == true);
}
BOOL IsAllBoardChecked(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
if (board[_2to1(i,j,maxCol)] <= 0) return false;
}
}
return true;
}
void testIsAllBoardCheck() {
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 1;
}
}
assert (IsAllBoardChecked(board, 10, 10) == true);
board[0] = 0;
assert (IsAllBoardChecked(board, 10, 10) == false);
}
IntPair MoveNext(IntPair currentRoachPosition, PSTR journey, int currentJourneyPosition, int* board, int maxRow, int maxCol) {
testGetMoveVector();
testMoveRoach();
testIncrementBoardBlockCount();
IntPair updatedRoachPosition;
IntPair moveVector = GetMoveVector(journey, currentJourneyPosition);
updatedRoachPosition = MoveRoach(currentRoachPosition, moveVector, maxRow, maxCol);
IncrementBoardBlockCount(board, updatedRoachPosition, maxRow, maxCol);
return updatedRoachPosition;
}
void testMoveNext() {
IntPair currentRoachPosition;
char journey[] = "333";
int maxRow = 10;
int maxCol = 10;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[_2to1(i,j,maxCol)] = 0;
}
}
currentRoachPosition.n1 = 9;
currentRoachPosition.n2 = 9;
int currentJourneyPosition = 0;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 0);
assert (board[_2to1(0,0,maxCol)] == 1);
currentJourneyPosition = 1;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 1);
assert (currentRoachPosition.n2 == 1);
assert (board[_2to1(1,1,maxCol)] == 1);
currentJourneyPosition = 2;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 2);
assert (currentRoachPosition.n2 == 2);
assert (board[_2to1(2,2,maxCol)] == 1);
}
IntPair GetMoveVector(char* journey, int currentJourneyPosition) {
IntPair moveVector;
// vector - row move vector, col move vector.
int MOVE_VECTOR_PAIR_ROW[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int MOVE_VECTOR_PAIR_COL[8] = { 0, 1, 1, 1, 0, -1, -1, -1};
int moveVectorPairIndex = journey[currentJourneyPosition] - '0';
moveVector.n1 = MOVE_VECTOR_PAIR_ROW[moveVectorPairIndex];
moveVector.n2 = MOVE_VECTOR_PAIR_COL[moveVectorPairIndex];
return moveVector;
}
void testGetMoveVector() {
char journey[MAX_JOURNEY_LENGTH] = "247";
IntPair nextMoveVector;
nextMoveVector = GetMoveVector(journey, 0);
assert (nextMoveVector.n1 == 0);
assert (nextMoveVector.n2 == 1);
nextMoveVector = GetMoveVector(journey, 1);
assert (nextMoveVector.n1 == 1);
assert (nextMoveVector.n2 == 0);
nextMoveVector = GetMoveVector(journey, 2);
assert (nextMoveVector.n1 == -1);
assert (nextMoveVector.n2 == -1);
}
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector, int maxRow, int maxCol) {
IntPair updatedRoachPosition;
updatedRoachPosition.n1 = (currentRoachPosition.n1 + moveVector.n1);
updatedRoachPosition.n2 = (currentRoachPosition.n2 + moveVector.n2);
if (updatedRoachPosition.n1 >= maxRow) updatedRoachPosition.n1 = 0;
else if (updatedRoachPosition.n1 < 0) updatedRoachPosition.n1 = maxRow-1;
if (updatedRoachPosition.n2 >= maxCol) updatedRoachPosition.n2 = 0;
else if (updatedRoachPosition.n2 < 0) updatedRoachPosition.n2 = maxCol-1;
return updatedRoachPosition;
}
void testMoveRoach() {
IntPair currentRoachPosition;
IntPair moveVector;
currentRoachPosition.n1 = 0;
currentRoachPosition.n2 = 0;
// case move type '2':
moveVector.n1 = 0;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector, 10, 10);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 1);
// One More Time..~
moveVector.n1 = 0;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector, 10, 10);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 2);
// Checking Boundary Warp.
int maxCol = 10;
int maxRow = 10;
currentRoachPosition.n1 = 9;
currentRoachPosition.n2 = 9;
moveVector.n1 = 1;
moveVector.n2 = 1;
currentRoachPosition = MoveRoach(currentRoachPosition, moveVector, maxRow, maxCol);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 0);
}
void IncrementBoardBlockCount(int* board, IntPair roachPosition, int maxRow, int maxCol) {
assert (roachPosition.n1 < maxRow);
assert (roachPosition.n2 < maxCol);
board[roachPosition.n1*maxCol + roachPosition.n2]++;
}
void testIncrementBoardBlockCount() {
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 0;
}
}
IntPair currentRoachPosition;
currentRoachPosition.n1 = 1;
currentRoachPosition.n2 = 1;
IncrementBoardBlockCount(board, currentRoachPosition, 10, 10);
assert (board[1*10+1] == 1);
}
void Output(int totalMoveCount, int* board, int maxRow, int maxCol) {
OutputMoveCount(totalMoveCount);
OutputBoardStatus(board, maxRow, maxCol);
}
void OutputMoveCount(int totalMaxCount) {
printf ("%d\n", totalMaxCount);
printf ("\n");
}
void OutputBoardStatus(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
printf ("%d ", board[maxCol*i+j]);
}
printf ("\n");
}
}
}}}
여기서 약간 ë�” 나가서. 현재 테스트 코드와 ë©”ì�¸ 코드가 섞여있어서 ìƒ�당히 소스가 복잡해보입니다. ê·¸ë¦¬ê³ AcceptanceTest ì—� 대해서는 ìž�ë�™í™”ë�˜ì§€ 않았습니다.
=== 마무리 소스 ===
==== main.cpp ====
{{{~cpp
#include "ScheduledWalkTestCase.h"
#include "ScheduledWalk.h"
int main()
{
/* ------------- Acceptance Test -------------
AcceptanceTestAll ();
------------- Acceptance Test ------------- */
AcceptanceTestAll (); // <--- For Acceptance Test
UnitTestAll();
// ScheduledWalkMain(); // <--- Main Routine
return 0;
}
void ScheduledWalkMain() {
InputData inputData;
IntPair startRoachPosition;
int maxRow;
int maxCol;
int* board;
char journey[MAX_JOURNEY_LENGTH]="";
int totalMoveCount = 0;
inputData = Input();
maxRow = inputData.boardSize.n1;
maxCol = inputData.boardSize.n2;
board = CreateBoard(maxRow, maxCol);
startRoachPosition = inputData.roachPosition;
strcpy(journey, inputData.journey);
totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey);
Output(totalMoveCount, board, maxRow, maxCol);
DestroyBoard(board);
}
}}}
==== ScheduledWalk.h ====
{{{~cpp
#ifndef _SCHEDULEDWALK_H_
#define _SCHEDULEDWALK_H_
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef int BOOL;
typedef char* PSTR;
typedef unsigned int UINT;
const int MAX_JOURNEY_LENGTH = 1000;
typedef struct __IntegerPair {
int n1; // Row 와 관계�것들.
int n2; // Col 와 관계�것들.
} IntPair;
typedef struct __InputDataStructure {
IntPair boardSize;
IntPair roachPosition;
char journey[MAX_JOURNEY_LENGTH];
} InputData;
InputData Input();
IntPair InputBoardSize();
IntPair InputStartRoachPosition();
void InputRoachJourney(PSTR journey);
void InputEndCode();
void InitializeArray(int* board, int maxRow, int maxCol);
int ScheduledWalk(int* board, int maxRow, int maxCol, IntPair startRoachPosition, PSTR journey);
BOOL IsFinished(PSTR journey, int currentPosition, int* board, int maxRow, int maxCol);
BOOL IsJourneyEnd(PSTR journey, int currentPosition);
BOOL IsAllBoardChecked(int* board, int maxRow, int maxCol);
IntPair MoveNext(IntPair currentRoachPosition, PSTR journey, int currentJourneyPosition, int* board, int maxRow, int maxCol);
IntPair GetMoveVector(char* journey, int currentPosition);
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector, int maxRow, int maxCol);
void IncrementBoardBlockCount(int* board, IntPair roachPosition, int maxRow, int maxCol);
void Output(int totalMoveCount, int* board, int maxRow, int maxCol);
void OutputMoveCount(int totalMaxCount);
void OutputBoardStatus(int* board, int maxRow, int maxCol);
int _2to1(int row, int col, int maxCol);
int* CreateBoard(int maxRow, int maxCol);
void DestroyBoard(int* board);
#endif
}}}
==== ScheduledWalk.cpp ====
{{{~cpp
#include "ScheduledWalk.h"
int _2to1(int row, int col, int maxCol) {
return maxCol*row+col;
}
int* CreateBoard(int maxRow, int maxCol) {
int* board = new int[maxRow * maxCol];
InitializeArray(board, maxRow, maxCol);
return board;
}
void DestroyBoard(int* board) {
delete board;
}
void InitializeArray(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[_2to1(i,j,maxCol)] = 0;
}
}
}
InputData Input() {
InputData inputData;
inputData.boardSize = InputBoardSize();
inputData.roachPosition = InputStartRoachPosition();
InputRoachJourney(inputData.journey);
InputEndCode();
return inputData;
}
IntPair InputBoardSize() {
IntPair size;
int boardRow;
int boardCol;
scanf("%d%d", &boardCol, &boardRow);
size.n1 = boardRow;
size.n2 = boardCol;
return size;
}
IntPair InputStartRoachPosition() {
IntPair position;
int startRow;
int startCol;
scanf("%d%d", &startRow, &startCol);
position.n1 = startRow;
position.n2 = startCol;
return position;
}
void InputRoachJourney(PSTR journey) {
scanf ("%s", journey);
}
void InputEndCode() {
int endCode;
scanf("%d", &endCode);
}
int ScheduledWalk(int* board, int maxRow, int maxCol, IntPair startRoachPosition, PSTR journey) {
int currentJourneyPosition = 0;
IntPair currentRoachPosition = startRoachPosition;
int totalMoveCount = 0;
IncrementBoardBlockCount(board, currentRoachPosition, maxRow, maxCol);
while (!IsFinished(journey, currentJourneyPosition, board, maxRow, maxCol)) {
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
totalMoveCount++;
currentJourneyPosition++;
}
return totalMoveCount;
}
BOOL IsFinished(PSTR journey, int currentPosition, int* board, int maxRow, int maxCol) {
return IsJourneyEnd(journey, currentPosition) || IsAllBoardChecked(board, maxRow, maxCol);
}
BOOL IsJourneyEnd(PSTR journey, int currentPosition) {
return strlen(journey) <= (UINT)currentPosition;
}
BOOL IsAllBoardChecked(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
if (board[_2to1(i,j,maxCol)] <= 0) return false;
}
}
return true;
}
IntPair MoveNext(IntPair currentRoachPosition, PSTR journey, int currentJourneyPosition, int* board, int maxRow, int maxCol) {
IntPair updatedRoachPosition;
IntPair moveVector = GetMoveVector(journey, currentJourneyPosition);
updatedRoachPosition = MoveRoach(currentRoachPosition, moveVector, maxRow, maxCol);
IncrementBoardBlockCount(board, updatedRoachPosition, maxRow, maxCol);
return updatedRoachPosition;
}
IntPair GetMoveVector(char* journey, int currentJourneyPosition) {
IntPair moveVector;
// vector - row move vector, col move vector.
int MOVE_VECTOR_PAIR_ROW[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int MOVE_VECTOR_PAIR_COL[8] = { 0, 1, 1, 1, 0, -1, -1, -1};
int moveVectorPairIndex = journey[currentJourneyPosition] - '0';
moveVector.n1 = MOVE_VECTOR_PAIR_ROW[moveVectorPairIndex];
moveVector.n2 = MOVE_VECTOR_PAIR_COL[moveVectorPairIndex];
return moveVector;
}
IntPair MoveRoach(IntPair currentRoachPosition, IntPair moveVector, int maxRow, int maxCol) {
IntPair updatedRoachPosition;
updatedRoachPosition.n1 = (currentRoachPosition.n1 + moveVector.n1);
updatedRoachPosition.n2 = (currentRoachPosition.n2 + moveVector.n2);
if (updatedRoachPosition.n1 >= maxRow) updatedRoachPosition.n1 = 0;
else if (updatedRoachPosition.n1 < 0) updatedRoachPosition.n1 = maxRow-1;
if (updatedRoachPosition.n2 >= maxCol) updatedRoachPosition.n2 = 0;
else if (updatedRoachPosition.n2 < 0) updatedRoachPosition.n2 = maxCol-1;
return updatedRoachPosition;
}
void IncrementBoardBlockCount(int* board, IntPair roachPosition, int maxRow, int maxCol) {
assert (roachPosition.n1 < maxRow);
assert (roachPosition.n2 < maxCol);
board[roachPosition.n1*maxCol + roachPosition.n2]++;
}
void Output(int totalMoveCount, int* board, int maxRow, int maxCol) {
OutputMoveCount(totalMoveCount);
OutputBoardStatus(board, maxRow, maxCol);
}
void OutputMoveCount(int totalMaxCount) {
printf ("%d\n", totalMaxCount);
printf ("\n");
}
void OutputBoardStatus(int* board, int maxRow, int maxCol) {
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
printf ("%d ", board[maxCol*i+j]);
}
printf ("\n");
}
}
}}}
==== ScheduledWalkTestCase.h ====
{{{~cpp
#include <assert.h>
#include <stdio.h>
#include "ScheduledWalk.h"
void testScheduledWalk1_1();
void testScheduledWalk1_2();
void testScheduledWalk1_3();
void testScheduledWalk1_4();
void testScheduledWalk2_1();
void testScheduledWalk2_2();
void testScheduledWalk2_3();
void testScheduledWalk2_4();
void testInput();
void testIsFinished();
void testIsJourney();
void testIsAllBoardCheck();
void testMoveNext();
void testGetMoveVector();
void testMoveRoach();
void testIncrementBoardBlockCount();
void testScheduledWalk();
void AcceptanceTestAll();
void UnitTestAll();
void testScheduledWalking(int maxRow, int maxCol, IntPair startRoachPosition, PSTR journey, int expectedTotalMoveCount, int* expectedBoardArray);
void excuteTest (void (*func)(void), PSTR message);
}}}
==== ScheduledWalkTestCase.cpp ====
{{{~cpp
#include "ScheduledWalkTestCase.h"
void testInput() {
InputData inputData;
printf ("Input data ... :");
inputData = Input();
// For Input() Testing....
printf ("Board Size value : %d, %d \n", inputData.boardSize.n1, inputData.boardSize.n2);
printf ("Start Position value : %d, %d \n", inputData.roachPosition.n1, inputData.roachPosition.n2);
printf ("Journey : %s \n", inputData.journey);
}
void testScheduledWalk() {
char journey[MAX_JOURNEY_LENGTH] = "22222";
int maxCol = 10;
int maxRow = 10;
IntPair startRoachPosition;
startRoachPosition.n1 = 0;
startRoachPosition.n2 = 0;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[_2to1(i,j,maxCol)] = 0;
}
}
int totalMoveCount = ScheduledWalk(board, maxRow, maxCol, startRoachPosition, journey);
assert (totalMoveCount == 5);
assert (board[_2to1(0,0,maxCol)] == 1);
assert (board[_2to1(0,1,maxCol)] == 1);
assert (board[_2to1(0,2,maxCol)] == 1);
assert (board[_2to1(0,3,maxCol)] == 1);
assert (board[_2to1(0,4,maxCol)] == 1);
assert (board[_2to1(0,5,maxCol)] == 1);
}
void testIsFinished() {
// Test Data.
char journey[MAX_JOURNEY_LENGTH] = "22";
int currentPosition = 0;
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 0;
}
}
int maxRow = 10;
int maxCol = 10;
int roachPositionRow = 0;
int roachPositionCol = 0;
assert(IsFinished(journey, currentPosition, board, maxRow, maxCol) == false);
}
void testIsJourney() {
char journey[MAX_JOURNEY_LENGTH] = "111122222";
int currentPosition = 1;
assert (IsJourneyEnd(journey, currentPosition) == false);
currentPosition = 9;
assert (IsJourneyEnd(journey, currentPosition) == true);
currentPosition = 10;
assert (IsJourneyEnd(journey, currentPosition) == true);
}
void testIsAllBoardCheck() {
int board[10*10];
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i*10+j] = 1;
}
}
assert (IsAllBoardChecked(board, 10, 10) == true);
board[0] = 0;
assert (IsAllBoardChecked(board, 10, 10) == false);
}
void testMoveNext() {
IntPair currentRoachPosition;
char journey[] = "333";
int maxRow = 10;
int maxCol = 10;
int board[10*10];
for (int i=0;i<maxRow;i++) {
for (int j=0;j<maxCol;j++) {
board[_2to1(i,j,maxCol)] = 0;
}
}
currentRoachPosition.n1 = 9;
currentRoachPosition.n2 = 9;
int currentJourneyPosition = 0;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 0);
assert (currentRoachPosition.n2 == 0);
assert (board[_2to1(0,0,maxCol)] == 1);
currentJourneyPosition = 1;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 1);
assert (currentRoachPosition.n2 == 1);
assert (board[_2to1(1,1,maxCol)] == 1);
currentJourneyPosition = 2;
currentRoachPosition = MoveNext (currentRoachPosition, journey, currentJourneyPosition, board, maxRow, maxCol);
assert (currentRoachPosition.n1 == 2);
assert (currentRoachPosition.n2 == 2);
assert (board[_2to1(2,2,maxCol)] == 1);
}
void testGetMoveVector() {
char journey[MAX_JOURNEY_LENGTH] = "247";
IntPair nextMoveVector;
nextMoveVector = GetMoveVector(journey, 0);
assert (nextM









