开篇介绍:
在此文章的开头,先附上牛客网该图形训练的链接:
线段图案_牛客题霸_牛客网https://www.nowcoder.com/practice/a95744270f274a14a8a0dafe10421589?tpId=290&tqId=309105&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page这是该训练的第一题,后面的题目都可在此链接进行查看
这里面有着大部分该类型题目的代码以及我的一些个人见解,不过并没有详细解释,故在下面我会进行统一思路的总结和针对部分特殊类型题目的分析
统一思路的总结:
其实去详细观察每个图形的特征,不难发现,它们和c语言中的二维数组非常类似,都有着行和列的表达,且每行每列,我们都可以使用二维数组的计数方式进行查找规律,每行每列都从0开始计数,而后开始逐渐递增,下图是该训练中某道题目使用二维数组的方式的画图解析:
该题目
BC99 正方形图案
从上述图像,我们便不难发现,该训练中输出图形与二维数组的联系,因此,我们对于该图形的表达,便可以使用类似二维数组的表达方式(注意:可不是真使用数组方式:arr[i][j]进行表达),我们可以使用双重循环去模拟图形的行与列,我这边使用i表示行,j表示列,该循环用for循环或者while循环都可以,个人更加推荐使用for循环(较便捷,循环嵌套也看得更加浅显易懂)
因此,对于这类题目的核心思路就是模拟二维数组的形式,去进行(i)和列(j)的输出,去找到每个所对应的i,j,并观察它们的规律(每个的i,j是否相加为某个数,或者相减/相乘/相除,也有可能是i,j就等于某个和n有关的式子),要扩散思维,不能光从一个一个图形去分析规律,要多个图形综合分析规律,因为越复杂的图形,其规律大概率要和我们输入的n挂钩,有可能是i+j==n-1等等,下图便是一个例子:
BC111 空心正方形图案
使用二维数组的方式进行画图(n==5)
观察上图(i和j对应n的关系,无相加或者相减联系),我们便可发现,对于每个所处的i和j,第一行,最后一行,第一列,最后一列,都有,所以我们就能对i和j进行条件限制,这里需要注意:由于我们是从0开始计数,并向后逐渐递增,所以,输入n,最后一行所对应的数是n-1,最后一列所对应的也是n-1,而第一行和第一列所对应的都是0,由于我们已经限制了i对应行,j对应列,所以我们想对行限制,就得对i进行限制,想对列进行限制,就得对j进行限制,这个时候就得使用if语句,如上述图中我所填写的代码,要使用if语句进行限制,什么地方要有*,什么地方不能没有*,应该是空格,都得进行限制,这里还有一个易错点,我们使用if语句后,想要在除*之外的地方打印空格,我们就得使用else语句,不难如若不使用else语句,还是会在所有地方打印空格,这便导致不能得到我们想要的效果
BC110 X形图案
使用二维数组的方式进行画图(n==6)
观察上图(i和j对应n的关系,有相加或者相减联系),这幅图便是有关于i与j的运算关系,需要我们自己去判断,每个所对应i和j运算后与n的关系,同时也会有i与j之间的关系,最常见的就是i==j,对待上述,我们都得使用if语句进行限制,该表达的地方表达,不该表达的地方就不要表达,**温馨提示:要在for(j)循环后,打印换行,不难就堆在一起了,不能正常输出图形。**
下面几个链接就是图形输出的一些练习,感兴趣的可以在看下文之前就去尝试解答一番:
正斜线形图案_牛客题霸_牛客网https://www.nowcoder.com/practice/61ef68d129534dfbb04b232e1244e447?tpId=290&tqId=309116&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page数字三角形_牛客题霸_牛客网
https://www.nowcoder.com/practice/804a22929b844e6b9379a5e90b5e2197?tpId=290&tqId=309320&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page
反斜线形图案_牛客题霸_牛客网KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的反。题目来自【牛客题霸】https://www.nowcoder.com/practice/7b066963c4eb4d188becd18c37dfe22d?tpId=290&tqId=309115&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page圣诞树_牛客题霸_牛客网
https://www.nowcoder.com/practice/9a03096ed8ab449e9b10b0466de29eb2?tpId=290&tqId=2337396&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page
统一思路的总结,大概是这些,下面对一些特殊的题目进行分析,也是和二维数组有关,也是和i,j的关系有关,但是会需要一些其他的步骤来进行更精细的表达
部分特殊题目的分析:
1:
BC100 直角三角形图案
BC102 带空格直角三角形图案
观察上面两道题,第一道应该是没什么难度,毕竟它是左对齐,不需要在打印*之前先印空格,只需要我们找到i和j对应的关系便能顺利解决,但是,其实这里面也有一些注意事项,我已经写在第一幅图的注释中了,需要注意,毕竟差之毫厘,谬以千里。
而第二道题,题目要求我们打印右对齐的图形,刚开始我是用尝试将'*'赋值给char c,然后后面在printf中使用“%c”去调整它的格式,设置为右对齐或者左对齐,但是经过尝试,不知道是vs编译器的问题,还是什么因素,无法通过这种方法去设置,最终只能以遗憾告终(后续我会再尝试看行不行)
因此,我们只能在打印之前就打印空格,先打印空格,再打印,但是随之而来的问题就是,我们要怎么去限制空格的打印,每行应该打印多少,逐行如何递减/增加,还有就是,我们应该打印“ ”(两个空格)还是“ ”(一个空格),这里我有一个小妙招:用鼠标去一个一个数之前的空格,看到左一个的时候,是经历一个空格,还是两个空格,(左一个也要算上是一个空格),其实就是看我们所选的那一个与其左一个*之间隔了多少个空格,0个就是打印“ ”(一个空格),1个就是打印“ ”(两个空格)。
下一个问题就是,我们要如何控制每行输出的空格个数,因为很明显,它是每行下去逐渐减少的,注意:针对空格的输出我们要设置一个新循环,这个循环在for(i)内,for(j)前,我设置其为for(k)循环,这个循环负责打印*之前的空格,空格是逐行递减的,这个毋庸置疑,而且根据我们的观察,我们可以发现,在最后一行(也就是第n-1行),*前面是没有空格的,所以,我们便可知道,对空格的限制是肯定要与n挂钩的,但是要是什么关系呢?看下图:
最左端一个*前面的空格数
由图,可以看出,空格数是肯定减少的,但是关系是和谁挂钩呢?其实很简单,for(k)循环就在for(i)循环内,那k肯定要和i挂钩,这样才能达到每行输出的空格都减少的目的,一般来说,我们针对右对齐的图形的空格输出是for(int k=0;k<n-i;k++) ,这么一来,我们就可以实现每行逐渐减少空格的目的(因为i会变大),当然,这只是一般规律,究竟是怎么样,还需要我们去画图分析,然后再去在编译器内不断调试,反正韩信点兵——多多益善,只有我们多去尝试,才能获得真知,我们要深知:没有通用的规律,只有坚毅的恒心和尝试。
这一个链接就是该题型的一种,有兴趣的可以去尝试尝试:
2:
编辑
BC100 直角三角形图案
BC101 翻转直角三角形图案
这两道题一个是从上到下输出的逐渐增多,一个则是从上到下输出的逐渐减少,顾名思义:翻转,就是把图形从上到下翻转过来,那么问题又来了,我们要怎么实现翻转呢,其实很简单,把我们for(i)循环与for(j)循环的条件进行更改就行啦,从++变为--,这样不就可以从上到下减少,不需要做一些更改,只需要如上述两幅图一样,把for条件进行调转一下,其实就能实现翻转了。这个应该算是较为简单的,只是终究还是需要我们去实践,去模拟,去调试。
这一个链接是这种题型的一种,有兴趣的同样可以进行尝试:
3:
BC105 菱形图案
#include <stdio.h>
int main()
{
int n = 0;
while (~scanf("%d", &n))
{
for (int i = 1; i <= n; i++)
{
for (int k = 0; k <= n - i; k++)
{
printf(" ");
}
for (int j = 0; j < i; j++)
{
printf("* ");
}
printf("\n");
}
for (int i = 0; i <= n; i++)//因为从0开始算,第n行有n+1个*
{
printf("* ");
}
printf("\n");
for (int i = n; i >= 1; i--)
{
for (int k = 0; k <= n - i; k++)
{
printf(" ");
}
for (int j = i; j > 0; j--)
{
printf("* ");
}
printf("\n");
}
}
return 0;
}
BC105 菱形图案:详细代码
上面这道题,第一眼看过去,两眼一黑,what is this?what can i do?嘿嘿,不必焦急,让我们分析分析,其实也是很简单的,下面提供我个人的一种解法,对于题目的解法还有很多种,毕竟条条大路通罗马,有兴趣的人可以自己去尝试不同方法的解答。
我们仔细去观察该图形,诶,怎么感觉,这个图形似乎是由两个图形组合起来的呢?如果有做了了上面两个链接的,应该不难发现,这就是有两个金字塔图形组成的,上面的是正置金字塔,下面的是倒置金字塔,但是这个时候可千万不要急着高兴,因为如果你再仔细观察的话,就会发现,这个图形的正中间,似乎与上下的图形不怎么搭呀,感觉它就像是一个对称轴,这可怎么办?这个对称轴的上下,我们还可以用金字塔去表达,但是中间的这个,又该如何呢?诶,不用怕,既然这一条不在金字塔循环中,那我们就把它独立出来,我们再设置一个循环,用这个循环单独表达中间这一行,其实如果我们有对这个图形使用二维数组的方式分析的话,就会知道,这一条对称轴,是在第n行(从0开始),所以这一行也应该要有n个*,于是,知道了上面这些,那我们不就对这个问题知根知底了吗?温馨提示:在这个单独的循环后,记得换行,不难可以会堆在一起的。
知道了上述的分析,不妨可以来尝试尝试这两道题:
结语:
写到这里,其实我对这类题型的分析也就差不多了,毕竟它终究只是编程者初步训练,难度有限,但是一法通万法通,上述思路的通用性或许不是万能的,但是当遇到类似题目的时候,我们都可以尝试一下这些思路,毕竟多一条路,就多一个方向,人生或许有很多条道路,但是只要我们无所畏惧,敢于尝试,敢于拼搏,相信自己,终究会走出一条属于你自己的通天大道,去前往成功,去摘下独属于你的胜利的果实。