Рисовать песочные часы рекурсивно в C - PullRequest
1 голос
/ 20 января 2020

Мне нужно рекурсивно нарисовать песочные часы в C. Мне нужно иметь 1 вспомогательную функцию плюс фактическую функцию. Вот подписи функций: void helper (unsigned int height, unsigned int offset) void real (unsigned int 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_re c (10) Проблемы с парой 1) Я не могу напечатать нижняя половина песочных часов 2) Количество звезд всегда должно быть нечетным 3) Я не знаю, как express четный случай ввода, где должно быть 2 строки по 1 звезде каждая 4) Если я использую этот код на нечетная высота, я падаю в бесконечное l oop.

Это моя первая неделя кодирования в C. У меня действительно возникают проблемы с выражением моей логики c на этом языке.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 20 января 2020

В дополнение к выборкам, предоставленным @ Vlad из Москвы , существует еще один подход, который вы можете использовать, который использует ту же вспомогательную функцию для рекурсии, но устанавливает начальную высоту как отрицательную и рекурсия заканчивается, когда высота больше, чем введенное исходное значение, например,

#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
*********************
 *******************
  *****************
   ***************
    *************
     ***********
      *********
       *******
        *****
         ***
          *
         ***
        *****
       *******
      *********
     ***********
    *************
   ***************
  *****************
 *******************
*********************
0 голосов
/ 20 января 2020

Вот и вы.

#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, вы можете использовать al oop для вывода начальных пробелов, например,

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' );
        }
    }
}

Другой подход заключается в использовании переменной stati c для выходного смещения вместо использования вспомогательной функции.

#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;
}

Вывод программы будет таким же, как и в программе выше.

...