华师一附中OI组

标题: 简单字符图案 [打印本页]

作者: admin    时间: 2018-7-29 20:43
标题: 简单字符图案
用字符来画图案是很有趣的,还可以训练我们编程,这栋大楼,我们循序渐进的画字符图形。
*

********


********
********
********
********
********
********
********
********
********

*
**
***
****
*****
******
*******
********
********


作者: admin    时间: 2018-7-29 20:44
画一个* 很简单  cout<<'*';就可以了。
画n个的话就可以 for(i=1;i<=n;i++) cout<<'*';当然 1-2个也可以 cout<<"**";
作者: admin    时间: 2018-7-29 20:55
要画m行n列的* 就得两重循环,内层循环控制每行n个* ,外层循环控制画m行,记住,每行画完还得 endl;
  1. for (r=1;r<=m;r++)
  2.    {
  3.       for (c=1;c<=n;c++) cout<<'*';
  4.       cout<<endl;
  5.     }
复制代码


比如5行5列的
*****
*****
*****
*****
*****

代码

  1. for (r=1; r<=5; r++)
  2.     {
  3.         for (c=1; c<=5; c++)
  4.             cout<<'*';
  5.         cout<<endl;
  6.     }
复制代码

作者: admin    时间: 2018-7-29 22:21
假设打印这样的5行5列的数字三角形,
*
**
***
****
*****

我们以行r为自变量,涉及到其他的变量都找到和r的对应函数关系,此题每行的字符个数在变,设为k个,则每行k=r,于是程序写作
  1. for (r=1; r<=5; r++)
  2.     {
  3.         for (c=1; c<=r; c++)
  4.             cout<<'*';
  5.         cout<<endl;
  6.     }
复制代码



再进一层,右对齐的三角形,
        *
      ***
    *****
   *******
  *********
我们发现每行前面的空格数kk也在变化,kk=10-r;(这个10无所谓,20也可以,只是起始位置不同)于是程序写作
  1. for(r=1;r<=5;r++)
  2. {
  3.    kk=10-r;
  4.    k=r;
  5.    for (i=1;i<=kk;i++) cout<<' '; ///画前面的空格
  6.    for (i=1;i<=k;i++) cout<<'* '; ///画*
  7.    cout<<endl;
  8. }
复制代码

再进一层,右对齐的等腰三角形,和上题目相比,字符的个数k不是k=r而是k=2*r-1;
        *
      ***
    *****
   *******
  *********

所以代码可以这样写
  1. for(r=1;r<=5;r++)
  2. {
  3.    kk=10-r;
  4.    k=2*r-1;
  5.    for (i=1;i<=kk;i++) cout<<' '; ///画前面的空格
  6.    for (i=1;i<=k;i++) cout<<'* '; ///画*
  7.    cout<<endl;
  8. }
复制代码

