对于牛客网—语言学习篇—编程初学者入门训练—循环输出图形的一些总结

134 阅读11分钟

开篇介绍:

在此文章的开头,先附上牛客网该图形训练的链接:

线段图案_牛客题霸_牛客网https://www.nowcoder.com/practice/a95744270f274a14a8a0dafe10421589?tpId=290&tqId=309105&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page这是该训练的第一题,后面的题目都可在此链接进行查看

再附上我对该图形训练所写的代码Gitee链接:kecheng_8.20/kecheng_8.20 / kecheng_8.20 .c:牛客网练习 · Win/daima - 码云 - 开源中国https://gitee.com/shinewin/daima/blob/master/kecheng_8.20/kecheng_8.20%20/%20kecheng_8.20%20.c%EF%BC%9A%E7%89%9B%E5%AE%A2%E7%BD%91%E7%BB%83%E4%B9%A0

这里面有着大部分该类型题目的代码以及我的一些个人见解,不过并没有详细解释,故在下面我会进行统一思路的总结和针对部分特殊类型题目的分析


统一思路的总结:

其实去详细观察每个图形的特征,不难发现,它们和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

超级圣诞树_牛客题霸_牛客网https://www.nowcoder.com/practice/470d26c9a73e4e17be8cc45cac843423?tpId=290&tqId=2337480&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会变大),当然,这只是一般规律,究竟是怎么样,还需要我们去画图分析,然后再去在编译器内不断调试,反正韩信点兵——多多益善,只有我们多去尝试,才能获得真知,我们要深知:没有通用的规律,只有坚毅的恒心和尝试。

这一个链接就是该题型的一种,有兴趣的可以去尝试尝试:

金字塔图案_牛客题霸_牛客网https://www.nowcoder.com/practice/d84e8339f9444bb6b29bd3f227c8e538?tpId=290&tqId=309110&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page

2:

​编辑

BC100 直角三角形图案

BC101 翻转直角三角形图案

这两道题一个是从上到下输出的逐渐增多,一个则是从上到下输出的逐渐减少,顾名思义:翻转,就是把图形从上到下翻转过来,那么问题又来了,我们要怎么实现翻转呢,其实很简单,把我们for(i)循环与for(j)循环的条件进行更改就行啦,从++变为--,这样不就可以从上到下减少,不需要做一些更改,只需要如上述两幅图一样,把for条件进行调转一下,其实就能实现翻转了。这个应该算是较为简单的,只是终究还是需要我们去实践,去模拟,去调试。

这一个链接是这种题型的一种,有兴趣的同样可以进行尝试:

翻转金字塔图案_牛客题霸_牛客网https://www.nowcoder.com/practice/c4775776e4464537bfb6a5ba37c596c6?tpId=290&tqId=309111&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page

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个*,于是,知道了上面这些,那我们不就对这个问题知根知底了吗?温馨提示:在这个单独的循环后,记得换行,不难可以会堆在一起的。

知道了上述的分析,不妨可以来尝试尝试这两道题:

K形图案_牛客题霸_牛客网https://www.nowcoder.com/practice/753cc2662d9949fe826a85f815db0ca4?tpId=290&tqId=309113&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page

箭形图案_牛客题霸_牛客网https://www.nowcoder.com/practice/a6d1081e0c9a42f19e42ed6cd91556c1?tpId=290&tqId=309114&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page这两道题也是相同的思路,去试试吧。

结语:

写到这里,其实我对这类题型的分析也就差不多了,毕竟它终究只是编程者初步训练,难度有限,但是一法通万法通,上述思路的通用性或许不是万能的,但是当遇到类似题目的时候,我们都可以尝试一下这些思路,毕竟多一条路,就多一个方向,人生或许有很多条道路,但是只要我们无所畏惧,敢于尝试,敢于拼搏,相信自己,终究会走出一条属于你自己的通天大道,去前往成功,去摘下独属于你的胜利的果实。