#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
int **Magic1(int n) //奇数阶魔方阵
{
assert(n%2 != 0);
int **arr = (int **)malloc(sizeof(int *)*n); //创建二维数组存放魔方阵
for(int i = 0;i<n;i++)
{
arr[i] = (int *)calloc(n,sizeof(int)); //所有元素赋值为零,以判断每个位置上是否放置了有效数字
}
int row = 0;
int col = n/2;
for(int i = 0;i<n*n;i++)
{
arr[row][col] = i+1; //从0行正中开始赋值
arr[(row-1+n)%n][(col+1)%n] == 0?row = (row-1+n)%n,col = (col+1)%n:row = (row+1)%n; //如果当前位置的前一行下一列数字是0,则把下一个数字放在那里,否则放在当前位置的下一行同列
}
return arr;
}
int **Magic2(int n) //单偶数阶魔方阵(能被2整除,不能被4整除)(思路:可以分为4个奇数阶矩阵)
{
assert(n%2 == 0 && n%4 != 0);
int **arr = (int **)malloc(sizeof(int *)*n);
for(int i = 0;i<n;i++)
{
arr[i] = (int *)calloc(n,sizeof(int)); //所有元素赋值为零,原理同上
}
int row = 0;
int col = n/4;
for(int i = 0;i<(n*n)/4;i++) //左上n/2阶矩阵赋值
{
arr[row][col] = i+1;
arr[(row-1+n/2)%(n/2)][(col+1)%(n/2)] == 0?row = (row-1+n/2)%(n/2),col = (col+1)%(n/2):row = (row+1)%(n/2); //奇数阶矩阵,原理同上
}
row = n/2;
for(int i = 0;i<n/2;i++,row++) //右下n/2阶矩阵赋值
{
col = n/2;
for(int j = 0;j<n/2;j++,col++)
{
arr[row][col] = arr[i][j]+(n*n)/4; //该矩阵当前位置元素值等于左上矩阵当前位置元素值与(n*n)/4之和
}
}
row = 0;
for(int i = 0;i<n/2;i++,row++) //右上n/2阶矩阵赋值
{
for(int j = n/2;j<n;j++)
{
arr[row][j] = arr[i+n/2][j]+(n*n)/4; //该矩阵当前位置元素值等于右下矩阵当前位置元素值与(n*n)/4之和
}
}
row = n/2;
for(int i = 0;i<n/2;i++,row++) //左下n/2阶矩阵赋值
{
for(int j = 0;j<n/2;j++)
{
arr[row][j] = arr[i][j+n/2] + (n*n)/4; //该矩阵当前位置元素值等于右上矩阵当前位置元素值与(n*n)/4之和
}
}
int t;
for(int i = 0;i<n/2;i++) //n=4*k+2阶矩阵左半边数列行转换,转换规则1:左上矩阵当前位置元素值与左下矩阵相同位置元素值对调
{
int col = 0;
i == n/4?col += n/4:col; //转换规则2:若为左上矩阵中间行,则从中间行中间列开始,其它从0列开始,每行从左往右转换k个数字
for(int j = 0;j<n/4;j++,col++)
{
t = arr[i][col];
arr[i][col] = arr[i+n/2][col];
arr[i+n/2][col] = t;
}
}
t = 0;
for(int i = 0;i<n/2;i++) //n=4*k+2阶矩阵右半边数列行转换
{
for(int j = n/2+n/4+2;j<n;j++) //从n/2+k+2列开始转换,直到最后一列,转换规则:右上矩阵当前位置与右下矩阵相同位置元素值对调
{
t = arr[i][j];
arr[i][j] = arr[i+n/2][j];
arr[i+n/2][j] = t;
}
}
return arr;
}
int **Magic3(int n) //双偶数阶,能同时被2和4整除(思路:把n阶矩阵分为(n/4)*(n/4)个小4阶矩阵,每个小矩阵对角线位置做出变换即可)
{
assert(n%4 ==0);
int **arr = (int **)malloc(n*sizeof(int *)); //创建二维数组存放矩阵
for(int i = 0;i<n;i++)
{
arr[i] = (int *)malloc(n*sizeof(int));
}
int t = 0;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
arr[i][j] = t+1; //赋值1到n*n
t++;
}
}
int row1 = 0;
int col1 = 0;
int row2 = 0;
int col2 = 0;
for(int i = 0;i<n/4;i++) //控制从第i大行第一个矩阵开始转换
{
row1 = row2 = 4*i;
col1 = 0;
col2 = 3;
for(int j = 0;j<n/4;j++) //控制从第j大列开始矩阵转换
{
row1 = row2 = 4*i;
col1 = 4*j;
col2 = 3 + 4*j;
for(int k = 0;k<4;k++)
{
arr[row1][col1] = n*n+1-arr[row1][col1]; //主对角线数字转换,转换规则:当前位置新值=n*n+1-旧值
row1++;
col1++;
arr[row2][col2] = n*n+1-arr[row2][col2]; //副对角线数字转换,转换规则:当前位置新值=n*n+1-旧值
row2++;
col2--;
}
}
}
return arr;
}
int main()
{
int **arr = Magic3(12);
for(int i = 0;i<12;i++)
{
for(int j = 0;j<12;j++)
{
printf("%-3d ",arr[i][j]);
}
printf("\n");
}
free(arr);
return 0;
}