James Bryant

【转】输出图案类问题的思路

0
阅读(954) 评论(1)

问题导入——编写一个程序,只用两条输出语句,生成一个像半个5*5正方形形状(直角三角形)的#符号图案:

#####

####

###

##

#

我们可以采用消减法,先把它想象成一个5*5的矩形。

第一行:##### 的实现代码(一个for循环即可)

1 for(int hashNum = 1;hashNum <= 5;hashNum++)
2     {
3         printf("#");
4     }
5     printf("\n");

所以,要想打印出一个5*5的矩形,只需将上述代码循环5次即可,即:

1 for(int row = 1;row <= 5;row++)
2     {
3         for(int hashNum = 1;hashNum <= 5;hashNum++)
4         {
5         printf("#");
6         }
7         printf("\n");
8     }

到目前为止,我们可以打印出一个5*5的矩形了,已经接近最终的解决方案了。

那么,接下来应该怎样修改代码,使它产生半正方形的图案呢?

如果我们观察上面的程序清单并把它与自己所需要的半正方形的输出进行比较,可以发现问题在于条件表达式hashNum <= 5上。这个条件产生了5个相同的、由5个#符号所组成的行。所以我们需要一种机制,调整每行所生成的符号数量,使第一行为5个符号,第二行为4个符号,以此类推。

接下来,我们要进行另一个消减程序的试验:写一段代码,功能:显示数字从5到1,每个数字出现在单独的一行中

分析:我们必须找到一种表达式,在第一行时其值为5,在第二行时其值为4,接下来以此类推。如果我们需要一个当行号递增时其值递减的表达式,首先想到的可能是在行号前面加个符号,相当于把它乘以-1.这种方法可以产生递减的数字,却不是我们所需要的数字。我们可以把对问题的分析通过一张表格来总结下

行号

所需的值

行号*-1

行号与所需值之差

image

差是一个固定值6。这意味着我们所需要的表达式是 row*-1 + 6。简化为6 - row。

所以“显示数字从5到1,每个数字出现在单独的一行中”的代码为:

1     for(int row = 1;row <= 5;row++)
2     {
3         printf("%d\n",(6-row));
4     }

所以打印半个5*5正方形形状(直角三角形)的#符号图案的完整代码为

 1 #include<stdio.h>
 2 int main()
 3 {
 4     for(int row = 1;row <= 5;row++)
 5     {
 6         for(int hashNum = 1;hashNum <= 6-row;hashNum++)
 7         {
 8             printf("#");
 9         }
10         printf("\n");
11     }
12 } 

问题延伸——编写一个程序,只用两条输出语句产生一个类似侧三角形形状的#符号图案:

#

##

###

####

###

##

#

根据前一个问题的分析,我们知道做法如下:

1,使用一个循环,显示一行特定长度的符号。

2,使用嵌套循环显示一系列的行。

3,使用代数表达式而不是固定值,为每一行创建不同数量的符号。

4,通过试验和分析,发现正确的代数表达式。

解决各形状问题所需要的各个组成部分

#####                                   #####     5

####                                     #####     4

###            #####               #####     3

##                                         #####     2

#                                           #####     1

#                                            ####      1

##                                         ####      2

###                                       ####      3

####          ####                 ####      4

###                                      ####      3

##                                        ####      2

#                                          ####      1

解决“侧三角形”问题所需要的各个组成部分

1    7     3    3  #

2    6     2    2  ##

3    5     1    1  ###

4    4     0    0  ####

3    3    -1    1  ###

2    2    -2    2  ##

1    1    -3    3  #

(a) (b) (c)  (d) (e)

分析:在“半正方形”问题中,用一个较大的整数减去行号是可行的,所以我们这次用8 - row(行号)得到(b)的结果,但这并不是我们想要的。在前一个问题中,我们需要从大到小的数而不是从小到大的数,因此用一个较大的数减去循环变量就可以了。在这个问题中,我们先是从小到大然后再从大到小。可以试着找到一个中间值,所以我们把前面的8 - row 替换成4 - row,可以得到(c)的结果。这个结果也不正确,但是如果忽略最后3个数左边的负号,它就是我们所需要的结果。如果我们使用绝对值函数去掉这些负号会怎么样?表达式abs(4 - row)产生结果(d),就是我们想要的结果了。

延伸分析:如果我们是对空格而不是#号进行计数会怎么样呢?(d)列就是我们对空格进行计数的正确的值序列。为了得到正确数量的#符号,可以把每行看成有4个格子,然后减去空格的数量。如果每行有4个格子,其中abs(4 - row)为空格的数量,则具有#符号的格子的数量就可以用4 - abs(4 - row)获得。

代码如下:(注意调用abs函数时要提前添加stdlib.h头文件)

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 int main()
 4 {
 5     for(int row = 1;row <= 7;row++)
 6     {
 7         for(int hashNum = 1;hashNum <= 4-abs(4 - row);hashNum++)
 8         {
 9             printf("#");
10         }
11         printf("\n");
12     }
13 } 

如果再次遇到类似的图案输出类问题,以上这套组合拳还是非常有效的!^_^

——做一名健壮的挨踢青年,如果未来无法用代码改变这个世界,还可以考虑去搬砖。

  1. 你提供的资料真是太有用了