Mario

要解决的问题

在任天堂 Super Mario Bros. 第 1-1 关的末尾附近,Mario 必须攀爬一个右对齐的砖块金字塔,如下图所示。

screenshot of Mario jumping up a right-aligned pyramid

在名为 mario-less 的文件夹中的 mario.c 文件中,用 C 语言实现一个程序来重建那个金字塔,使用井号(#)表示砖块,如下图所示:

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

但要提示用户输入一个 int 类型的金字塔实际高度,这样程序也能输出如下较矮的金字塔:

  #
 ##
###

如果用户输入的值不大于 0 或根本不是 int 类型,则根据需要反复提示用户。

提示
  • 记住你可以通过 int 从用户那里获取 get_int, 该函数声明在 cs50.h.
  • 记住你可以打印一个 string with printf, 该函数声明在 stdio.h.

演示

建议

先写一些确定能编译的代码

即使这个程序暂时什么也不做,它至少应该能用 make 编译!

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

int main(void)
{

}
在继续写更多代码前,先写一些伪代码

如果你还不确定如何解决问题本身,可以先把它拆成几个更小、你大概能先解决的问题。例如,这个问题其实就是两个问题:

  1. 提示用户输入金字塔高度
  2. 打印对应高度的金字塔

因此,先把伪代码写成注释,提醒自己要完成这些步骤:

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

int main(void)
{
    // Prompt the user 的 pyramid's height

    // Print a pyramid of that height
}
把伪代码转换成代码

首先,思考如何提示用户输入金字塔高度。回忆一下,当你希望某件事至少执行一次,并且可能反复执行时,do while 循环会很有帮助,如下所示:

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

int main(void)
{
    // Prompt the user 的 pyramid's height
    int n;
    do
    {
        n = get_int("Height: ");
    }
    while (n < 1);

    // Print a pyramid of that height
}

其次,思考如何从上到下打印该高度的金字塔。注意第一行应有一块砖,第二行应有两块砖,依此类推。你很可能需要一个循环,如下所示;即使暂时还不确定循环里该写什么,也可以先添加一些伪代码注释:

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

int main(void)
{
    // Prompt the user 的 pyramid's height
    int n;
    do
    {
        n = get_int("Height: ");
    }
    while (n < 1);

    // Print a pyramid of that height
    for (int i = 0; i < n; i++)
    {
        // Print row of bricks
    }
}

如何打印那一行砖块呢?如果有一个名为 print_row 的函数能完成这件事,不是很好吗?让我们假设有这样一个函数:

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

void print_row(int bricks);

int main(void)
{
    // Prompt the user 的 pyramid's height
    int n;
    do
    {
        n = get_int("Height: ");
    }
    while (n < 1);

    // Print a pyramid of that height
    for (int i = 0; i < n; i++)
    {
        // Print row of bricks
    }
}

void print_row(int bricks)
{
    // Print row of bricks
}

然后我们就可以从 main 中调用该函数,如下图所示:

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

void print_row(int bricks);

int main(void)
{
    // Prompt the user 的 pyramid's height
    int n;
    do
    {
        n = get_int("Height: ");
    }
    while (n < 1);

    // Print a pyramid of that height
    for (int i = 0; i < n; i++)
    {
        // Print row of bricks
        print_row(i + 1);
    }
}

void print_row(int bricks)
{
    // Print row of bricks
}

但为什么是 i + 1 呢?

现在让我们来实现 print_row

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

void print_row(int bricks);

int main(void)
{
    // Prompt the user 的 pyramid's height
    int n;
    do
    {
        n = get_int("Height: ");
    }
    while (n < 1);

    // Print a pyramid of that height
    for (int i = 0; i < n; i++)
    {
        // Print row of bricks
        print_row(i + 1);
    }
}

void print_row(int bricks)
{
    for (int i = 0; i < bricks; i++)
    {
        printf("#");
    }
    printf("\n");
}

但为什么末尾要有 \n 呢?

不幸的是,这段代码打印的是左对齐的金字塔,而你需要的是右对齐的!或许我们应该在一些砖块前打印一些空格来将它们右移?让我们按如下方式修改 print_row,使其能同时打印空格和砖块:

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

void print_row(int spaces, int bricks);

int main(void)
{
    // Prompt the user 的 pyramid's height
    int n;
    do
    {
        n = get_int("Height: ");
    }
    while (n < 1);

    // Print a pyramid of that height
    for (int i = 0; i < n; i++)
    {
        // Print row of bricks
    }
}

void print_row(int spaces, int bricks)
{
    // Print spaces

    // Print bricks
}

现在 mainprint_row 中都还留有一些伪代码,接下来就交给你完成了!

也可以思考一下,是否能把 main 中的一部分代码提取到一个 get_height 函数中,让它返回你需要的 int

讲解视频

如何测试

你的代码在以下输入情况下是否按预期工作:

  • -1 或其他负数?
  • 0
  • 1 或其他正数?
  • 字母或单词?
  • 只按 Enter 键,不输入任何内容?

正确性

check50 cs50/problems/2026/x/mario/less

代码风格

style50 mario.c

如何提交

在终端中执行以下命令提交你的作业,并按提示完成操作。

submit50 cs50/problems/2026/x/mario/less