AI영재교육원 로고이미지

공지사항

RSS 페이스북 공유하기 트위터 공유하기 카카오톡 공유하기 카카오스토리 공유하기 네이버밴드 공유하기 프린트하기
마방진 알고리즘을 시각화 C언어 프로그래밍으로 쉽게 이해하는 법
작성자 정보영재 등록일 15.09.24 조회수 438

 

마방진 알고리즘을 시각화 C언어 프로그래밍으로 쉽게 이해하는 법

http://me2.do/xwioROYr

  
 
마방진(Magic Square) 처리를 하는 알고리즘을 C언어와, 시각화 설계 방법인 쏙(SOC: Structured Object Component)과 쏙을 지원하는 자동화 도구인 새틀(SETL: Structured Efficiency TooL)을 이용하여 표현해 보겠습니다.

1. 마방진 처리 
 
마방진 처리에는 여러가지 방법이 있습니다.
마방진 처리는 홀수차와 짝수차에 따라 다르고, 짝수차는 4의 배수와 아닌 수에 따라 달라집니다.
여기에서는 그 중 가장 간단한 형태의 홀수 마방진 처리 알고리즘을 다뤄보겠습니다. 홀수 마방진 처리를 그림으로 나타내면 아래와 같습니다.
 
                                                  
 
<홀수 마방진 처리 방법>
1. 첫 번째 행의 가운데 열 위치에서 '1'부터 시작합니다.
2. 이동 방향에서 행은 감소하는 방향, 열은 증가(또는 감소)하는 방향입니다.
    (위의 그림은 왼쪽 위의 방향으로 채워갑니다.)
3. 이동중 행렬의 범위를 벗어날 경우의 처리입니다.
   - 행이 벗어난 경우, 반대편 행으로 옮깁니다.
   - 열이 벗어난 경우, 반대편 열로 옮깁니다.
4. 다른 수에 막히는 경우 다음 행부터 시작합니다.
    (N차일 경우 N의 배수 다음 수에서 막히게 됩니다. 위 그림에서는 3 다음 수인 4에서 막힙니다.)

이 네가지 규칙으로 알고리즘을 작성하면, 홀수 마방진 배열을 만들 수 있습니다.
 
 쏙(SOC)

       
 
  프로그램
 
#include
 
#define MAXSIZE 100
 
void main(void) {
   int yAxis = 0;                                                   // 홀수 마방진 행위치
   int xAxis = 0;                                                   // 홀수 마방진 열위치
   int numCnt = 0;                                                // 홀수 마방진 정수 카운터
   int magicSquareArr[MAXSIZE][MAXSIZE];        // 홀수 마방진 배열
   int remain;                                                      // 나머지
   int magicSquareSize;                                       // 홀수 마방진 크기
 
   //.홀수 마방진 처리를 한다. 
   {
 
      //.홀수 마방진 크기를 입력받는다. 
      {
 
         //.홀수를 입력받을 때만 다음으로 진행한다. 
         for (;;) {
            printf("\n홀수 마방진의 크기를 두자리 수 이내의 홀수로 입력하세요=>");
            scanf_s("%d", &magicSquareSize, sizeof(magicSquareSize));
            fflush(stdin);
            remain = magicSquareSize % 2;
            if (remain==1) break;
            printf("\n홀수 마방진의 크기를 짝수로 입력하셨습니다.\n");
         }
      }
      
//.홀수 마방진 설정 처리를 한다. 
      {
         xAxis = magicSquareSize / 2;   // 열 위치를 배열의 중앙으로 설정 
         numCnt = 1;                           // 정수 카운터를 1로 초기화
 
         //.홀수 마방진의 크기만큼 정수를 카운트하여 대입한다. 
         while (!(numCnt > (magicSquareSize * magicSquareSize))) {
             // 마방진 배열에 정수 카운터 값 대입
             magicSquareArr[yAxis][xAxis] = numCnt;  
            // 나머지 = 정수 카운터 % 마방진 크기
            remain = numCnt % magicSquareSize;      
 
            //.numCnt가 홀수 마방진 배열 크기의 배수이면 아래 위치로 이동한다. 
            if (remain == 0) { 
               yAxis++;                          // 행 위치 1 증가
 
               //.행 위치가 홀수 마방진 크기에 도달하면 초기화 
               if (yAxis>(magicSquareSize - 1)) { 
                  yAxis = 0;                     // 행 위치 0으로 초기화
               }
            }
            else {
               // numCnt가 배열 크기의 배수가 아니면 왼쪽 위로(대각선) 이동 
               yAxis--;                          // 행 위치 1 감소
               xAxis--;                          // 열 위치 1 감소
 
               //.행 위치가 0보다 작아지면 행 위치를 배열 크기로 설정 
               if (yAxis < 0) { 
                  // 반대 방향의 행으로 이동한다. 
                  yAxis = magicSquareSize - 1;
               }

               //.열 위치가 0보다 작아지면 열 위치를 배열 크기로 설정 
               if (xAxis < 0) { 
                  // 반대 방향의 열로 이동한다. 
                  xAxis = magicSquareSize - 1;
               }
 
               //.열 위치가 배열 크기보다 커지면 0으로 초기화 
               if (xAxis >(magicSquareSize - 1)) { 
                  xAxis = 0;                            // 열 위치 0으로 초기화
               }
            }
            numCnt++;                                // 정수 카운터 1 증가
         }
      }
 
      //.홀수 마방진 처리 결과를 출력한다. 
      {
         printf("\n%d x %d 홀수 마방진의 처리 결과\n", magicSquareSize, magicSquareSize);
         printf("=================================\n\n");
         
         //.홀수 마방진의 내용을 출력한다. 
         for (yAxis=0; yAxis 
            //.연속된 정수 한 줄을 배열에서 꺼내 출력한다. 
            for (xAxis=0; xAxis               printf("%4d ", magicSquareArr[yAxis][xAxis]);
            }
            printf("\n");
         }
      }
   }
}

 
 실행화면
 
       
 
 
