From time to time it has been asked how to build standard 2D shapes with simple loops. It could be a rectangle of some sort or a right / equilateral triangle. Maybe even a triangle that is facing the left rather than facing the right. Even the diamond pattern is a good one asked by many instructors around. But why on Earth would instructors ask you to build these types of shapes during that introductory class in programming? Simple, loops and nested loops are some of the most widely used control structures in programming. To know how to set them up and nest them is of great value later when it comes to building more complex applications. We take a glimpse into this world of looping as we build some common shapes… right here on this entry of the Programmer’s Underground!
The examples in this entry are done in Java but the syntax can almost be carried over statement for statement into C++ (the only thing you have to be cautious over is the printing statements). All these shapes involve some form of nested loops. That is, loops within loops to execute lines of code.
The best way I like to think about shape building this way is to imagine a box that will surround the shape. Each box will have a series of rows and columns. Pretty much like you standard spreadsheet. When you go to setup your loops you are going to typically start with looping through a row or a column first, while the inner loop will loop through the opposite of the outer loop. So if the first loop is looping through rows, the inner loop is looping through columns.
So lets start with our first shape and see this box that we can use later for building.
public static void rectangle(int rows, int cols) { // Loop through the rows for (int i = 0; i < rows; i++) { // Loop through the columns and print an asterisk for each column of the row. for (int j = 0; j < cols; j++) { System.out.print("*"); } // Go to the next row. System.out.println(); } }
From the code above you can see that the function takes a number of rows and columns. The outer loop loops through our rows while the inner loop loops through the columns. As we go through each column of a given row, we print an asterisk. The result is that we can build any size rectangle we want.
With this basic setup of a loop within a loop, we can build some other shapes similar to rectangles like right triangles. Right triangles are triangles which have one corner that is 90 degrees or a “right angle”. The great thing about this shape is that it is related to a rectangle in that it is typically half a rectangle (cut diagonally).
Besides printing just our asterisks, we may also need to keep track of the spaces. In our right triangle, our first row is going to have 1 asterisk and the rest spaces. The last row is then going to be all asterisks and no spaces. Where we put these spaces will determine our direction of the right triangle. As we progress down the rows, the number of spaces is going to shrink. It shrinks because the number of asterisks grow. So row 1 is going to have one asterisk and 4 spaces in a right triangle which has 5 columns. The last row is going to have five asterisks and no spaces.
Lets take a look at how this might be done for a right triangle that faces to the right…
public static void rightTriangle(int rows) { // Find out our starting space count int spaces = rows - 1; // Loop through each row for (int i = 0; i < rows; i++) { // This row is going to print asterisks that is equal to the row minus the spaces count for (int j = 0; j < (rows - spaces); j++) { System.out.print("*"); } // New row System.out.println(); // Decrease the space count so next row will have one more asterisk spaces--; } }
So as you can see from the example, we just need to specify the number of rows and the width of asterisks will be the same. We start row 1 with the row count minus 1. This makes spaces one less than the row and thus if the rows was 5, it will have 4 spaces and 1 asterisk. We then loop through each row subtracting the number of spaces from the row count. This will tell us how many asterisks to print. In this instance we don’t have to worry about actually inserting the spaces because they are the end of each line. But in our next example, when we flip directions, we have to perpend the spaces onto the front so we will have to get the spaces count and add those first before printing asterisks.
Lets flip this triangle the other direction and show how we add the spaces….
public static void leftRightTriangle(int rows) { // Find out our starting space count int spaces = rows - 1; // Loop through the rows for (int i = 0; i < rows; i++) { // Here we have to first print the spaces before our asterisks // So we loop through the spaces and print those. for (int j = 0; j < spaces; j++) { System.out.print(" "); } // Then we loop through the remaining columns of the row and print asterisks. // Again we find asterisks by taking our row and subtracting the number of spaces. for (int j = 0; j < (rows - spaces); j++) { System.out.print("*"); } // New row System.out.println(); // Decrease the space count, resulting in another asterisk printing next time around. spaces--; } }
Are you seeing a trend here between these examples so far? We have used the same loop for moving through the rows and at least one inner loop to move through the columns. The last example we used two loops, but each of them were still moving through the columns once per row. Lets go onto some trickier ones where we have to get creative with the spaces. Next up is the equilateral triangle. That is, a triangle which has the same length sides.
public static void equilateralTriangle(int rows) { // Find the number of spaces for the row int spaces = rows - 1; // Loop through the rows for (int i = 0; i < rows; i++) { // Print the spaces in front of each row (similar to our left facing right triangle) for (int j = 0; j < spaces; j++) { System.out.print(" "); } // Here we are printing the asterisk with a space on the end for nice equal formatting // But this still results in asterisk count which is the row minus the spaces for (int j = 0; j < (rows - spaces); j++) { System.out.print("* "); } // Next row System.out.println(); // Subtract the spaces spaces--; } }
As you can see we perpend the spaces to each line like the left facing right triangle, but this time we are adding a space onto the end of each asterisk so that we get a staggered formation and is of equal length sides.
Last but not least, the diamond shape. This shape is essentially an equilateral triangle with another one flipped upside down, sharing its base. So we setup the first part just like an equilateral triangle, but then go the opposite direction with it afterwards (that is, decrease the amount of asterisks by increasing the number of spaces). Here is the example…
public static void diamond(int rows) { // Start our spaces just like an equilateral triangle int spaces = rows - 1; // Loop through the rows for (int i = 0; i < rows; i++) { // Perpend spaces just like our equilateral triangle for (int j = 0; j < spaces; j++) { System.out.print(" "); } for (int j = 0; j < (rows - spaces); j++) { System.out.print("* "); } System.out.println(); spaces--; } // Restart the spaces at 1 and this time increase spaces to form bottom half of diamond spaces = 1; for (int i = rows; i >= 0; i--) { for (int j = 0; j < spaces; j++) { System.out.print(" "); } for (int j = 0; j < (rows - spaces); j++) { System.out.print("* "); } System.out.println(); // Notice here we increase spaces so we decrease asterisks being printed. spaces++; } }
So now with these methods you can expand on them and making them into all sorts of shapes. As long as you keep track of the rows (and make sure you setup your for loops to iterate the right number of rows) and columns you can easily make modifications in the inner or outer loops to adjust output. This may include detecting a specific row number (if row equals 3, print this pattern) or even print only every other row by using the modulus operator so that you print only on even or odd rows.
This tactic is great for printing things like the faces of dice as well for those who are doing dice related games in a console application. The 2D console drawing world is now your oyster! Enjoy the functions and thank you again for reading! 🙂