c++recursionascii-art

C++ - How do I draw an isosceles right side up triangle using recursion?


Write a recursive function called DrawTriangle() that outputs lines of '*' to form a right side up isosceles triangle. Function DrawTriangle() has one parameter, an integer representing the base length of the triangle. Assume the base length is always odd and less than 20. Output 9 spaces before the first '*' on the first line for correct formatting.

Hint: The number of '*' increases by 2 for every line drawn.

Ex: If the input of the program is: 3 the function DrawTriangle() outputs:

         *
        ***

Ex: If the input of the program is: 19 the function DrawTriangle() outputs:

         *
        ***
       *****
      *******
     *********
    ***********
   *************
  ***************
 *****************
*******************

Note: No space is output before the first '*' on the last line when the base length is 19.

I was able to make the triangle correctly with the following recursive function:

void DrawTriangle(int baseLength, int spaces = 0) {
   if(baseLength <= 0){
    return;  
   }  
   
   DrawTriangle(baseLength - 2, spaces + 1);
   
   for(int i = 0; i < spaces; i++){
    cout << ' ';  
   }   
   
  for(int i = 0; i < baseLength; i++){
   cout << '*';  
  } 
  cout << endl;
}

The problem I am having is that I have no idea how to get the correct spacing that is required, which is 9 spaces before the singular star


Solution

  • Since the first line should always start with 9 spaces, no matter what baseLength is, you should change the logic a bit.

    To fix your code with only little change, you could add this statement at the top of your function:

    if (spaces == 0) spaces = 9 - baseLength / 2;
    

    This says that if it was the first call (spaces == 0), then the bottom line in the output should have 9 - baseLength / 2 spaces.

    This will give the desired output, but it looks more complex than it should be.

    The number of spaces to print is directly related to the value of baseLength, so you could do without the spaces parameter.

    Also, you can replace the i-loops and use std::cout to print a character N times:

    void DrawTriangle(int baseLength) {
        if (baseLength <= 0) {
            return;  
        }  
        DrawTriangle(baseLength - 2);
        std::cout << std::string(9 - baseLength/2, ' ') << std::string(baseLength, '*') << std::endl;
    }
    

    Recursion seems overkill here: you can instead do this with a loop that produces one line per iteration, starting at the top.

    void DrawTriangle(int baseLength) {
        for (int stars = 1; stars <= baseLength; stars+=2) {
            std::cout << std::string(9 - stars/2, ' ') << std::string(stars, '*') << std::endl;
        }
    }