2. 마방진 처리 알고리즘의 추상화 수준별 처리 흐름
 
<표1>은 마방진 처리 알고리즘의 추상화 수준별 처리 흐름을 나타내기 위해 사용된 그림이며, 그림과 관련하여 상세한 설명은 아래와 같습니다.

 
 
 
홀수 마방진 처리 알고리즘의 추상화 수준별 처리 흐름을 알아보면 다음과 같습니다.

         
 
위의 쏙으로 표현한 홀수 마방진 처리 알고리즘에서 맨 왼쪽의 절차는 추상화 수준 0으로 가장 개념화한 것을 의미하며, 오른쪽의 절차는 추상화 수준 5로 구체화한 것을 의미합니다. 즉, 6단계의 추상화가 이루어진 것입니다. 
홀수 마방진 처리 알고리즘 전체의 흐름을 목표-수단 계열의 논리 흐름으로 나타내면 다음과 같습니다.
 
(1) 추상화 수준 0과 1을 목표-수단 계열로 파악하는 경우의 논리 흐름
“홀수 마방진 처리를 한다."는 목표를 확인하고 나서, 목표를 달성하기 위한 수단으로 아래와 같은 절차를 거칩니다.
            홀수 마방진 크기를 입력받는다.
            홀수 마방진 설정 처리를 한다.
            홀수 마방진 처리 결과를 출력한다.

          
 
(2) 추상화 수준1과 2를 목표-수단 계열로 파악하는 경우의 논리 흐름
첫째, 
 "홀수 마방진 크기를 입력받는다.”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.
                   홀수를 입력받을 때만 다음으로 진행한다.

       
 
둘째,  
"홀수 마방진 설정 처리를 한다.”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.
                   xAxis = magicSquareSize / 2;  ※열 위치를 배열의 중앙으로 설정 
                   numCnt = 1;                   ※정수 카운터를 1로 초기화
                   홀수 마방진의 크기만큼 정수를 카운트하여 대입한다.

       
 
세째,  
"홀수 마방진 처리 결과를 출력한다.”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.
                   printf("\n%d x %d 홀수 마방진의 처리 결과\n", magicSquareSize, magicSquareSize);
                   printf("=================================\n\n");
                   홀수 마방진의 내용을 출력한다.

       
 
위와 같은 2단계 세부 절차를 진행하는 과정을 전체 논리 흐름으로 나타내면 다음과 같습니다.

       
 
(3) 추상화 수준2와 3를 목표-수단 계열로 파악하는 경우의 논리 흐름
첫째, 
"홀수를 입력받을 때만 다음으로 진행한다.”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.
              printf("\n홀수 마방진의 크기를 두자리 수 이내의 홀수로 입력하세요=>");
              scanf_s("%d", &magicSquareSize, sizeof(magicSquareSize));
              fflush(stdin);
              remain = magicSquareSize % 2;
 
① 사이끝되풀이 조건이 true 일 경우
마방진의 크기를 입력할 때, 사이끝되풀이 조건(remain==1)이 true 일 경우는 짝수를 입력한 것으로, 홀수를 입력할 때까지 되풀이
               printf("\n홀수 마방진의 크기를 짝수로 입력하셨습니다.\n");
  
       
 
② 사이끝되풀이 조건이 false 일 경우
마방진의 크기를 입력할 때, 사이끝되풀이 조건(remain==1)이 false 일 경우는 홀수를 입력한 것으로 루프 탈출

        
 
둘째, 
"홀수 마방진의 크기만큼 정수를 카운트하여 대입한다.”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.
 
① 앞끝되풀이 조건이 true 일 경우
아래 알고리즘에서 마방진의 크기를 9 로 입력하였으므로 magicSquareSize 는 9 입니다.
앞끝되풀이 제어 변수 numCnt 를 1 로 초기화하고, numCnt 값을 1씩 증가시켜  앞끝되풀이 조건(numCnt > (magicSquareSize * magicSquareSize)) 에서 numCnt 가 81 보다 작거나 같을 동안 되풀이
                       ※마방진 배열에 정수 카운터 값 대입       
                           magicSquareArr[yAxis][xAxis] = numCnt;     
                       ※나머지 = 정수 카운터 % 마방진 크기   
                           remain = numCnt % magicSquareSize;
                        numCnt가 홀수 마방진 배열 크기의 배수이면 아래 위치로 이동한다.
                        numCnt++;                              ※정수 카운터 1 증가

       
 
