星号棱形,数字棱形及其他对称图形的分析方法
这一类图形其实都可以运用其对称性进行分析,选定中心图案或数字,进行规律分析来实现的。 1. 先来一道简单的题。
输入一个整数n,输出n行n列的“ * ”号,代码如下
//比较简单,直接上两个for循环就行了。
#include <stdio.h>
int main()
{
int i,n,k;
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(k=0;k<n;k++)
{
printf("*");
}
printf("\n");
}
return 0;
}
2.输出入下图所示的棱形。
*
***
*****
***
*
我们只需要输出以上棱形就行了,通过观察,棱形一共有5行,我们可以用5个printf()函数进行输出。但是,用这种方式难免太机械化了,如果要输出100行,很明显这种方法行不通,还有没有其他方法呢?
3.
Description
由键盘输入正数n(n<30),要求输出如下2*n+1行的菱形图案。
输出格式
菱形右边不留多余空格
输入样例
2
输出样例
*
***
*****
***
*
(题源 SCAU )
这道题用printf()函数输出根本不可能了,很容易地,我们想到了应该用循环来解决问题。
先把这个棱形分成上下两部分,设置一个外层循环控制行,再使用内层循环打印空格及*号。
* *** ***** *** *
(红色为上半部分,绿色为下半部分,通过每部分的规律来实现。因为分上下部分,所以就需要两个for循环)
#include <stdio.h>
int main()
{
int n,i,k,j;
scanf("%d",&n);
for(i=1,k=1;i<=n+1;i++)
{
for(j=1;j<=n-i+1;j++)
{
printf(" "); //打印空格
}
for(j=1;j<=k;j++)
{
printf("*"); //打印*号
}
printf("\n");
k+=2;
}
for(i=1,k=2*n-1;i<=n;i++)
{
for(j=1;j<=i;j++)
{
printf(" "); //打印空格
}
for(j=1;j<=k;j++)
{
printf("*"); //打印*号
}
printf("\n");
k-=2;
}
return 0;
}
我们发现,凡是这些图形,都可以把他们分成若干分,一个个地来实现。
还有没有更好的办法呢?
不难发现,棱形是一个上下呈对称的图形,还可以利用对称性来更好的解决问题。
题目要求输出的行数是2*n+1行,是奇数,因此,还可以用相反数来控制行数。
#include "stdio.h"
int main()
{ int n,i,j;
scanf("%d",&n);
for(i=-n;i<=n;i++) //一共要打印2*n+1行,从-n到n。
{
for(j=1;j<=abs(i);j++) printf(" ");
for(j=1;j<=2*n+1-2*abs(i);j++) printf("*");
printf("\n");
}
return 0;
}
代码量是不是瞬间就减少了好多。
下面我们来一步步进行分析!
1.) 首先,棱形是一个上下左右对称的图形,肯定存在某种数学规律。
2.) 其次,设置绝对值就是利用了对称性。
3.)以当n=2为例。(以---代替空格)
--* 空格数:2 *号数:1 -*** 空格数:1 *号数:3 ***** 空格数:0 *号数:5 ---------->以上下对称轴处为中心行,在打印*号时用相应行数的绝对值的四则运算来 -*** 空格数:1 *号数:3 进行计算要打印多少*号 --* 空格数:2 *号数:1
好了,我们通过选定了中心行很容易地打印了*号棱形。
既然我们利用了上下对称的规律,有没有可以利用左右对称呢?
4.
打印星号空心菱形
描述
由键盘输入n(n为奇数),打印如下图空心菱形
例n=7
*
* *
* *
* *
* *
* *
*
输入格式
奇正整数
输入样例
3
输出样例
*
* *
*
当然,这道题也可以把它分成若干分,一个个来实现。(代码如下)
#include <stdio.h>
int main(void)
{
int i,j,n;
scanf("%d",&n);
for(i=1;i<=(n+1)/2;i++)
{
for(j=1;j<=(n+1-2*i)/2;j++)
{
printf(" ");
}
printf("*");
if(i==1)
{
printf("\n");
}
else
{
for(j=1;j<=2*i-3;j++)
{
printf(" ");
}
printf("*\n");
}
}
for(i=1;i<=(n-1)/2;i++)
{
for(j=1;j<=i;j++)
{
printf(" ");
}
printf("*");
for(j=1;j<=n-2*i-2;j++)
{
printf(" ");
}
if(i<=(n-3)/2)
{
printf("*\n");
}
}
return 0;
}
超级长,而且里面的数学表达式要算很久。
若采用对称的方法:(代码如下)
#include <stdio.h>
int main(void)
{
int i,j,n;
scanf("%d",&n);
n=(n-1)/2;
for(i=-n;i<=n;i++)
{
for(j=1;j<=2*n+1-abs(i);j++)
{
if(j==abs(i)+1||j==2*n+1-abs(i)) printf("*");
else printf(" ");
}
printf("\n");
}
return 0;
}
采用了上下左右对称的方法,并且运用数学公式,符合规律的打印输出相应的空格或*号。
以n=7为例分析:
*
* *
* *
* *
* *
* *
*
在代码中,第二个for循环用来控制一行需要输出的字符数,这里的字符是空格和*号。
还是选定上下对称轴的那行作中心行。
一行处除特殊外都要输出两个*号,排除特殊性来分析。
然后在if语句中,很容易发现第一个判断“j==abs(i)+1”的规律,
第二个判断语句是以中心行最右边的*号为基点缩回的。
(.......未完) |