若*之间有空格的话,为了对齐,函数的关系就会发生变化,比如
         *
        * *
       * * *
      * * * *
     * * * * *
  1.    for (r=1; r<=5; r++)
  2.     {
  3.         k=10-r;
  4.         kk=r;
  5.         for (c=1;c<=k;c++) cout<<' ';
  6.         for (c=1; c<=kk; c++)
  7.             cout<<'*'<<' ';
复制代码






作者: admin    时间: 2018-8-16 09:52
要是画的不是*而是数字就还得注意同一行的数字也许还会有不同,就不再是统一的 cout<<'*',而是 cout<<kkk;kkk表示那个数字
         1
        2 2
       3 3 3
      4 4 4 4
     5 5 5 5 5

  1.      for (r=1; r<=5; r++)
  2.     {
  3.         k=10-r;
  4.         kk=r;
  5.         kkk=r;
  6.         for (c=1;c<=k;c++) cout<<' ';
  7.         for (c=1; c<=kk; c++)
  8.             cout<<kkk<<' ';
  9.         cout<<endl;
  10.     }
  11.   
复制代码

作者: admin    时间: 2018-8-16 10:04
再来一个,比如这样的,
         *
        * *
       * * *
      * * * *
     * * * * *
      * * * *
       * * *
        * *
         *
可以用两种方法,第一种先画一个正着的三角形,再画一个反着的三角形,

第二种就直接画九行的菱形,列表找到行r和每行的*个数kk,前面的空格数目k之间的关系,这个有点复杂,要涉及到绝对值函数。当然有人用if判断,这也不错,就是麻烦了点,最好还是找到统一的关系表达式。
r 1 2 3 4 5 6 7 8 9
k9876 5 6 7 8 9
kk 1 2 3 4 5 4 3 2 1

  1.     for (r=1; r<=9; r++)
  2.     {
  3.         kk=5-abs(5-r);
  4.         k=10-kk;
  5.         for (c=1;c<=k;c++) cout<<' ';
  6.         for (c=1; c<=kk; c++)
  7.             cout<<'*'<<' ';
  8.         cout<<endl;
  9.     }

复制代码
其中第三句改成
  1. if (r<5) kk=r ;else kk=10-r;
复制代码
效果等同,更直观但是数学味道少了一点。

作者: admin    时间: 2018-8-16 10:23
1992年全国程序设计大赛的题目:打印如下图形
         1
        1 1
       2 2 2
      2 2 2 2
     3 3 3 3 3
    3 3 3 3 3 3
   4 4 4 4 4 4 4
  4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5
  6 6 6 6 6 6 6 6
   6 6 6 6 6 6 6
    7 7 7 7 7 7
     7 7 7 7 7
      8 8 8 8
       8 8 8
        9 9
         9

此题,关键是要找到k,kk,kkk三个数字和r之间的关系。同样列表
r 1 23 4 5 6 7 8 9 10 11 12 13 14 1516 17 18
k 1918 17 16 15 14 13 12 11 11 12 13 14 15 16 17 18 19
kk 12 3 4 5 6 78 9 9 8 7 6 5 4 3 2 1
kkk 1 1 22 3 3 4 4 5 5 6 6 7 7 8 8 99

  1.     for (r=1; r<=18; r++)
  2.     {

  3.         kk=9.5-abs(9.5-r);
  4.         k=10-kk;
  5.         kkk=(r-1)/2+1;
  6.         for (c=1;c<=k;c++) cout<<' ';
  7.         for (c=1; c<=kk; c++)
  8.             cout<<kkk<<' ';
  9.         cout<<endl;
  10.     }
复制代码

找到这三个函数关系是最重要的部分,这与数学思维很相关要好好体会。其中k kk=9.5-abs(9.5-r);有点难得推出来但是是这个就很好理解了:if (k<=9) kk=r;else kk=19-r;

作者: admin    时间: 2018-8-16 10:47
这个题目也是一个很经典的
        0
       1 2
      3 4 5
     6 7 8 9
    A B C D E
   F G H I J K
  L M N O P Q R
S T U V W X Y Z

要非常清楚每一行所输出的内容和r之间的关系,还是一样,先列表。假设我们合成一个字符串“0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ”,那么每行输出的内容就与字符串的起点,终点建立了一个关系。
r 1 2 3 45 6 7 8
空格数 9 8 7 6 5 4 3 2
字符串起点 0 1 3 6 10 15 21 28
字符串终点 0 2 5 9 14 20 27 35


很清晰的一张表,你找到规律了吗?

  1.    for (i='0';i<='9';i++) s=s+char(i);
  2.    for (i='A';i<='Z';i++) s=s+char(i);
  3.    i=0;l=s.size();head=tail=0;j=1;
  4.    while (tail<=l-1)
  5.    {
  6.       for (k=1;k<=10-j;k++) cout<<' ';
  7.       for (k=head;k<=tail;k++) cout<<s[k]<<' ';
  8.       cout<<endl;
  9.       head=tail+1;tail=head+j;
  10.       j++;
  11.    }
复制代码


这个while(tail<=-1)也可以改成for (j=1;j<=8;j++)一回事。
作者: admin    时间: 2018-8-17 08:57
综上所述,一类简单的字符图案就是要找到每一行的变化的东西和行号r之间的关系,一般来说,变化的东西有这么几个:
1、每行前面的空格
2、每行的字符的个数
3、每个字符的内容(有可能一行相同也可能每个不同)

练习:
1、打印小九九乘法口诀表
2、打印边长为n的空心菱形
3、打印如下图形
       A
     ABA
   ABCBA
*********  共26行。

作者: admin    时间: 2018-8-17 09:00
进阶学习:复杂字符图案  http://www.hsyit.cn/forum.php?mod=viewthread&tid=36287




欢迎光临 华师一附中OI组 (http://hsyit.cn/) Powered by Discuz! X3.2