为什么我的金字塔中间没有 space?

Why isn't there a space in the middle of my pyramid?

所以我正在尝试解决 https://cs50.harvard.edu/x/2021/psets/1/mario/more/ 这个从 cs50 设置的问题。

我花了很长时间才走到这一步(在 youtube 的帮助下需要 5-6 小时)。

#include <cs50.h>
#include <stdio.h>

int get_positive_int(void);
int main(void)
{
    int n = get_positive_int();
    // Run a below loop until i is greater than n
    for(int i = 0; i < n; i++)
    {
      // Run if statement on the same row until j is greater than n*2 + i+1
        for(int j=0; j < n*2 + i+1; j++)
        {
            // Create a blank space in exact center of the pyramid
            if(j + i - n == 0 || j + i - n == 1)
                printf(" ");
            //If the value of n-1 is less than the combined value of j and i, or 
            //if the value of i and n minus j is less than or equal to zero print #
            else if ( j + i > n - 1 || i + n - j <= 0)
                printf("#");
            else 
                //otherwise print " "
                printf(" ");
        }
        printf("\n");
    }
}

下面为什么不在我的金字塔中心创建两个“ ”?

if(j + i - n == 0 || j + i - n == 1)
                printf(" ");

为什么当我为 n 选择值 1 时程序没有打印任何内容?

这种 thinking/math 的特定类型叫什么?我很难掌握它,我不知道如何在网上找到信息,因为我不知道它叫什么。

我的输出如下。 当 N = 8

          #######
         #########
        ###########
       #############
      ###############
     #################
    ###################
   #####################

我想要的输出是。 当 N = 8

       #  #
      ##  ##
     ###  ###
    ####  ####
   #####  #####
  ######  ######
 #######  #######
########  ########

当我输入值 1 时,我得到了。

   

我输入1的时候想要的是,

#  #

我想知道我具体做错了什么以便自己解决问题,而不是尽可能直接回答。

首先观察你的两个 for 循环都是从 0 开始的。因此在开始时 ij 都等于 0。因此,由于 n 是一个正整数,您的 ifelse if 子句都被评估为 false 并且只有最后的 else 被执行,即 printf(" ");

现在看看你的金字塔。您的“金字塔”用 n 行和 2*n + 2 列填充 space。第一个循环 for (i = 0; i < n; i++) 是针对行的,它是正确的,因为有 n 行。但是,您的第二个 for 循环有问题。应该是 for (int j=0; j < n*2 + 2; j++).

现在,当我们查看第 i 行时,我们看到(记住行从 0 开始,因为我们从 0 开始计数 i),您想要打印n-1-i spaces,然后是 i+1 # 个字符,然后是 2 spaces,然后是 i+1 # 个字符,最后是 n- 1-i spaces。所以“spaces”是当 j < n-1-i(记住 j 也是从 0 开始),当 j == nj == n+1 以及当 j > n+2+i

这可以用if-else写成如下:

if ( j < (n-1-i) || j == n || j == n+1 || j > n+2+i) printf(" ");
else printf("#");

因此最终代码将如下所示:

#include <cs50.h>
#include <stdio.h>

int get_positive_int(void);

int main(void)
{
    int n = get_positive_int();
    
    for(int i = 0; i < n; i++)
    {
        for(int j=0; j < n*2 + 2; j++)
        {
            if ( j < (n-1-i) || j == n || j == n+1 || j > n+2+i) printf(" ");
            else printf("#");
        }
        printf("\n");
    }
}

从数学上考虑一下。您的斜率为 -1,所以我们有 j = -i + k。我们的公式变为 k = i + j。如果我们有 n = 5:

i j k
0 4 4
1 3 4
2 2 4
3 1 4
5 0 4

n = 6

i j k
0 5 5
1 4 5
2 3 5
3 2 5
4 1 5
5 0 5

所以k = n - 1

这是上半场,下半场更容易,j = i + k,所以k = j - i。它是移动 k 的正斜率。所以 n=5

i j k
0 4 4
1 5 4
2 6 4
3 7 4
5 8 4

n = 6

i j k
0 5 5
1 6 5
2 7 5
3 8 5
4 9 5
5 10 5

看看我们在两种情况下都匹配 k = n - 1。所以我们的公式是 j = -i + n - 1j = i + n - 1.

其次,在这两种情况下,我们在 max(i) + k 处都有最大值 j,换句话说,n - 1 + n - 1,所以 2 * n - 2

所以:

  1. 我们收到了您的台词。
  2. 看近了,你会看到你的j要走多远。

代码如下:

// int get_positive_int(void);
int main(void)
{
    int n = 5; //get_positive_int();
    // Run a below loop until i is greater than n
    for(int i = 0; i < n; i++)
    {   
        // Run if statement on the same row until j is greater than n*2 + i+1
        for(int j = 0; j < n * 2 - 1; j++)
        {                                                                                                                                                     
            // Create a blank space in exact center of the pyramid
            if (j == n - i - 1 || j == n + i - 1)
                printf("#");
            else 
                //otherwise print " "
                printf(".");
        }   
        printf("\n");
    }   
}

输出:

....#....
...#.#...
..#...#..
.#.....#.
#.......#

现在您可以通过查看此优化 trim 减少 25% 的内部循环执行次数。我不需要超出我打印第二个 # 的点,这意味着超出 max(j) = j + 1 我的第二个公式 + 1 的值是因为我仍然希望能够进入循环,所以我们得到最大值 max(j) = (n + i - 1) + 1.

#include <stdio.h>

// int get_positive_int(void);
int main(void)
{
    int n = 5; //get_positive_int();
    // Run a below loop until i is greater than n
    for(int i = 0; i < n; i++)
    {
        // Run if statement on the same row until j is greater than n*2 + i+1
        for(int j = 0; j < n + i; j++)                                                                                                                        
        {
            // Create a blank space in exact center of the pyramid
            if (j == n - i - 1 || j == n + i - 1)
                printf("#");
            else
                //otherwise print " "
                printf(".");
        }
        printf("\n");
    }
}

输出:

....#
...#.#
..#...#
.#.....#
#.......#

如果您注意到,通过数学方式思考这一点,您可以节省大量操作。例如在第二个 for() 循环中,OP 和其他答案有超过 1 个操作,其中 this 有 1 个,在 if/else 中都有超过 2 个相等语句,这个有 2.

注意:我使用 . 而不是 进行演示。