콘솔에 삼각형

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


을 출력하는 C# 애플리케이션을 만들어 보자. 이런 소스 코드의 작성은 학원이나 학교에서 프로그래밍 입문자에게 과제로 많이 주어지는 것 중의 하나이다. 코끼리를 보거나 만진 사람들이 저마다 그 생김새를 말할 때 제각기 다르게 표현할 수 있듯이 이런 소스 코드의 작성도 알고 보면 얼마든지 많은 방법이 있을 것이다. 여기서는 쉬운 코드 부터 작성해 보고 차츰차츰 소스를 바꾸어 가면서 C# 프로그래밍의 기초부분을 터득해 보기로 한다.


우선 첫번 째로 다음 예제는 컨솔 출력 메소드 System.Console.WriteLine()의 사용법만 알면 누구나 코딩할 수 있는 매우 단순한 소스 코드이다.


삼각형 출력 예제 1
/*
 *  Filename: PrintTriangleApp1.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp1.cs
 *  Execute: PrintTriangleApp1
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;

namespace MyTestApplication1 {

    public class PrintTriangleApp1 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            Console.WriteLine("        *        ");
            Console.WriteLine("       * *       ");
            Console.WriteLine("      *   *      ");
            Console.WriteLine("     *     *     ");
            Console.WriteLine("    *       *    ");
            Console.WriteLine("   *         *   ");
            Console.WriteLine("  *           *  ");
            Console.WriteLine(" *             * ");
            Console.WriteLine("*****************");
        }
    }
}


위의 소스 코드는 아무 알고리즘도 없는 너무 단순한 코드이다. 이런 코드를 작성했다간 출력 모양이나 크기를 변경해야 하는 상황을 맞이하면 워드프로세서로 문서 만드는 것 이상으로 많은 수작업을 하거나 아니면 포기하는 지경에 이를 수도 있다. 그래서 다음처럼 좀 더 나은 소스 코드를 작성하였다.



삼각형 출력 예제 2
/*
 *  Filename: PrintTriangleApp2.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp2.cs
 *  Execute: PrintTriangleApp2
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;

namespace MyTestApplication1 {

    public class PrintTriangleApp2 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            for (int i = 0; i < 8; i++) {
                for (int k = 0;  k < 8 - i; k++) {
                    Console.Write(" ");
                }
                for (int k = 0;  k < 2*i + 1; k++) {
                    if (k == 0 || k == 2*i)
                        Console.Write("*");
                    else
                        Console.Write(" ");
                }
                for (int k = 0;  k < 8 - i; k++) {
                    Console.Write(" ");
                }
                Console.WriteLine();
            }

            for (int i = 0; i < 17; i++) {
                Console.Write("*");
            }
            Console.WriteLine();
        }
    }
}


위의 소스 코드는 출력 메소드 Console.WriteLine()과 Console.Write() 그리고 for 구문을 적절히 사용하여 구현되었다. 숫자 몇 곳만 수정하면 출력되는 삼각형의 크기를 바꿀 수 있다. 한 줄에 출력될 문자를 구성하는 알고리즘은 위의 예제와 근본적으로 같지만 Console.Write()를 사용하지 않고, 그대신 System.Text.StringBuilder 클래스를 적절히 사용하여 한 즐씩 출력하는 소스 코드를 다음 예제와 같이 작성해 보았다. 아래의 소스 코드에서 사용된 문자치환 메소드 StringBuilder.Replace()의 사용법은 다음과 같다.

using System.Text;
public StringBuilder StringBuilder.Replace(string oldValue, string newValue, int startIndex, int count);



삼각형 출력 예제 3
/*
 *  Filename: PrintTriangleApp3.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp3.cs
 *  Execute: PrintTriangleApp3
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;
using System.Text;

namespace MyTestApplication1 {

    public class PrintTriangleApp3 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            string line = "                 ";
            StringBuilder line2 = new StringBuilder("");
            for (int i = 0; i < 8; i++) {
                line2 = new StringBuilder(line);
                line2.Replace(" ", "*", 8-i, 1);
                line2.Replace(" ", "*", 8+i, 1);
                Console.WriteLine(line2);
            }

            line2 = new StringBuilder(line);
            for (int i = 0; i < 17; i++) {
                line2.Replace(" ", "*", i, 1);
            }
            Console.WriteLine(line2);
        }
    }
}



별(*) 문자를 이용하여 삼각형을 출력하는 일은 빈칸  문자와 별 문자를 적당한 좌표(위치)에 촐력하는 일이다. StringBuilder를 사용하더라도 한 줄의 출력을 빈칸 만으로로 구성된 string(소스 코드에서 변수 whites가 참조하는 string 값)을 기본으로 하고, 이 string에 한 두 개의 빈칸을 바꾸어 출력하는 기법으로 작성한 것이 다음 소스 코드이다. 단, 마지막 줄에 츨력될 string은 stars라는 별도의 변수로 처리하였다.



삼각형 출력 예제 4
/*
 *  Filename: PrintTriangleApp4.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp4.cs
 *  Execute: PrintTriangleApp4
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;
using System.Text;

namespace MyTestApplication1 {

    public class PrintTriangleApp4 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            String whites = "                 ";
            String stars  = "*****************";
            StringBuilder line2 = new StringBuilder(whites);
            line2.Replace(" ", "*", 8, 1);
            Console.WriteLine(line2);

            for (int i = 1; i < 8; i++) {
                line2 = new StringBuilder(whites);
                line2.Replace(whites.Substring(8-i, 1), stars.Substring(8-i, 1), 8-i, 1);
                line2.Replace(whites.Substring(8+i, 1), stars.Substring(8+i, 1), 8+i, 1);
                Console.WriteLine(line2);
            }

            Console.WriteLine(stars);
        }
    }
}



빈칸 문자를 별(*) 문자로 바꾸기 위해, 위의 소스 코드에서는 StringBuilder.Replace() 메소드를 이용하였지만, 다음 소스 코드에서는 StringBuilder[index] = char 메소드를 이용하였다.



삼각형 출력 예제 5
/*
 *  Filename: PrintTriangleApp5.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp5.cs
 *  Execute: PrintTriangleApp5
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;
using System.Text;

namespace MyTestApplication1 {

    public class PrintTriangleApp5 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            String whites = "                 ";
            String stars  = "*****************";
            StringBuilder line = new StringBuilder(whites);
            int start = 8;
            line[start] =  stars[8];
            Console.WriteLine(line);

            for (int i = 1; i < 8; i++) {
                line = new StringBuilder(whites);
                line[start - i] = stars[start - i];
                line[start + i] =  stars[start + i];
                Console.WriteLine(line);
            }

            Console.WriteLine(stars);
        }
    }
}




출력되는 삼각형이 좌우 대칭이라는 사실에 착안하여, 다음 소스 코드에서는  각 줄을 처음 8자, 중앙 한 문자, 끝 8자(처음 8자의 역순)로 string을 만들어 출력하였다.

Java 언아에는 StringBuffer.reverse()라는 메소드가 있어서 유익하였지만,
C# 언어에는  StringBuilderRreverse()라는 메소드가 없기에
Java 소스 코드

                line.reverse();
                System.out.println(line);

가 C# 소스 코드

                arrRev = line.ToString().ToCharArray();
                Array.Reverse(arrRev);
                Console.WriteLine( new String(arrRev) );

처럼 여러 단계를 거쳐 역순 문자열이 출력되었다.



삼각형 출력 예제 6
/*
 *  Filename: PrintTriangleApp6.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp6.cs
 *  Execute: PrintTriangleApp6
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;
using System.Text;

namespace MyTestApplication1 {

    public class PrintTriangleApp6 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            char[] arrRev;
            String whites = "        ";
            String stars  = "********";
            int start = 8;
            StringBuilder line = new StringBuilder(whites);
            line.Append('*');
            line.Append(whites);
            Console.WriteLine(line);

            for (int i = 1; i < 8; i++) {
                line = new StringBuilder(whites);
                line[start - i] = stars[start - i];
                Console.Write(line);
                Console.Write(" ");
                arrRev = line.ToString().ToCharArray();
                Array.Reverse(arrRev);
                Console.WriteLine( new String(arrRev) );
             }

            line = new StringBuilder(stars);
            Console.Write(line);
            line.Append("*");
            Console.WriteLine(line);
        }
    }
}




다음 소스 코드는 한 줄에 출력될 문자열의 데이터를 17비트 이진법 수로 구성하고, 이 이진법수의 비트가 0인 곳에는 빈칸을, 1인 곳에는 별(*)을 출력하는 기법으로 작성되었다.

int 타입을 2진법 표현 문자열로 표현하는 C# 소스 코드는 어떻게 될까?
Java 소스 코드는

                String strValue = Integer.parseInt(intValue, 2);

이다. 이를 C# 소스 코드로 재작성하면

                String strValue = System.Convert.ToString(intValue, 2);

이 된다.



삼각형 출력 예제 7
/*
 *  Filename: PrintTriangleApp7.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp7.cs
 *  Execute: PrintTriangleApp7
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;
using System.Text;

namespace MyTestApplication1 {

    public class PrintTriangleApp7 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            int start = 0x100;
            int total = 0;
            int val = start;
            String data;
            for (int k = 0; k < 8; k++) {
                val = (start << k) | (start >> k);
                data = Convert.ToString(val, 2);
                for (int i = 0; i < 17 - data.Length; i++) {
                    Console.Write(' ');
                }
                for (int i = 0; i < data.Length; i++) {
                    if (data[i] == '0')
                        Console.Write(' ');
                    else
                        Console.Write('*');
                }
                Console.WriteLine();
                total += val;
            }

            val = (start << 8) | (start >> 8);
            total += val;
            data = Convert.ToString(total, 2);
            for (int i = 0; i < 17 - data.Length; i++) {
                Console.Write(' ');
            }
            for (int i = 0; i < data.Length; i++) {
                if (data[i] == '0')
                    Console.Write(' ');
                else
                    Console.Write('*');
            }
            Console.WriteLine();
        }
    }
}




기본적인 원리는 위의 소스 코드와 같지만 이진법수의 한 비트 마다 한 문자씩 츨력하는 대신에 출력된 한 줄의 string을 완성하여 이를 Sytem.out.println()으로 출력하는 기법으로 재작성한 것이 다음의 소스 코드이다. String.replaceAll() 메소드를 이용하여, 모든 0을 빈칸으로, 모든 1을 별(*) 문자로 바꾸었으며, 별(*) 문자만으로 이루어진 마지막 줄 출력을 위해 변수 total을 준비하였다. for 반복 구문의 블럭 내에서 구문

            total |= val;

이 하는 일이 무엇인지 이해할 수 있으면 좋겠다.




삼각형 출력 예제 8
/*
 *  Filename: PrintTriangleApp8.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp8.cs
 *  Execute: PrintTriangleApp8
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;
using System.Text;

namespace MyTestApplication1 {

    public class PrintTriangleApp8 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            String zeros  = "00000000";
            int start = 0x100;
            int total = 0;
            int val = start;
            String line = "";
            String data;
            for (int k = 0; k < 8; k++) {
                val = (start << k) | (start >> k);
                data = Convert.ToString(val, 2);
                line = zeros.Substring(0, 17 - data.Length) + data;
                line = line.Replace("0", " ");
                line = line.Replace("1", "*");
                Console.WriteLine(line);
                total |= val;
            }

            val = (start << 8) | (start >> 8);
            total |= val;
            line = Convert.ToString(total, 2);
            line = line.Replace("0", " ");
            line = line.Replace("1", "*");
            Console.WriteLine(line);
        }
    }
}




소스 코드가 처음 것 보다 매우 복잡해졌지만 저너릭(generics)을 지원하는 리스트(System.Collections.Genericl.List)를 이용해서도 할 수 있다는 것을 보여주기 위해서 일부러 작성해보았다. C# 2.0 부터 등장한 저너릭를 이용한 소스 코드이므로 C# 2.0 이상에서 컴파일되어야 한다. 별(*) 문자만으로 이루어진 마지막 줄 출력을 위해 변수 last를 준비하였다.



삼각형 출력 예제 9
/*
 *  Filename: PrintTriangleApp9.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp9.cs
 *  Execute: PrintTriangleApp9
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace MyTestApplication1 {

    public class PrintTriangleApp9 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            int start = 8;
            List<String> data = new List<String>();
            List<String> last = new List<String>();
            for (int k = 0; k < 17; k++) {
                data.Add(" ");
                last.Add(" ");
            }
            data[start] = "*";
            last[start] = "*";
            for (int i = 0; i < data.Count; i++) {
                Console.Write(data[i]);
            }
            Console.WriteLine();
            data[start] = " ";

            for (int k = 1; k < 8; k++) {
                data[start - k] = "*";
                last[start - k] = "*";
                data[start + k] = "*";
                last[start + k] = "*";

                for (int i = 0; i < data.Count; i++) {
                    Console.Write(data[i]);
                }
                Console.WriteLine();

                data[start - k] = " ";
                data[start + k] = " ";
            }

            last[start - 8] = "*";
            last[start + 8] = "*";
            for (int i = 0; i < last.Count; i++) {
                Console.Write(last[i]);
            }
            Console.WriteLine();
        }
    }
}




다음 예제는 수학에서 xy-좌표평면에 점을 찍듯이 논리 구문

             (x + y - 8 == 0) || (y - x + 8 == 0) || (y - 8 == 0)

가 참이 되는 위치에 별(*) 문자를 표시하는 기법으로 작성된 소스 코드이다.




삼각형 출력 예제 10
/*
 *  Filename: PrintTriangleApp10.cs
 *            Print a triangle on console.
 *
 *  Compile: csc PrintTriangleApp10.cs
 *  Execute: PrintTriangleApp10
 *
 *      Date:  2009/01/24
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace MyTestApplication1 {

    public class PrintTriangleApp10 {
        // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
        public static void Main(string[] args) {
            char a;
            for (int y = 0; y <= 8; y++) {
                for (int x = 0; x <= 16; x++) {
                    if ((x + y - 8 == 0) || (y - x + 8 == 0) || (y - 8 == 0))
                        a = '*';
                    else
                        a = ' ';
                    Console.Write(a);
                }
                Console.WriteLine();
            }
        }
    }
}


Posted by Scripter
,