魔方阵还是一个比较有难度的C代码。魔方阵分为奇数魔方阵和偶数魔方阵,而偶数魔方阵中又分为能被4整除的偶数魔方阵和不能被4整除的偶数魔方阵。
下面是能被4整除的偶数 (4K) 魔方阵代码:
在写代码之前我们要先了解能被4整除的偶数魔方阵的规则:
(1) 先将整个方阵划分成k*k个4阶方阵,然后在每个4阶方阵的对角线上做记号
(2) 由左而右、由上而下,遇到没有记号的位置才填数字,但不管是否填入数字,每移动一格数字都要加1
(3) 自右下角开始,由右而左、由下而上,遇到没有数字的位置就填入数字,但每移动一格数字都要加1
#include<stdio.h>
#include <assert.h>
//偶数魔方阵 4K(能被4整除) //4 8 12 16
void Magic2()
{
#define ROW 8
#define COL ROW
assert(ROW % 2 == 0 && ROW % 4 == 0);
int arr[ROW][COL] = { 0 };
int tmp = 1;
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
arr[i][j] = tmp++;
}
}
int row1 = 0;//主对角线行
int col1 = 0;//主对角线列
int row2 = 0;//副对角线行
int col2 = 0;//副对角线列
//总体划分K*K块(i*j)
for (int i = 0; i < (ROW / 4); i++)//i指向行
{
for (int j = 0; j < COL / 4; j++)//j指向列
{
row1 = 4 * i;
col1 = 4 * j;
row2 = 4 * i;
col2 = 4 * j + 3;
for (int k = 0; k < 4; k++)
{
arr[row1][col1] = (ROW * COL + 1) - arr[row1][col1];
arr[row2][col2] = (ROW * COL + 1) - arr[row2][col2];
row1++;
col1++;
row2++;
col2--;
}
}
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf("%-3d", arr[i][j]);
}
printf("\n");
}
#undef ROW
#undef COL
}
int main()
{
Magic2();
return 0;
}
调试结果如下:
下面是不能被4整除的偶数(4K+2)魔方阵代码 :
在写代码之前我们要先了解不能被4整除的偶数魔方阵的规则:
1. 将其划分4个奇数魔方阵,左上角将1~ROW*COL/4,按照奇数魔方阵的规则放进去,接下来是右下,右上,左下,依次赋值
//上下标记的数字进行交换
标记的规则:1. 右半边大于k+2的列(从1开始)
2. 左半边,上下两个块最中心的点进行交换
3. 左半边小于中心列的列(除了上下半边最中心的行的第一列的那个值不用交换)(从1开始)
#include<stdio.h>
#include <assert.h>
void Magic3()
{
#define ROW 10
#define COL ROW
assert(ROW % 2 == 0 && ROW % 4 != 0);
int arr[ROW][COL] = { 0 };
int currow = 0;
int curcol = ROW / 4;
arr[currow][curcol] = 1;
//左上角
for (int i = 2; i <= ROW * COL / 4; i++)
{
if (arr[(currow - 1 + ROW / 2) % (ROW / 2)][(curcol + 1) % (COL / 2)] == 0)
{
currow = (currow - 1 + ROW / 2) % (ROW / 2);
curcol = (curcol + 1) % (COL / 2);
}
else
{
currow = (currow + 1) % (ROW / 2);
}
arr[currow][curcol] = i;
}
//右下角
currow = ROW / 2;
for (int i = 0; i < ROW / 2; i++, currow++)
{
curcol = COL / 2;
for (int j = 0; j < COL / 2; j++, curcol++)
{
arr[currow][curcol] = arr[i][j] + (ROW * COL / 4);
//curcol++;
}
//currow++;
}
//右上角
currow = 0;
for (int i = ROW / 2; i < ROW; i++, currow++)
{
curcol = COL / 2;
for (int j = COL / 2; j < COL; j++, curcol++)
{
arr[currow][curcol] = arr[i][j] + (ROW * COL / 4);
//curcol++;
}
//currow++;
}
//左下角
currow = ROW / 2;
for (int i = 0; i < ROW / 2; i++, currow++)
{
curcol = 0;
for (int j = COL / 2; j < COL; j++, curcol++)
{
arr[currow][curcol] = arr[i][j] + (ROW * COL / 4);
//curcol++;
}
//currow++;
}
//2.改标记点,先改右半边大于k+2的列 k=ROW/4 右半边的k=ROW/4+ROW/2 右半边的k+2 = ROW/4+ROW/2+2
for (int j = ROW / 4 + ROW / 2 + 2; j < COL; j++)//j现在就指向大于k+2的那一列 如果j合法,则上下交换
{
for (int i = 0; i < ROW / 2; i++)
{
int tmp = arr[i][j];
arr[i][j] = arr[i + ROW / 2][j];
arr[i + ROW / 2][j] = tmp;
}
}
//3.左半边,上下两个块的中心点
int tmp = arr[ROW / 4][COL / 4];
arr[ROW / 4][COL / 4] = arr[ROW / 4 + ROW / 2][COL / 4];
arr[ROW / 4 + ROW / 2][COL / 4] = tmp;
//4.左半边小于k+1的列(除了上下半边最中心的行的第一列的那个值不用交换)(从1开始)
for (int i = 0; i < ROW / 2; i++)
{
for (int j = 0; j < ROW / 4; j++)
{
if (i == ROW / 4 && j == 0)
{
continue;
}
int tmp = arr[i][j];
arr[i][j] = arr[i + ROW / 2][j];
arr[i + ROW / 2][j] = tmp;
}
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf("%-3d", arr[i][j]);
}
printf("\n");
}
#undef ROW
#undef COL
}
int main()
{
Magic3();
return 0;
}
调试结果如下: