【问题标题】:Draw hourglass recursively in C在C中递归绘制沙漏
【发布时间】:2020-01-20 02:14:17
【问题描述】:

我需要在 C 中递归地绘制一个沙漏。我需要有 1 个辅助函数加上实际函数。以下是函数签名: void helper(无符号整数高度,无符号整数偏移) void real(unsigned int height)

height 描述要绘制的行数,offset 是每行开头的空格数。对于每一行,星星的数量应该减少 2,偏移量应该增加 1,高度应该减少 1,直到到达沙漏的中间。之后,高度应该继续减少,但星数应该增加 2,偏移量应该减少 1。如果输入高度是偶数,那么第一行应该有高度 - 1 星。此外,中间应该有两排只有 1 颗星。如果输入高度是奇数,那么第一行应该有高度星。

Ex) height = 6
*****
 ***
  *
  *
 ***
***** 

Ex) height = 5
*****
 ***
  *
 ***
*****

我必须使用递归,不允许循环。

这是我的辅助函数。我无法弄清楚主要功能。

void draw_hourglass_rec_helper(unsigned int height, unsigned int offset)
 {

  if (height == 0) {
    printf("\n");
  } else if (offset == 0) {
    printf("*");
    draw_hourglass_rec_helper(height-1, 0);
  } else {
    printf(" ");
    draw_hourglass_rec_helper(height, offset-1);
  }
 }

最佳尝试:

void draw_hourglass_rec(unsigned int height)
{
  if(height < 1)
  {
  return;
  }
 {
   draw_hourglass_rec_helper(height, ((-0.5 * height) + (9.0/2.0)));
   draw_hourglass_rec(height-2);
 }

}

打印:

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

对于 draw_hourglass_rec(10) 夫妻问题 1) 我无法打印沙漏的下半部分 2)星星的数量应该总是奇数 3)我不知道如何表达偶数输入情况,其中应该有 2 行每行 1 星 4)如果我在奇数高度使用此代码,我会陷入无限循环。

这是我用 C 语言编码的第一周。我真的很难用这种语言表达我的逻辑。

提前谢谢你。

【问题讨论】:

  • 无需发布您的所有次失败尝试,但您的最佳次尝试会有所帮助。 “我无法弄清楚主要功能”:你有什么问题?辅助函数是你自己写的,还是给你的?
  • 感谢您的及时回复。我在上面添加了我的问题。我写了辅助函数,但是函数签名给了我,我必须使用它。
  • 你需要在递归调用之前和之后做一些事情首先你在向下打印,然后在向上打印。
  • 但这不会破坏递归调用吗?因为如果我自己调用它,它会做所有这些事情。对不起,如果这没有意义。

标签: c function recursion definition


【解决方案1】:

你来了。

#include <stdio.h>

void draw_hourglass_rec_helper( unsigned int n, int offset )
{
    const char c = '*';

    if ( n )
    {
        printf( "%*c", offset + 1, c );

        unsigned int k = n % 2 == 0 ? n - 1 : n;

        for ( unsigned int i = 0; i < k - 1; i++ ) putchar( c );
        putchar( '\n' );

        if ( ! ( n < 2 ) ) draw_hourglass_rec_helper( n - 2, offset + 1 );

        if ( n != 1 )
        {
            printf( "%*c", offset + 1, c );
            for ( unsigned int i = 0; i < k - 1; i++ ) putchar( c );
            putchar( '\n' );
        }
    }
}

void draw_hourglass_rec( unsigned int n )
{
    if ( n )
    {
        draw_hourglass_rec_helper( n, 0 );
    }
}

int main(void) 
{
    while ( 1 )
    {
        printf( "Enter a non-negative number (0 - exit): " );

        unsigned int n;

        if ( scanf( "%u", &n ) != 1 || n == 0 ) break;

        putchar( '\n' );

        draw_hourglass_rec( n );

        putchar( '\n' );
    }

    return 0;
}

程序输出可能看起来像

Enter a non-negative number (0 - exit): 10

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

Enter a non-negative number (0 - exit): 9

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

Enter a non-negative number (0 - exit): 8

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

Enter a non-negative number (0 - exit): 7

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

Enter a non-negative number (0 - exit): 6

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

Enter a non-negative number (0 - exit): 5

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

