魔方阵还是一个比较有难度的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 ROWassert(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 ROWassert(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+2for (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;
}
调试结果如下: