目录
一、 课程设计题目及设计目的
幻方是一种很有意思的数字矩阵,在很早著名的九宫八卦阵就与幻方有关。幻方的定义为:
1 到 N*N 的整数填入N*N的方格中,每行和每列以及对角线的数字之和必须是相等的。
你作为八卦公司的顶级程序员,现在需要你解决一个问题,将任意100以内奇数阶的幻方找出来。
注:
幻方又称为魔方,方阵或厅平方,它最早起源于我国。宋代数学家杨辉称之为纵横图。
所谓纵横图,它是由1到n*n,这n*n个自然数按照一珲的规律排列成N行、N列的一个方阵。它具有一种厅妙的性质,在各种几何形状的表上排列适当的数字,如果对这些数字进行简单的逻辑运算时,不论采取哪一条路线,最后得到的和或积都是完全相同的。
后来,人们经过研究,得出计算任意阶数幻方的各行、各列、各条对角线上所有数的和的公式为:
Nn=1/2n(n 2+1)
其中n为幻方的阶数,所求的数为Nn.
奇阶幻方:n为奇数
二、设计思路与算法
在填幻方前我们做如下约定:如填定数字超出幻方格范围,则把幻方看成是可以无限伸展的图形。
(即:碰到底的时候就将数翻到上面去,碰到右边的时候就翻到左面去)
//分析:魔方阵有如下规律:
// 1:自然数1总是在方阵第一行当中一列上。
// 2:后续的自然数在当前数的右上方,
// 1)如果是在第一行则行数变为第n行列数加1 ;
// 2)如果是在最后一列,行数减1,列数为第1行。
// 3)如果后续的数所处位置已有数,则行数加1,列数不变
// 4)如果是在第一行最后一列,行数加一,列数不变
具体实现:
1, 建立一个n*n的二维数组来存放幻方。
2, 给幻方初始化置零,通过二重循环形成n*n的数组。
3, 通过变量a的变化(1—n*n)依次将数据1-n*n填入幻方中。
4, 通过控制下标的变化可以控制数据排放的的位置,而幻方形成是有规律的,可通过多次判断加循环来实现。
if语句实现多重判断:先将第一行中间一列置1,接下来判断下标是否为第一行最后一列(第二行最后一列总是接上面的数字),同样,第三步判断下标是否为某行的最后一列(是的话行数减一,列数为零)。以上三步为特殊位置数据的形成方法;最后的判断为后续的自然数的右上方数字是否为零,即是否填进数字,若后续的数所处位置已有数,则行数加1,列数不变,否则行数减一,列数加一。注意,四种情况下a均自增。
5,再通过一次二重循环输出数组,程序结束。
变量名称 | 变量类型 | 变量作用 | 取值范围 |
a | 整型 | 存放n从1到n的变化 | 1-100的奇数 |
n | 整型 | 记录n*n矩阵中n的值 | 1-100的奇数 |
x | 整型 | 记录数组中行的坐标 | 1-100 |
y | 整型 | 记录数组中行的坐标 | 1-100 |
cube[][] | 二维数组 | 形成并存放幻方矩阵 | 1-10000 |
#include "stdio.h"
#include "conio.h"
int main()
{ int a;
while(1){
int n;
int x,y;
int cube[100][100];
scanf("%d",&n);
if(n==0){
break;
}
for(x=0;x<n;x++){
for(y=0;y<n;y++){
cube[x][y]=0; //生成矩列并且每项置零
}
}
a=1;
x=0;
y=(n+1)/2-1;
while(a!=n*n+1){ //n从1开始,到n*n结束
cube[x][y]=a; //依次赋值,第零行中间列置1
if(x==0 && y==n-1){
x=x+1;
a=a+1;
} //如果是在第一行最后一列,行数加一,列数不变
else if(x==0 && y!=n-1){
x=n-1;
y=y+1;
a=a+1;
} //如果是在第0行则行数变为第n-1行列数加1
else if(x!=0 && y==n-1){
x=x-1;
y=0;
a=a+1;
} //如果是在最后一列,行数减1,列数为第0行。
else if(cube[x-1][y+1]==0){
x=x-1;
y=y+1;
a=a+1;
} //后续的自然数在当前数的右上方
else{
x=x+1;
a=a+1;
} //如果后续的数所处位置已有数,则行数加1,列数不变
} //不同情况下a均自增
for(x=0;x<n;x++){
for(y=0;y<n;y++){
printf("%d ",cube[x][y]);
}
printf("/n"); //输出形成的矩列
}
}
return 0;
}
输入:
1
3
7
2
4
0
输出:
1
8 1 6
3 5 7
4 9 2
30 39 48 1 10 19 28
38 47 7 9 18 27 29
46 6 8 17 26 35 37
5 14 16 25 34 36 45
13 15 24 33 42 44 4
21 23 32 41 43 3 12
22 31 40 49 2 11 20
3 0
0 4
15 1 7 13
4 6 12 14
9 11 0 3
10 16 2 8
程序终止
分析:
程序只能输出奇数的幻方,因此输入偶数时会出现0这一数字,并且数字也不是从1-n*n渐变的,而输入0时,程序错误,即break语句引起的终止
这次做C语言的报告使我对C的了解又深入了一步,通过一学期的学习,将上学期没有涉及到的东西完整的学了一遍,没有了解透彻的东西掌握的更加牢固,在此基础上我做了这次报告,题目出自于ACM,一个古老的幻方问题。
经过在网上的搜索,发现这个题目是比较适合我做的,之前的很多参赛题目,比如百度的ASTAR和英特尔的多核设计,虽然都是不错的题目,然而大多涉及到了C++中的表,栈等内容,而其他的诸如计算日期,猜数字等题目又太过简单,没有涉及到数组、指针等内容。
我的课程设计题目- 幻方,也称魔方、矩阵,起源于我国,春秋时已经有记载了,宋代数学家杨辉称之为纵横图。幻方又分为奇阶幻方和偶阶幻方,在搜索算法和程序时,我发现了很多不同的经典算法,我采用的是Merzirac法生成奇阶幻方,另外还有loubere法生成奇阶幻方、horse法生成奇阶幻方 、Hire法生成偶阶幻方、Strachey法生成单偶幻方、Spring法生成以偶幻方、YinMagic构造偶阶幻方等,这些方法都非常巧妙,小小的幻方可以衍生出很多奇妙的东西,比如我国古代的八卦与国际象棋均是起源于此,不止如此,幻方还可以扩展到三维,应用到宇宙天文学等领域,真是让我大开眼界。而我现在只能将它与C语言最低限度的结合起来,形成一个较简单的奇阶幻方,通过它我领略到了C的奇妙和强大,仅仅通过判断二维数组下标的变化,既可以快速的生成幻方,这其中我的感觉是将幻方的一些规则”翻译”成了C语言来告诉计算机执行,应用到的东西不过是循环、条件结构加二维数组,很遗憾没有使用到指针,可见C语言的功能是非常强大的。
最后我想说在编译器的使用上也是麻烦不断,先后用了VC6.0、BorlandC++、TC2.0、win-TC等, 由于对编译器的不熟悉,调试过程中屡屡出现错误而无法自己解决,实在是一大遗憾,意识到平时没有下功夫多练习编程,是不可能熟练地完成调试的
以上是这次编程的全部心得, 谢谢 老师看完,希望老师多给些指导和意见!