一、分析
令n=3,以3x3的魔方矩阵为例,可以看到:
1、填充数字是从1~n*n的连续整数(回答程序边界在哪里的问题);
2、第一个元素1的位置在第0行第1列,即matrix[0][n/2](回答程序从何处开始的问题);
3、其他元素(回答如何根据当前位置,确定下一个位置的问题):
1)下一个填充位置为当前位置的上一行,下一列,如果当前位置行标为0,则下一个位置行标为n-1=2,如果当前位置列标为n-1=2,则下个元素列标为0;那么在这里,就构成了n=3个数字的循环结构,可以采用取余的方式,省去很多if、else的判断。即:i = (i-1+n)%n,j = (j+1+n)%n,左侧i、j表示下一个位置,右侧表示当前位置。
2)如果第(i-1+n)%n个位置已经占用,则向下直到找到未被填充的位置,作为下一个元素的位置。
二、程序设计
1、准备
- num = 1;
- 一个n*n矩阵matrix[n][n],初始元素全为0;
- 两对坐标(a,b)、(c,d),分别代表当前位置和下一个位置,a=0,b=n/2;
2、步骤
- (c,d)保存当前坐标;
- a = (a-1+n)%n, b = (b+1+n)%n 寻找下一个位置,如果matrix[a][b] != 0,从上一个位置向下寻找(a=++c),直到找到matrix[a][b] = 0的位置;
- matrix[a][b] = num++;
- 直到num=n*n,程序结束;
三、代码
void PrintMagicMatrix(int n) {
if (n % 2 == 0) {
return;
}
int array[n][n], num = 1, a = 0, b = n / 2, c, d;
//初始化矩阵
memset(array, 0, sizeof(int) * n * n);
array[a][b] = num++;
while (num <= n * n) {
//e、f记录上一个点的位置
c = a;
d = b;
a = (a + n - 1) % n;
b = (b + n + 1) % n;
while (array[a][b] != 0) {
a = ++c;
b = d;
}
array[a][b] = num++;
}
for (int k = 0; k < n; ++k) {
for (int l = 0; l < n; ++l) {
printf("%3d", array[k][l]);
}
printf("\n");
}
}