-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOddMagicSquare.cpp
148 lines (139 loc) · 4.61 KB
/
OddMagicSquare.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include "OddMagicSquare.h"
/// <summary>
/// 문제
/// 홀수 정사각형의 크기를 입력 받은 후, 가로 세로 대각선의 합이 일정한 마방진을 출력하는 프로그램을 작성하시오.
///
/// 마방진이란 1부터 N * N까지의 숫자를 한 번씩만 써서 정사각형에 배치하여 가로와 세로, 그리고 대각선의 합이 같도록 하는 것이다.
///
/// 다음의 순서에 따라 각 위치에 차례대로 값을 넣는다.
/// 1. 첫 번째 숫자인 1을 넣는 위치는 첫 번째 행 가운데이다.
/// 2. 숫자가 N의 배수이면 바로 아래의 행으로 이동하여 다음의 수를 넣고
/// 3. 그렇지 않으면 왼쪽 위로 이동하여 다음의 숫자를 넣는다.
/// 만약 행이 첫 번째를 벗어나면 마지막 행으로 이동하고, 열이 첫 번째를 벗어나면 마지막 열로 이동한다.
///
/// 입력 형식
/// 정사각형의 크기 n(2부터 100사이의 홀수)을 입력받는다.
///
/// 출력 형식
/// 위에서 언급한 형태로 정사각형의 내부 숫자를 차례로 채운 후의 모습을 출력한다. 숫자 사이는 공백으로 구분한다.
///
/// 입력 예 /// 입력 예
/// 3 /// 5
///
/// 출력 예 /// 출력 예
/// 6 1 8 /// 15 8 1 24 17
/// 7 5 3 /// 16 14 7 5 23
/// 2 9 4 /// 22 20 13 6 4
/// /// 3 21 19 12 10
/// /// 9 2 25 18 11
///
/// Hint!
/// <코드>
/// void fill()
/// {
/// int x = 1; // 행 - 처음에는 1
/// int y = n / 2 + 1; // 열 - 초기값 중앙
/// int i; // 배열에 순서대로 채울 값 (for 문에 사용할 변수)
/// int end = n * n; // 배열에 채울 마지막 값
///
/// for (i = 1; i <= end; i++) // 배열에 채울 값 1부터 end까지
/// {
/// arr[x][y] = i; // i를 배열의 현재 위치에 넣는다.
/// if (i % n == 0) x++; // 만약 현재의 수가 n의 배수이면 아래로 이동
/// else
/// {
/// x--, y--; // 왼쪽 위로 이동
/// if (x < 1) x = n; // x가 0이면 n으로
/// if (y < 1) y = n; // y가 0이면 n으로
/// }
/// }
/// }
///
/// <코드분석>
/// 06~07 : 행과 열을 처음에 넣어야 할 위치로 초기화 하고
/// 11~21 : 1부터 n * n 까지 각각 넣어야 할 위치에 차례대로 채워나가는 프로그램
/// 13~15 : i가 n의 배수이면 아래로 이동하고
/// 16~20 : 그렇지 않으면 왼쪽 위로 이동을 한 후 범위를 벗어나면 끝으로 이동시킨다.
///
/// <코드>
/// /* 채워야 할 위치(x, y)와 값(num)을 전달받아 */
/// /* 배열에서 해당 위치에 값을 넣고 다음의 위치와 값을 호출하는 재귀함수 */
///
/// void fill(int x, int y, int num)
/// {
/// if (num > n * n) return; // 수가 범위를 벗어나면 종료
/// if (x < 1) x = n; // x가 0이면 n으로
/// if (y < 1) y = n; // y가 0이면 n으로
/// arr[x][y] = num; // 배열 채우기
///
/// if (num % n == 0) fill(x + 1, y, num + 1); // num이 n의 배수이면 바로 아래 호출
/// else fill(x - 1, y - 1, num + 1); // 아니면 왼쪽 위 호출
/// }
///
/// <코드분석>
/// 이 함수는 전달받은 위치 한곳만 채우고 다음 위치를 호출하는 재귀함수이다.
/// 재귀함수 특성상 자신이 처리해야 할 위치 한 곳만 처리하고
/// (09) 다음 위치를 호출하면 임무가 끝난다.
/// (10~11) 다음 위치를 호출할 때 i가 n의 배수가 아니면 무조건 왼쪽 위를 호출했기 때문에
/// (11) 범위를 벗어난 경우 마지막 위치로 바꾸어 주는 작업이 필요하다.
/// (07~08) 범위를 벗어나는 호출이 들어오면 모든 작업이 끝나게 된다.
/// (06) 처음에는 첫 번째 행 중앙에 1을 채워야 하므로 메인에서는 아래와 같이 호출해야 한다.
/// fill(1, n / 2 + 1, 1);
///
/// http://www.jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=1338&sca=2020
/// </summary>
void OddMagicSquare::Code()
{
int n;
std::cin >> n;
int** arr = new int* [n];
for (int i = 0; i < n; i++)
{
arr[i] = new int[n];
std::fill_n(arr[i], n, 0);
}
int num{ 1 };
int i{ 0 }, j{ n / 2 };
while (num <= n * n)
{
if (arr[i][j] == 0)
{
arr[i][j] = num;
}
if (num % n == 0)
{
i++;
if (i >= n)
{
i = 0;
}
}
else
{
i--;
j--;
if (i < 0)
{
i = n - 1;
}
if (j < 0)
{
j = n - 1;
}
}
num++;
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
std::cout << arr[i][j] << ' ';
}
std::cout << '\n';
}
for (int i = 0; i < n; i++)
{
delete[] arr[i];
}
delete[] arr;
}