brunch

You can make anything
by writing

C.S.Lewis

by Cylogic Aug 07. 2018

마방진 만들기. 2 -코딩수업#12

앞선 이야기에서 마방진을 만드는 기본 방법을 이해했을 것으로 믿는다.


3X3이나 5X5와 같은 정도의 마방진을 만든다면 눈으로 보고 하는 것도 별 문제가 없겠지만, 만일 128X128의 마방진을 만든다면 눈으로 보고 연필을 사용해서 마방진을 만드는 것은 쉬운 일이 아니다. 

이렇게 데이터의 양이 커져서 쉽게 계산하기 어렵거나, 잘 정리된 문제풀이 방법을 가지고 그 풀이를 체계화하는 것이 코딩이다.

이제 하나씩 앞 선 방법을 코딩으로 풀어보자.


만일 7X7 인 마방진을 만든다고 가정해 보자.


1. 

크기를 size라는 변수에 미리 입력해 두자.

var size=7;


2. 

가장 먼저 7X7인 변수의 방 49개를 만들어야 한다. 이 숫자는 어느 크기의 마방진을 만드냐에 따라 언제든 달라진다.

javascript에서 2차원 배열을 만드는 다양한 방법이 있겠지만 다음과 같은 형식으로 rooms라는 방을 만드는 것을 진행해 보자.


var rooms = [];

for (var r=0; r<size; r++){

      rooms[r]=[];

      for (var c= 0; c<size; c++) rooms[r][c]=0;

}


size가 7 이므로 7개의 행과 열이 있는 배열이 만들어졌다.

그리고 이렇게 만들어진 각 방에는 모두 0이라는 숫자를 넣었다.

만일 어느 방에 0이 들어가 있으면 그 방은 비어 있는 것이고 그렇지 않다면 방에 이미 숫자가 들어가 있는 것으로 규칙을 정하자.


3. 

만들어진 방의 첫 줄 가운데 자리에 1을 넣는다.

그렇다면 행 번호(row)는 0 (코딩을 할 때 방 번호는 0부터 시작함을 기억하시라)

열(col)의 번호는 size/2의 몫으로 생각하면 된다.

size가 7 이므로 7/2=3 (몫)이고 나머지 1은 무시하자.


var col=Math.trunc(size/2);

var row=0;

 

4. 

첫 줄에 숫자를 넣었으므로 우측 아래에 다음 숫자를 넣는 것으로 원칙을 정하자.

row라는 변수를 행로 하고, col이라는 변수를 열이라고 하면

다음 숫자의 위치는 현재의 row+1, col+1 이 될 것이다.

그 숫자가 size를 벗어나는 숫자(현재의 예로는 7)가 되면 0으로 세팅하면 된다.

    

이러한 작업을 1부터 49 (7x7)까지 반복할 것이다.

그리고 앞 이야기에서 이야기한 것처럼 자리가 비어 있지 않으면, 

규칙에 따라 다른 자리에 숫자를 넣을 것이다.


for (var i=1;i<=size*size;i++){ // 1부터 마방진의 최대수까지 현재는 49

    rooms[row][col]=i; // 현재의 자리에 숫자를 넣는다.

    row++;                      // 다음 숫자가 들어갈 자리를 정한다.

    col++;

    if (row>=size) row=0; // 만일 자리의 행이 격자의 한계를 벗어나면 0으로

    if (col>=size) col=0;    // 만일 자리의 열이 격자의 한계를 벗어나면 0으로

    if (rooms[row][col]!=0) { // 현재의 자리가 비어있지 않으면

        col--;                               // 열은 원래 자리로

        row-=2;                           // 행은 원래 자리보다 하나 적게 

    }

    if (row==-2) row=size-2;  // 행이 -2일 경우에는 행은 격자의 끝행보다 하나 아래로

    if (row==-1) row=size-1;  // 행이 -1일 경우에는 행은 격자의 끝행에

    if (col==-1) col=size-1;    // 열이 -1이면 열은 격자의 끝열에

}


이렇게 홀수 마방진이 완성되었다.


5. 

이렇게 완성된 마방진을 찍어보자.

마방진이 대각선으로도 같은 합을 가지기 위해서는 상단 중앙에 1이 있는 열을 배치하고,

우측 아래로 진행한 증가값이 있는 줄을 제일 아래에서부터 반복하여 인쇄해야 한다.

그래서 출력의 방법을 아래와 같이 진행해 보자.


for (var c=0;c<size;c++) document.writeln(pad2(rooms[0][c])); // 첫 줄 먼저 찍고

document.writeln("<br/>"); // 행 찍고 줄 바꿈 할 것

for (var r=size-1;r>0;r--){   // 마지막 행부터 거꾸로 인쇄

     for (var c=0;c<size;c++) document.writeln(pad2(rooms[r][c]));

     document.writeln("<br/>"); // 행 찍고 줄 바꿈 할 것


function pad2(num) {  // 숫자의 칸 위치를 맞추기 위하여 1자리 숫자 앞에 0을 붙임

     return (num < 10 ? '0' : '') + num

}


전체 코드를 확인해 보면


30 39 48 01 10 19 28

38 47 07 09 18 27 29

46 06 08 17 26 35 37

05 14 16 25 34 36 45

13 15 24 33 42 44 04

21 23 32 41 43 03 12

22 31 40 49 02 11 20


위와 같은 출력을 얻을 수 있다.

엑셀에 해당 자료를 넣어 가로 세로 값을 확인해 보자.

이렇게 확인이 끝났다.


대입, 반복, 조건에 대한 판단 만을 가지고 또 하나의 문제 풀이가 완성된 것 같다.

size=9로 바꾸어 

9x9에서도 정확한 판이 만들어지는지 검사해 보자.




3, 5, 7 칸의 마방진과 동일하게 9x9에서도 코드의 결과는 동일하게 완벽한 마방진을 생성하는 것으로 나타난다.


<오류가 있어서 코드와 표를 수정하였습니다. - 2024-04-15

  오류를 발견해 주신 "차므로" 님께 감사드립니다.>



매거진의 이전글 마방진 만들기.1 -코딩수업#11
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari