본문 바로가기

강의자료/C/C++

049. 2차배열로 마방진을 만들어보자.


◈ 이 글은 강의를 위하여 제가 직접 작성한 내용입니다. 따라서 퍼가실 경우, 출처를 명확히 해주시기 바랍니다!!
◈ This ariticle was written by me for teaching. So if you want to copy this article, please clarify the source!!



// 마방진 작성하기.
(1) 다음 규칙에 따라 마방진 클래스를 작성하시오.(7x7 마방진을 기준으로 설명)
(2) 마방진 숫자를 저장할 2차원 배열 z를 만드시오.
(3) 배열 z에 (행, 렬)을 기준으로 첫행, 가운데열(0, 3)에 시작 숫자(1)를 입력한다.
(4) 숫자가 입력된 위치에서 (-1, -1)을 이동한다.
(5) 현재 위치가 마방진의 범위를 벗어날 경우 반대편으로 이동한다.
-- 예) (-1, 2)일경우, (6, 2)로 수정한다. <- 숫자 2가 입력되어야 할 위치.
-- 예) (3, -1)일 경우, (3, 6)로 수정한다.
-- 예) (-1, -1)일경우, (6, 6)로 수정한다.
(6) 이동한 위치(또는 수정된 위치)에 다음번 숫자를 입력한다.
(7) 단, 숫자가 이미 입력되어 있는 경우에는 원래 위치에서 아래로 한칸 이동 후 입력한다.
-- 예) (0, 2)에서 (-1, -1)이동하여 (6, 1)이 되었는데 숫자가 이미 입력되었을 경우,
-- (0, 2)에서 (+1, 0)이동하여 (1, 2)에 숫자를 입력한다.
(8) 1부터 49까지의 숫자가 모두 채워질때까지 (4)~(7)번 과정을 반복한다.

/*
// 마방진 작성하기.
(1) 다음 규칙에 따라 마방진 클래스를 작성하시오.(7x7 마방진을 기준으로 설명)
(2) 마방진 숫자를 저장할 2차원 배열 z를 만드시오.
(3) 배열 z에 (행, 렬)을 기준으로 첫행, 가운데열(0, 3)에 시작 숫자(1)를 입력한다.
(4) 숫자가 입력된 위치에서 (-1, -1)을 이동한다.
(5) 현재 위치가 마방진의 범위를 벗어날 경우 반대편으로 이동한다.
	예) (-1, 2)일경우, (6, 2)로 수정한다.  <- 숫자 2가 입력되어야 할 위치.
	예) (3, -1)일 경우, (3, 6)로 수정한다.
	예) (-1, -1)일경우, (6, 6)로 수정한다.
(6) 이동한 위치(또는 수정된 위치)에 다음번 숫자를 입력한다.
(7) 단, 숫자가 이미 입력되어 있는 경우에는 원래 위치에서 아래로 한칸 이동 후 입력한다.
	예) (0, 2)에서 (-1, -1)이동하여 (6, 1)이 되었는데 숫자가 이미 입력되었을 경우,
	(0, 2)에서 (+1, 0)이동하여 (1, 2)에 숫자를 입력한다.
(8) 1부터 49까지의 숫자가 모두 채워질때까지 (4)~(7)번 과정을 반복한다.
*/
#include 
using namespace std;

class Magic
{
	int size;
	int **magic;

public:
	Magic(int s) : size(s)
	{
		magic = new int*[size];
		for(int i=0; i < size; i++)
		{
			magic[i] = new int[size];
			memset(magic[i], 0, size*sizeof(int));
		}

		Generate();
	}

	~Magic()
	{
		for(int i=0; i < size; i++)
		{
			delete [] magic[i];
		}
		delete [] magic;
	}

	void Generate()
	{
		int row=0;			//상단 
		int col=size/2;		//중앙
		for(int i=1; i <= size*size; i++)
		{
			magic[row][col]=i;
			row--, col--;
			fixPos(row, col);
		}
	}

	void fixPos(int& row, int& col)
	{
		// 범위를 벗어난 경우, 반대편으로 이동한다.
		if(row < 0) 
		{
			row=size-1;
		}
		if(col < 0) 
		{
			col=size-1;
		}

		// 해당 위치에 이미 값이 존재할 경우,
		if(magic[row][col] != 0)
		{
			row+=2;	// 제자리로 돌린 후 아래로 한칸 더 간다.
			col++;	// 제자리로 돌아간다.
		}

		// 범위를 벗어난 경우, 반대편으로 이동한다.
		if(row > size-1) 
		{
			row=row-size;	// 아래쪽으로 두칸을 이동하므로 0또는 1이 될수가 있다.
		}
		if(col > size-1) 
		{
			col=col-size;
			//col = 0;		// 어차피 오른쪽으로 한칸만 이동하므로 0이 될 수 밖에 없다.
		}
	}

	void Show()
	{
		cout << "[마방진 " << size << "X" << size << " ]" << endl;
		for(int i=0; i < size; i++)
		{
			for(int n=0; n < size; n++)
			{
				cout.width(5);
				cout << left << magic[i][n];
			}
			cout << endl;
		}
		for(int i=0; i < size; i++)
			cout << "-----";
		cout << endl;
	}
};

void main()
{
	Magic magic3x3(3);
	magic3x3.Show();

	Magic magic5x5(5);
	magic5x5.Show();

	Magic magic7x7(7);
	magic7x7.Show();
}