在做一些打印菱形的题目时发现题型不外乎这几种:
【一】:输出*形组成的菱形
①题目:
描述
由键盘输入正数n(n<30,n为奇数),要求输出具有n行的如下图案。
输入样例
7
输出样例
******* *** *** ** ** * * ** ** *** *** *******
凡是遇到这种输出几就有几行的菱形(例如n=7,则有7行),一般采取“对称法”,就是设一个for循环这个i就是用来控制行,而且上下对称,例如第二行和倒数第二行的时候i的绝对值相同,就可以通过这个相同的绝对值来输出相同个数的*和空格,具体操作代码如下:<span style="white-space:pre"> </span>for(i=-(n/2);i<=n/2;i++)
#include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int n,i,j; scanf("%d",&n); for(i=-(n/2);i<=n/2;i++) { if(i==-(n/2)||i==(n/2)) { if(i==-(n/2)) { for(j=1;j<=n;j++) { printf("*"); } printf("\n"); } else { for(j=1;j<=n;j++) { printf("*"); } } } else { for(j=1;j<=abs(i)+1;j++) printf("*"); for(j=1;j<=(n-2*(abs(i)+1));j++) printf(" "); for(j=1;j<=abs(i)+1;j++) printf("*"); printf("\n"); } } return 0; }
②还有别的情况就是输入的n不是代表行数,而是其它数字,例如下面这道题:
Description
由键盘输入正数n(n<30),要求输出如下2*n+1行的菱形图案。
输出格式
菱形右边不留多余空格
输入样例
2
输出样例
* *** ***** *** *这道题是输入一个n,则输出2*n+1行的*,其实思路是一样的,还是利用i的绝对值相同上下对称的原理,只需要改变一下i与n的关系,具体代码如下:
#include "stdio.h" #define abs(x) ((x)>0?(x):-(x)) main() { int n,i,j; scanf("%d",&n); for(i=-n;i<=n;i++) { for(j=1;j<=abs(i);j++) printf(" "); for(j=1;j<=2*n+1-2*abs(i);j++) printf("*"); printf("\n"); } }
还有一种情况是输入一个n,则输出2*n-1行的*,思路更是差不多,这里就不累述了。但还有一种情况要提一下,就是下面的第3种。
③这种情况是输出半边的菱形。
如:编写程序,输入整数n,输出n行的字符图案。例如n=5时输出:
*
**
***
****
*****
****
***
**
*
输入格式
输入一个整数
输出格式
输出2*n-1行的三角形
输入样例
2
输出样例
*
**
*
分析:这种情况需要我们先输出空格然后输出*,所以我们应该找到空格、*与i的关系,不难发现每一行的空格和*的和都等于n,那么我们只需要控制i设置一个循环就行了。
以上大概就是*类型的菱形打印题型,然而题目的做法远远不止这些,本人还找到了一些更新奇的做法,在这里和大家分享一下!#include <stdio.h> #include <stdlib.h> int main() { int n; scanf("%d",&n); int hang=n*2-1; int i,kong,tmp,i_; for(i=1;i<=hang;i++) { if(i<=n) { kong=n-i; for(;kong>0;kong--) printf(" "); tmp=i; while(tmp>0) { printf("*"); tmp--; } printf("\n"); } else { i_=hang+1-i; kong=n-i_; for(;kong>0;kong--) printf(" "); tmp=i_; while(tmp>0) { printf("*"); tmp--; } printf("\n"); } } return 0; }
方法一、根据图形的样子找出规律,如下图:
打印菱形程序如下:
在图形中画十字分成4份,以其中的一部分考虑
方法二、扩展思想,把它当作正方形中截取的图形如下图:#include #define M 3 /*可以自定义菱形的大小*/ int main(int argc, char** argv) { int i,j,k; for(i=0;i<=M;i++)/*上半部分的行数*/ { for(j=0;j<=M-1-i;j++)/*打印空格的个数,我是以0开始的*/ printf(" "); for(k=0;k<=2*i;k++)/*,假如除去空格外都打印“*”,则以2*i+1打印"*"个数,这是每一行的特点*/ { if(k==0||k==2*i)/*然后只选择你要打印的“*”位置的个数*/ printf("*"); else printf(" ");/*之间的全为空格*/ } printf("\n"); } for(i=0;i<=(M-1);i++)/*下半部分比上班部分少一行*/ { for(j=0;j<=i;j++) printf(" "); for(k=0;k<=2*(M-1)-2*i;k++)/*判断k时没有合并式子,仅供学习探究,这点判断很重要,留作你自己思考了*/ { if(k==0||k==2*(M-1)-2*i)/*同上分析*/ printf("*"); else printf(" "); } printf("\n"); } return 0; }
![]()
#include #include #include #define M 3 int main() { int i,j; for(i=-M;i<=M;i++) { for(j=-M;j<=M;j++) if((abs(i)+abs(j))==M) /*横纵坐标之和等于M的则全部打印*/ printf("*"); else printf(" "); printf("\n"); } getch(); return 0; }
这个方法看起来很简单易懂,但是算法巧妙。觉得是一个很好的思想。至此,当然你开可以发挥让它打印实体的菱形了,怎么打?还是看规律,发现横纵坐标之和只要小于等于M就让它打印,修改代码为if((abs(i)+abs(j))<=M) 即可。还可以发挥思想看怎样修改可以打印如下的图案:
a
bcd
efghi
gklmnop
qrstu
vwx
y
下面来讨论一下第二大类,数字类的菱形。
【二】输出数字类的菱形
这种类型的题目可以变化的范围就很大了,题目五花八门,这里给出下面一些例子。
Description
由键盘输入正数n(n<10),要求输出如下中间数字为n的菱形图案。
输出格式
菱形右边不留多余空格
输入样例
4输出样例
1 121 12321 1234321 12321 121 1
这种和上面的第一大类的第2小类很类似,但需要多考虑数字的变化,最简洁的版本是下面这个。
但本人第一次做这道题的时候实在想不出这种方法,所以我的做法是下面这个:#include<stdio.h> #define abs(x) ((x)>0?(x):-(x)) main() { int n,i,j; scanf("%d",&n); n--; for(i=-n;i<=n;i++) { for(j=0;j<abs(i);j++) printf(" "); for(j=-(n-abs(i));j<=n-abs(i);j++) printf("%d",n+1-abs(j)-abs(i)); printf("\n"); } }
但不管是哪种方法,其实关键都是要找到一个函数关系式能满足行数与输出数字个数的关系,这个你只能慢慢研究。#include <stdio.h> #include <stdlib.h> int main() { int i,k,j; int n; scanf("%d",&n); int hangshu=n*2-1; int tmp=n; int d=1; for(i=1;i<=hangshu;i++) { k=tmp-1; if(k<0) k=-k; while(k>0) { printf(" "); k-=1; } tmp-=1; if(i<=n) { int geshu=i*2-1; int a; int b=1; for (a=1;a<=geshu;a++) { if(b>i) { int c=b; int d; if(b-i==1) d=1; c=c-d*2; printf("%d",c); d+=1; b+=1; continue; } printf("%d",b); b+=1; } } else { int geshu=(i*2-1)-4*(i-n); int a; int b=1; for(a=1;a<=geshu;a++) { if(b>(i-2*(i-n) )) { int c=b; c=c-d*2; printf("%d",c); d+=1; b+=1; continue; } printf("%d",b); b+=1; } d=1; } printf("\n"); } return 0; }
类似的题型还有很多,以后会再补充,也欢迎大家来评论补充。