题目:
用1~9这九个数字, 编成一个3行3列的矩阵, 使得每行,每列和对角线上的数字之和相等.
思路:
我们需要先理解构造幻方的底层逻辑:填充低阶且阶数为奇数的幻方,我们一般使用“罗伯法”去进行填充。我们以该题所需输出的三阶幻方举例:
首先,将数字1放入第一行中间的格子中:
1 | ||
向右上斜行,依从小到大的顺序填入数字,如果右上斜行超出了矩阵的上端,则将数字沉底到该列的最下端,比如这里我们要填的“2”超出了上端,则填在第三列的底端:
1 | ||
2 |
依然向右上斜行去填,如果超出了矩阵的右端,就平移至该行的最左端,比如这里我们要填的“3”超出了右端,则填在第二行最左边:
1 | ||
3 | ||
2 |
依然向右上斜行去填,如果目标的格子里面已经有数字,或者正好是矩阵的右上角,则这个数字不向右上方填写,而是改为向下去一行,比如“4”就填写在“3”的下方:
1 | ||
3 | ||
4 | 2 |
按照此法依次填入得出3阶幻方为:
8 | 1 | 6 |
3 | 5 | 7 |
4 | 9 | 2 |
理解了填充幻方的底层逻辑后,利用这个方法写出C语言代码:
#include <stdio.h>
int main(void)
{
int n = 3; // 定义矩阵阶数为3
int magic_square[3][3] = {0}; // 作出一个3*3的0矩阵
int num = 1;
int row = 0, col = n / 2; // 从第一行正中间开始填
/* 注意,在C语言中,通常矩阵的索引是从0开始计数的,所以在C语言代码中,
第0,1,2行(列),分别对应实际矩阵的第1,2,3行(列) */
while (num <= n * n) {
magic_square[row][col] = num;
row--;
col++; // 向右上角填入数字
if (row < 0) row = n - 1; // 超上沉底
if (col >= n) col = 0; // 超右移到最左
if (magic_square[row][col] != 0) {
row = (row + 2) % n;
col = (col - 1 + n) % n;
} // 被占用则下移一行
num++;
}
printf("3阶幻方:\n");
for (row = 0; row < n; row++) {
for (col = 0; col < n; col++) {
printf("%2d ", magic_square[row][col]); // 依次打印矩阵中的数字
}
printf("\n");
}
return 0;
}
运行结果:
我们可以对这个代码进行推广,让我们输入一个正整奇数n,就可以输出n阶的幻方:
#include <stdio.h>
#include <stdlib.h>
/* 定义函数generateMagicSquare */
void generateMagicSquare(int n, int magicSquare[][15])
{
int row = 0;
int col = n / 2;
for (int num = 1; num <= n * n; num++) {
magicSquare[row][col] = num;
row--;
col++;
if (num % n == 0) {
row += 2;
col--;
} else {
if (row < 0) row = n - 1;
if (col >= n) col = 0;
}
}
}
/* 定义函数printMagicSquare */
void printMagicSquare(int n, int magicSquare[][15])
{
printf("%d阶幻方:\n", n);
for (int row = 0; row < n; row++) {
for (int col = 0; col < n; col++) {
printf("%2d ", magicSquare[row][col]);
}
printf("\n");
}
}
int main() {
int n;
printf("请输入奇数阶数n:");
scanf("%d", &n);
if (n <= 0 || n % 2 == 0) {
printf("请输入一个正整奇数。\n");
return 1;
}
int magicSquare[15][15]; // 最大阶数不得超过15(可以自定义)
generateMagicSquare(n, magicSquare);
printMagicSquare(n, magicSquare);
return 0;
}
运行结果:
输入正整奇数:
输入不符合要求的数字:
(个人见解,如有错误或改进建议欢迎练习作者)