CS50x - Problem Set 1 - Mario.
mario more and pyramids
Let's start with the first problem in CS50.
Problem to solve
Toward the beginning of World 1-1 in Nintendo’s Super Mario Brothers, Mario must hop over adjacent pyramids of blocks.
In a file called mario.c in a folder called mario-more, implement a program in C that recreates that pyramid, using hashes (#) for bricks, as in the example below:
# ### ##### ####### ####And let’s allow the user to decide just how tall the pyramids should be by first prompting them for a positive int between, say, 1 and 8, inclusive.
Notice that width of the “gap” between adjacent pyramids is equal to the width of two hashes, irrespective of the pyramids’ heights.
Getting started
Let's break down the problem. First, I need to get user input on how tall the pyramid is going to be, between 1 and 8 "blocks" high. Then I can "print" the pyramid, one line at a time.
User input
This is easy enough, I'll take advantage of the <cs50.h> library and use the get_int( ) function. But to make sure it's the number I want, I need a modified while loop to keep asking for a number if it's not between 1 and 8.
Slightly new syntax, but nothing crazy:
// Initialize a variable to store user input
int n;
// Keep asking for n if it's not between 1 and 8
do
{
n = get_int("Pyramid height: ");
}
while (n < 1 || n > 8);
Here you can see I'm asking for "Pyramid height: " while n is less than 1 OR n is greater than 8.
I think this is also the first time I've shown comments, started as two backslashes \\ in C, which tells the compiler to ignore the following line of characters. Comments are useful in coding for keeping track of your thoughts, writing pseudocode, to-dos, or letting other people who have access to the project (including yourself in the future) know what the code is supposed to do.
Building the pyramid
So I have the height of the pyramid, stored in an int called n. The computer can't print out the whole pyramid at once, it doesn't know how. Instead, it'll print each line one at a time, and within each line, one character at a time. So to get the correct output, I need to start at the top of the pyramid, line 1 (line 0 for the computer), and work my way down.
To get the pyramid to display correctly, each line is made up of a certain amount of spaces, then blocks, then exactly 2 spaces (this is the only value that doesn't change), then blocks again. The next line has 1 less space, and 1 more block. The final line, of course, is made up of only blocks, because the pyramid is as wide as it is tall. Here's a visualization:
...#..#
..##..##
.###..###
####..####
Above, blocks are being represented by hashes # and spaces represented by periods .
I know that I'll always be starting at the top of the pyramid (even though I don't always know how tall the pyramid is going to be), and I also know that in every pyramid, the top will only have 1 block. The amount of blocks will increase per line, but it'll always start at 1. So let's initalize a variable:
int b = 1;
To figure out exactly how many spaces I need, I need to figure out the relationship between the blocks, spaces, and total height. In this case, it's a rather simple equation: The amount of spaces I need is the total height minus the amount of blocks. Let's declare another variable:
int s = n - b;
Now I have 2 variables with the right number of blocks (b) and spaces (s) I want the computer to print. I can take this time to practice a little abstraction. Instead of writing out a bunch of different loops and potentially losing track of the process, I made 2 new functions to handle the printing process for me:
void print_spaces(int spaces);
void print_blocks(int blocks);
The void in front of the functions just means that the function isn't returning a type of data (like an int or bool), it's just for printing to the screen. And inside the brackets, it's telling the computer to expect an int that means spaces, which is more semantics for me than for the computer, not the int part, that's important, but writing out spaces.
print_spaces(int spaces)
This function needs a very simple loop, I just want the computer to loop the amount of spaces I need, and each time print one space:
for (int i = 0; i < spaces; i++)
{
printf(" ");
}
print_blocks(int blocks)
This function is a little bit more involved, I'll need 2 loops. Because I want to print the amount of blocks twice with a double space " " in the middle:
// First loop only runs twice
for (int i = 0; i < 2; i++)
{
// Second loop runs for each block to print
for (int j = 0; j < blocks; j++)
{
printf("#");
}
// Only after the first set of blocks are done, print the double space
if (i == 0)
{
printf(" ");
}
}
// After both set of blocks are printed, create a new line
printf("\n");
Back to main
Now I know how many blocks and spaces to print, and I have the functions to print them for me, I need one more loop to go through the total height of the pyramid.
Our blocks (b) always starts at 1 and they also can't go past n, because that's the max height of the pyramid, so let's use a while loop to print the correct pyramid size:
int b = 1;
while (b <= n)
{
int s = n - b;
print_spaces(s)
print_blocks(b)
b++;
}
A few notes on the main loop: First, usually you set the limit of a loop to less than the number of times you want it to run, but that's because you usually start at 0. This time, however, I'm starting the count at 1, and I want to loop through when b = n as well. So, I set the loop to run while b <= n. Second, I moved the spaces variable into the loop, as I need to recalculate it before each run. And lastly, after printing the spaces and blocks, I increment b by 1 and the loop runs again.