Mario
Aufgabe
Gegen Ende von Welt 1-1 in Nintendos Super Mario Bros. muss Mario eine rechts ausgerichtete Pyramide aus Steinen erklimmen, wie in der folgenden Abbildung.
Wir wollen in dieser Aufgabe eine solche Pyramide über die Konsolenausgabe eines Programmes nachbilden, indem wir Hashes (#
) für die Steine verwenden, wie im Folgenden gezeigt:
#
##
###
####
#####
######
#######
########
Allerdings sollte der Benutzer gebeten werden, die tatsächliche Höhe der Pyramide mit int
anzugeben, damit das Programm auch kürzere Pyramiden ausgeben kann. Zum Beispiel eine dreistufige:
#
##
###
Wenn die Eingabe des Benutzers nicht größer als 0 oder kein int
ist, fordern Sie ihn immer wieder erneut auf, eine passende Eingabe zu tätigen.
Implementieren Sie dieses Programm in C in einer Datei namens mario.c
in einem Ordner namens mario
.
mkdir mario
mit dem Befehl pwd
, in welchem Verzeichnis Sie aktuell befinden. Wenn Sie diese Aufgabe im Anschluss an Hello, It’s Me bearbeiten, befinden Sie sich vermutlich noch in me
. Um in der Verzeichnisstruktur wieder nach oben zu gelangen, können Sie cd ../
eingeben. Anschließend können Sie alle Schritte für die Erstellung von Ordner und Datei analog zu Hello, It’s Me wiederholen.
Tipps
- Erinnern Sie sich, dass Sie einen
int
von einem Benutzer mitget_int
erhalten können, das incs50.h
deklariert ist (siehe manual.cs50.io). Wie verhält sich die Funktion laut Beschreibung im Handbuch, wenn keinint
eingegeben wird? - Erinnern Sie sich, dass Sie einen
string
mitprintf
ausgeben können, das instdio.h
deklariert ist.
Demo
Hilfestellung
Klicken Sie auf die folgenden Tipps, um einige Ratschläge zu erhalten. Versuchen Sie aber zunächst, selbst so weit wie möglich zu kommen.
Beginnen Sie mit Code, der kompilierbar ist
Auch wenn dieses Programm noch nichts tut, sollte es zumindest mit make
kompiliert werden können!
#include <cs50.h>
#include <stdio.h>
int main(void)
{
}
Denken Sie daran, dass Sie jetzt cs50.h
und stdio.h
eingebunden haben. Zwei “Header-Dateien”, die Ihnen Zugang zu Funktionen geben, die Ihnen bei der Lösung dieses Problems helfen könnten.
Versuchen Sie das Problem in Pseudocode zu beschreiben
Wenn Sie unsicher sind, wie Sie das eigentliche Problem lösen können, unterteilen Sie es in kleinere Probleme, die Sie wahrscheinlich einfacher lösen können. Im Kern besteht diese Aufgabe eigentlich aus zwei Problemen:
- Die Aufforderung an den Benutzer, die Höhe der Pyramide einzugeben.
- Das Ausgeben einer Pyramide mit dieser Höhe.
Fügen Sie die identifizierten Probleme nun in Form von Pseudocode als Kommentare ein, um Sie dann nacheinander bearbeiten zu können.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
// Prompt the user for the pyramid's height
// Print a pyramid of that height
}
Wandeln Sie den Pseudocode in Code um
Überlegen Sie zunächst, wie Sie den Benutzer nach der Höhe der Pyramide fragen können. Erinnern Sie sich daran, dass eine do while
-Schleife hilfreich ist, wenn Sie etwas mindestens einmal und möglicherweise immer wieder tun wollen, wie in dem folgenden Beispiel:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
// Prompt the user for the pyramid's height
int height;
do
{
height = get_int("Height: ");
}
while (height < 1);
// Print a pyramid of that height
}
Überlegen Sie sich nun, wie Sie eine Pyramide mit dieser Höhe von oben nach unten ausgeben könnten. Beachten Sie, dass die erste Reihe (von oben betrachtet) aus einem Stein bestehen sollte, die zweite Reihe aus zwei Steinen und so weiter. Wahrscheinlich denken Sie bereits an eine Schleife, auch wenn Sie (noch!) nicht wissen, was Sie in diese Schleife einfügen sollen. Fügen Sie also erst einmal etwas mehr Pseudocode als Kommentar hinzu:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
// Prompt the user for the pyramid's height
int height;
do
{
height = get_int("Height: ");
}
while (height < 1);
// Print a pyramid of that height
for (int i = 0; i < height; i++)
{
// Print row of bricks
}
}
Wie kann man diese Reihe von Steinen ausdrucken? Nun, wäre es nicht schön, wenn es eine Funktion namens print_row
gäbe, die genau das tun könnte? Nehmen wir an, es gäbe sie (vergessen Sie nicht den Funktionsprototypen oberhalb der main
-Funktion einzufügen, wenn Sie die Funktion unterhalb der main
-Funktion definieren):
#include <cs50.h>
#include <stdio.h>
void print_row(int bricks);
int main(void)
{
// Prompt the user for the pyramid's height
int height;
do
{
height = get_int("Height: ");
}
while (height < 1);
// Print a pyramid of that height
for (int i = 0; i < height; i++)
{
// Print row of bricks
}
}
void print_row(int bricks)
{
// Print row of bricks
}
Wir können diese Funktion dann von main
aus innerhalb der for
-Schleife aufrufen, wie im Folgenden gezeigt:
#include <cs50.h>
#include <stdio.h>
void print_row(int bricks);
int main(void)
{
// Prompt the user for the pyramid's height
int height;
do
{
height = get_int("Height: ");
}
while (height < 1);
// Print a pyramid of that height
for (int i = 0; i < height; i++)
{
// Print row of bricks
print_row(i + 1);
}
}
void print_row(int bricks)
{
// Print row of bricks
}
Warum aber i + 1
?
Versuchen wir zuerst einmal print_row
zu implementieren:
#include <cs50.h>
#include <stdio.h>
void print_row(int bricks);
int main(void)
{
// Prompt the user for the pyramid's height
int height;
do
{
height = get_int("Height: ");
}
while (height < 1);
// Print a pyramid of that height
for (int i = 0; i < height; i++)
{
// Print row of bricks
print_row(i + 1);
}
}
void print_row(int bricks)
{
for (int i = 0; i < bricks; i++)
{
printf("#");
}
printf("\n");
}
Wissen Sie, wofür ein \n
am Ende ausgegeben wird?
Leider gibt dieser Code eine linksbündige Pyramide aus. Wir wollen aber eine rechtsbündige! Vielleicht könnten wir vor einige der Steine ein paar Leerzeichen setzen, um sie nach rechts zu verschieben? Ergänzen wir also print_row
wie folgt (vergessen Sie nicht den Funktionsprototypen oberhalb der main
-Funktion entsprechend zu ergänzen):
#include <cs50.h>
#include <stdio.h>
void print_row(int spaces, int bricks);
int main(void)
{
// Prompt the user for the pyramid's height
int height;
do
{
height = get_int("Height: ");
}
while (height < 1);
// Print a pyramid of that height
for (int i = 0; i < height; i++)
{
// Print row of bricks
}
}
void print_row(int spaces, int bricks)
{
// Print spaces
// Print bricks
}
Überlegen Sie sich nun also noch, wie Sie möglichst geschickt die Leerzeichen übergeben und ausgeben können. Und überlegen Sie sich zusätzlich, ob Sie nicht auch einen Teil des Codes in main
in eine get_height
-Funktion auslagern könnten, die den benötigten int
zurückgibt!
Testen
Funktioniert Ihr Code wie vorgesehen, wenn Sie folgendes eingeben:
-1
oder andere negative Zahlen?0
?1
oder andere positive Zahlen?- Buchstaben oder Wörter?
- überhaupt keine Eingabe, wenn Sie nur Enter drücken?
Korrektheit
Führen Sie in Ihrem Terminal den folgenden Befehl aus, um die Korrektheit Ihrer Arbeit zu überprüfen:
check50 -l cs50/problems/2024/x/mario/less
Style
Führen Sie den folgenden Befehl aus, um den Stil Ihres Codes mit style50
zu analysieren:
style50 mario.c