② 앞끝되풀이 조건이 false 일 경우
앞끝되풀이 제어 변수 numCnt 를 1 로 초기화하고, numCnt 값을 1씩 증가시켜  앞끝되풀이 조건(numCnt > (magicSquareSize * magicSquareSize)) 에서 numCnt 가 81 보다 크면 루프 탈출

         
 
세째, 
"홀수 마방진의 내용을 출력한다.”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.
 
① 되풀이 조건이 true 일 경우
(yAxis=0; yAxis
                  연속된 정수 한 줄을 배열에서 꺼내 출력한다.
                  printf("\n");

       
 
② 되풀이 조건이 false 일 경우
(yAxis=0; yAxis

       
 
(4) 추상화 수준3와 4를 목표-수단 계열로 파악하는 경우의 논리 흐름
첫째,
"numCnt가 홀수 마방진 배열 크기의 배수이면 아래 위치로 이동한다.”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.

① (remain == 0) 조건이 true 경우
                  yAxis++;                         ※행 위치 1 증가
                  행 위치가 홀수 마방진 크기에 도달하면 초기화
 
       
 
② (remain == 0) 조건이 false 일 경우
            ※numCnt가 배열 크기의 배수가 아니면 왼쪽 위로(대각선) 이동
                yAxis--;                         ※행 위치 1 감소
                xAxis--;                         ※열 위치 1 감소
            행 위치가 0보다 작아지면 행 위치를 배열 크기로 설정
            열 위치가 0보다 작아지면 열 위치를 배열 크기로 설정   
            열 위치가 배열 크기보다 커지면 0으로 초기화    
 
       
 
둘째, 
"연속된 정수 한 줄을 배열에서 꺼내 출력한다.”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.
 
① 되풀이 조건이 true 일 경우
(xAxis=0; xAxis 

                 printf("%4d ", magicSquareArr[yAxis][xAxis]); 

        
 
② 되풀이 조건이 false 일 경우
(xAxis=0; xAxis

       

(5) 추상화 수준4와 5를 목표-수단 계열로 파악하는 경우의 논리 흐름
첫째,
"행 위치가 홀수 마방진 크기에 도달하면 초기화”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.

① (yAxis>(magicSquareSize - 1)) 조건이 true 경우
                  yAxis = 0;                 ※행 위치 0으로 초기화
 
아래 알고리즘에서 magicSquareSize 값은 마방진 크기로 9 
        조건식 (yAxis>(magicSquareSize - 1))   =>    yAxis > 9-1   =>  yAxis > 8 
        따라서 yAxis 값이 8보다 크면 행의 위치를 0으로 초기화

       
 
② (yAxis>(magicSquareSize - 1) 조건이 false 일 경우

       
 

둘째,
"행 위치가 0보다 작아지면 행 위치를 배열 크기로 설정”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.

① (yAxis < 0) 조건이 true 경우
               ※반대 방향의 행으로 이동한다.
                   yAxis = magicSquareSize - 1;
 
아래 알고리즘에서 magicSquareSize 값은 마방진 크기로 9 이며, 조건식 (yAxis < 0 )이 true 경우 yAxis 값에 8 을 넣는다.
 
       
 
② (yAxis < 0) 조건이 false 일 경우

       
 
세째,
"열 위치가 0보다 작아지면 열 위치를 배열 크기로 설정”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.

① (xAxis < 0) 조건이 true 경우
               ※반대 방향의 열으로 이동한다.
                   xAxis = magicSquareSize - 1;
 
아래 알고리즘에서 magicSquareSize 값은 마방진 크기로 9 이며, 조건식 (xAxis < 0 )이 true 경우 xAxis 값에 8 을 넣는다.
 
       
 
② (xAxis < 0) 조건이 false 일 경우

       
 
네째,
"열 위치가 배열 크기보다 커지면 0으로 초기화”는 목표를 확인하고 나서, 목표 달성을 위한 수단으로 아래와 같은 절차를 거칩니다.

① (xAxis>(magicSquareSize - 1)) 조건이 true 경우
                  xAxis = 0;                 ※열 위치 0으로 초기화
 
아래 알고리즘에서 magicSquareSize 값은 마방진 크기로 9 이며,
조건식 (xAxis>(magicSquareSize - 1))   =>    xAxis > 9-1   =>  xAxis > 8 
따라서 xAxis 값이 8보다 크면 열의 위치를 0으로 초기화
 
       
 
② (xAxis >(magicSquareSize - 1)) 조건이 false 일 경우
 
       

이전글 정보영재교육원 협조 및 공지사항 알림
다음글 드론의 192가지 미래의 사용방법