Enter a non-negative number (0 - exit): 4

***
 *
 *
***

Enter a non-negative number (0 - exit): 3

***
 *
***

Enter a non-negative number (0 - exit): 2

*
*

Enter a non-negative number (0 - exit): 1

*

Enter a non-negative number (0 - exit): 0

如果辅助函数的第二个参数是 unsigned int 类型,那么您可以使用循环来输出初始空格,例如

void draw_hourglass_rec_helper( unsigned int n, unsigned int offset )
{
    const char c = '*';

    if ( n )
    {
        for ( unsigned int i = 0; i < offset; i++ ) putchar( ' ' );

        unsigned int k = n % 2 == 0 ? n - 1 : n;

        for ( unsigned int i = 0; i < k; i++ ) putchar( c );
        putchar( '\n' );

        if ( ! ( n < 2 ) ) draw_hourglass_rec_helper( n - 2, offset + 1 );

        if ( n != 1 )
        {
            for ( unsigned int i = 0; i < offset; i++ ) putchar( ' ' );
            for ( unsigned int i = 0; i < k; i++ ) putchar( c );
            putchar( '\n' );
        }
    }
}

另一种方法是使用静态变量作为输出偏移量,而不是使用辅助函数。

#include <stdio.h>

void draw_hourglass_rec( unsigned int n )
{
    static int offset = 0;

    const char c = '*';

    if ( n )
    {
        ++offset;
        printf( "%*c", offset, c );

        unsigned int k = n % 2 == 0 ? n - 1 : n;

        for ( unsigned int i = 0; i < k - 1; i++ ) putchar( c );
        putchar( '\n' );

        if ( ! ( n < 2 ) ) draw_hourglass_rec( n - 2 );

        if ( n != 1 )
        {
            printf( "%*c", offset, c );
            for ( unsigned int i = 0; i < k - 1; i++ ) putchar( c );
            putchar( '\n' );
        }

        --offset;
    }
}

int main(void) 
{
    while ( 1 )
    {
        printf( "Enter a non-negative number (0 - exit): " );

        unsigned int n;

        if ( scanf( "%u", &n ) != 1 || n == 0 ) break;

        putchar( '\n' );

        draw_hourglass_rec( n );

        putchar( '\n' );
    }

    return 0;
}

程序输出将与上面的程序相同。

【讨论】:

  • 我喜欢!我所做的唯一设计选择差异是制作base == height,这导致偶数的最小宽度为2。谁会想到会有这么多不同的方法来处理递归沙漏:)
【解决方案2】:

除了@Vlad from Moscow 提供的选择之外,您还可以采用另一种方法,它使用相同的辅助函数进行递归,但是将初始高度设置为负值,并且当高度大于原始值时递归结束输入,例如

#include <stdio.h>
#include <stdlib.h>

void hghelper (int h, int current)
{
    if (current > h)
        return;

    int ac = abs(current);

    if (ac == 1)
        current = 1;

    if (ac != 0) {
        int stars = ac;
        int indent = (h - stars) / 2;

        while (indent--)
            putchar (' ');
        while (stars--)
            putchar ('*');
        putchar ('\n');
    }

    hghelper (h, current + 2);
}

void hourglass (int h)
{
    int negh = -h;

    hghelper (h, negh);
}

int main (int argc, char **argv) {

    int height;

    if (argc > 1) {
        if (sscanf (argv[1], "%d", &height) != 1 || height < 0)
            return 1;
    }
    else
        height = 5;

    hourglass (height);
}

使用/输出示例

注意,对于这个算法,底边(宽度)的星数总是与高度相同。您可以根据需要进行调整。

默认height = 5

$ ./bin/hourglass_recursive
*****
 ***
  *
 ***
*****

height = 6:

$ ./bin/hourglass_recursive 6
******
 ****
  **
  **
 ****
******

height = 7:

$ ./bin/hourglass_recursive 7
*******
 *****
  ***
   *
  ***
 *****
*******

height = 21:

$ ./bin/hourglass_recursive 21
*********************
 *******************
  *****************
   ***************
    *************
     ***********
      *********
       *******
        *****
         ***
          *
         ***
        *****
       *******
      *********
     ***********
    *************
   ***************
  *****************
 *******************
*********************

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-03
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    相关资源
    最近更新 更多