[[TableOfContents]] === 소개글 === ["ë°ë¸”ìŠ¤ìº í”„2002"]때 ì†Œê°œí–ˆì—ˆë˜ StructuredProgramming ê¸°ë²•ì„ ì²˜ìŒë¶€í„° ë까지 진행하는 ëª¨ìŠµì„ ë³´ì—¬ë“œë¦½ë‹ˆë‹¤. ì¤‘ê°„ì— ë²„ê·¸ê°€ ë°œìƒí•˜ê³ , ê·¸ 버그를 ìˆ˜ì •í•œ 소스를 그대로 실어봅니다. 그대로 ë”°ë¼í•´ë³´ì…”ë„ ì¢‹ì„듯. 단, 중간 삽질과 ì»´íŒŒì¼ ì—ëŸ¬ì— ê²ë¨¹ì§€ë§Œ ì•Šìœ¼ì‹ ë‹¤ë©´. ^^; Spec ê³¼ Test Case 는 ["RandomWalk2"] ì— ìžˆìŠµë‹ˆë‹¤. === 개발ì›ë¦¬ === StructuredProgramming 기법으로 StepwiseRefinement 하였습니다. ë¬¸ì œë¥¼ TopDown 스타ì¼ë¡œ ê³„ì† ìž¬ì •ì˜í•˜ì—¬ 뼈대를 ë§Œë“ ë‹¤ìŒ, Depth First (트리ì—서 ê¹Šì´ ìš°ì„ ) 로 가장 ìž‘ì€ ëª¨ë“ˆë“¤ì„ ë¨¼ì € 하나하나 구현해 나갔습니다. 중반부터는 UnitTest 코드를 삽입하기를 시ë„, 중후반부터는 UnitTest Code를 ë¨¼ì € ë§Œë“¤ê³ í”„ë¡œê·¸ëž¨ 코드를 ë‚˜ì¤‘ì— ìž‘ì„±í•˜ì˜€ìŠµë‹ˆë‹¤. === 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 () { } }}} === 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() { } }}} === 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 ì˜ ê²°ê³¼ê°€ 완벽하다ë¼ê³ ë§í• 수는 없으니까요. 하지만, ë¬¸ì œì™€ ì „ë°˜ì 프로그램 ë””ìžì¸, í° ë°‘ê·¸ë¦¼ì„ ê·¸ë¦¬ê³ ì´í•´í•˜ëŠ”ë° ë„ì›€ì„ ì¤Œì—는 분명합니다. ) (Hierarchy Input-Process-Output) ì˜ ê²½ìš°ì—” 다ìŒê³¼ 같습니다. (그림 첨부 í•„ìš”) === Version 0.4 - Implementation : Input === 10ë¶„ íœ´ì‹ - 1시 55분까지. 커피 보충등등; ì´ì •ë„ë©´ 처ìŒì— ìƒê°í•´ë‘” 뼈대가 ë‚˜ì™”ë‹¤ê³ ìƒê°ë©ë‹ˆë‹¤. (즉, 추후 ë” ì„¸ë¶„í™”ì‹œì¼œì„œ 나눌 수 있긴 하지만, ì´ì •ë„ì—ì„œë„ ë°”ë¡œ 구현으로 ë“¤ì–´ê°€ëŠ”ë° ë³„ ë¬¸ì œê°€ ì—†ì„ ê²ƒì´ë¼ê³ ìƒê°ë ì •ë„) 그럼. 하나씩 êµ¬í˜„ì„ í•´ 들어갑니다. ì–´ë–¤ 함수 ë˜ëŠ” 모듈 부터 êµ¬í˜„ì„ í•´ì•¼ í• ê¹Œ ê¶ë¦¬í–ˆì—ˆìŠµë‹ˆë‹¤. 어차피 ê° ëª¨ë“ˆë¶€ë¶„ì—ì„ ê·¸ ì¸ìžë¥¼ 구체ì 으로 명시시키지 않았습니다. ì´ì¯¤ì—서 DFD를 ê·¸ë¦¬ê³ ë°ì´í„°ì˜ íë¦„ì— ëŒ€í•´ í‘œí˜„í• ìˆ˜ë„ ìžˆê² ì§€ë§Œ, ì €ëŠ” ì¼ë‹¨ 소스 ìžì²´ì— ì´›ì ì„ ë§žì·„ìŠµë‹ˆë‹¤. 그래서 필요하면 ì¸ìžë¥¼ 하나씩 ë” ì¶”ê°€í•˜ê³ , 필요없어졌다 ì‹¶ìŒ ì¸ìžë¥¼ ì‚ì œí•˜ëŠ” ì‹ìœ¼ë¡œ ì ‘ê·¼í–ˆìŠµë‹ˆë‹¤. 그래서 따로 HIPO 다ì´ì–´ê·¸ëž¨ì— Argument 를 넘기는 ë¶€ë¶„ì„ í‘œí˜„í•´ë‘ì§€ 않았습니다. (워낙 ìžì£¼ 소스를 ê³ ì¹œ 관계로. 하지만, ì‹œê°„ì´ ë§Žì´ ê±¸ë¦° ì¼ì€ 아니였습니다.~) 구현 ìˆœì„œì— ëŒ€í•´ì„œ ì›ì¹™ì´ 있으면 좋ì„것ì´ëž€ íŒë‹¨í•˜ì— 다ìŒê³¼ ê°™ì€ ì›ì¹™ì„ ì„¸ì› ìŠµë‹ˆë‹¤. 1. 순차ì 으로 - 왼쪽 -> 오른쪽 순서로. 실행 ìˆœì„œì— ë”°ë¼ êµ¬í˜„í•œë‹¤. (실행 순서와 ìƒê´€ì—†ì´ ë…립ì 으로 따로 ìƒê°í•˜ì—¬ êµ¬í˜„í• ìˆ˜ 있습니다. ì´ëŠ” UnitTest 참조) 2. Depth-Module First. -> 깊ì´ê°€ 가장 깊ì´ì— 있는 ê²ƒë“¤ì´ ì‰¬ìš´ ë¬¸ì œì¼ ê²ƒì´ë¼ íŒë‹¨, 깊ì´ê°€ ê¹Šì€ ëª¨ë“ˆë¶€í„° 구현하기로 했습니다. (ì¼ìž¥ì¼ë‹¨ì¸ë°, ê·¸ ëŒ€ì‹ ìž˜ëª» ì ‘ê·¼í•˜ë©´ Bottom-Up ì´ ë˜ì–´ë²„릴 ìˆ˜ë„ ìžˆê¸° 때문ì—.. ì´ ê²½ìš° 해당 함수가 하는 ì¼ì„ 명확하게 해줄 필요가 ìžˆë‹¤ê³ ìƒê°ë©ë‹ˆë‹¤. ì „ì²´ 구조 ë‚´ì—ì„œì˜ ì—í• ì„ ìžŠì–´ì„ ì•ˆë˜ê² ì£ .) 구현 ìˆœì„œì— ëŒ€í•œ ì›ì¹™ì„ 잡았으면 êµ¬í˜„ì„ í•´ë´…ë‹ˆë‹¤. ì¼ë‹¨ Input ë¶€ë¶„ì„ êµ¬í˜„í•˜ê¸°ë¡œ ì •í•´ì¡Œê³ ìš”. (ìˆœì„œìƒ ê°€ìž¥ 왼쪽) ê·¸ 중 가장 깊ì´ê°€ ê¹Šì€ InputBoardSize, InputStartRoachPosition, InputRoachJourney 중 InputBoardSize 를 구현합니다. {{{~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 등으로 ê²°ê³¼ê°’ì„ í™•ì¸í•´ë³´ê¸°. 다ìŒì€ 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 ë¶€ë¶„ì„ ì¼ë‹¨ 완성했습니다. === Version 0.5 - Implementation : ScheduledWalk === ë‹¤ìŒ ëª¨ë“ˆ - ScheduledWalk() ê´€ë ¨. Depth First ì— ìž…ê°í•˜ì—¬. ê·¸ë¦¬ê³ ì´ì¯¤ì—서 TestDrivenDevelopment 를 약간 가미해봅시다. (ê´€ë ¨ 페ì´ì§€ 참조, ë˜ëŠ” ["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 를 í†µê³¼í• ë•Œê¹Œì§€ 코드를 작성하면 ë˜ê² ì£ . 추후 ë”가가 ìž‘ë™ì´ ì´ìƒí•˜ë‹¤ë¼ê³ 한다면, 1. ì¼ë‹¨ 해당 ë¬¸ì œì¼ ëª¨ë“ˆì„ ì²´í¬í•œë‹¤. 2. Test Code 를 확ì¸í•´ë³¸ë‹¤. 3. ì‹¤ì œ 함수 ëª¨ë“ˆì„ í™•ì¸í•´ë³¸ë‹¤. ì˜ ê³¼ì •ìœ¼ë¡œ 디버깅 ê³¼ì •ì„ ë§Œë“¤ì–´ë‚¼ 수 ìžˆê² ìŠµë‹ˆë‹¤. 코드를 작성합니다. {{{~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 를 ëŠ˜ë ¤ë³´ê¸°. (ì´ ì‚¬ì´ì¦ˆì— ë”°ë¼ êµ¬í˜„ì˜ ë‚œì´ë„ê°€ 있습니다. 테스트와 ë‹¤ìŒ í…ŒìŠ¤íŠ¸ ìž‘ì„±ê³¼ì˜ ì‹œê°„ì´ ê¸¸ì–´ì§ˆìˆ˜ë¡ ì–´ë µìŠµë‹ˆë‹¤. ê·¸ ë§Œí¼ ìƒê°ì„ ì¶”ìƒì 으로 한다는 ëœ»ì¼ ìˆ˜ 있으니까요.) 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를 ìž‘ì„±í•˜ê³ êµ¬í˜„í•˜ë©´ ë©ë‹ˆë‹¤. {{{~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ë¶„. 재개~ ì „ì²´ 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