콘솔에 삼각형

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


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

삼각형 출력 부분을 main() 메소드에서 하지 않고, 별도로 구현된 printTriange() 메소드에서 하기로 한다. 이 메소드는 public 이고 static인 메소드(또는 함수)로 선언하여 어느 것에서든지 쉽게 불러 쓸 수 있도록 하였다. 이 문서의 모든 예제 소스 코드는 메소드를 적절히 구현하여 소스에서 역할 분담을 하게 하는 것이 얼마나 중요한지 알려주기 위해 재작성된 소스 코드들이다.


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


삼각형 출력 예제 1
/*
 *  Filename: PrintTriangleFn1.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn1.java
 *  Execute: java PrintTriangleFn1
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn1 {

    public static void printTriange() {
        System.out.println("        *        ");
        System.out.println("       * *       ");
        System.out.println("      *   *      ");
        System.out.println("     *     *     ");
        System.out.println("    *       *    ");
        System.out.println("   *         *   ");
        System.out.println("  *           *  ");
        System.out.println(" *             * ");
        System.out.println("*****************");
    }

    public static void main(String[] args) {
        printTriange();
    }
}


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



삼각형 출력 예제 2
/*
 *  Filename: PrintTriangleFn2.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn2.java
 *  Execute: java PrintTriangleFn2
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn2 {

    public static void printTriange() {
        for (int i = 0; i < 8; i++) {
            for (int k = 0;  k < 8 - i; k++) {
                System.out.print(" ");
            }
            for (int k = 0;  k < 2*i + 1; k++) {
                if (k == 0 || k == 2*i)
                    System.out.print("*");
                else
                    System.out.print(" ");
            }
            for (int k = 0;  k < 8 - i; k++) {
                System.out.print(" ");
            }
            System.out.println();
        }

        for (int i = 0; i < 17; i++) {
            System.out.print("*");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printTriange();
    }
}



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



삼각형 출력 예제 3
/*
 *  Filename: PrintTriangleFn3.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn3.java
 *  Execute: java PrintTriangleFn3
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn3 {

    public static void printTriange() {
        String line = "                 ";
        StringBuffer line2 = new StringBuffer("");
        for (int i = 0; i < 8; i++) {
            line2 = new StringBuffer(line);
            line2.setCharAt(8-i, '*');
            line2.setCharAt(8+i, '*');
            System.out.println(line2);
        }

        line2 = new StringBuffer(line);
        for (int i = 0; i < 17; i++) {
            line2.setCharAt(i, '*');
        }
        System.out.println(line2);
    }

    public static void main(String[] args) {
        printTriange();
    }
}



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


삼각형 출력 예제 4
/*
 *  Filename: PrintTriangleFn4.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn4.java
 *  Execute: java PrintTriangleFn4
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn4 {

    public static void printTriange() {
        String whites = "                 ";
        String stars  = "*****************";
        StringBuffer line2 = new StringBuffer(whites);
        line2 = line2.replace(8, 9, "*");
        System.out.println(line2);

        for (int i = 1; i < 8; i++) {
            line2 = new StringBuffer(whites);
            line2 = line2.replace(8-i, 8+i, stars.substring(8-i, 8+i));
            line2 = line2.replace(8-i+1, 8+i-1, whites.substring(8-i, 8+i-1));
            System.out.println(line2);
        }

        System.out.println(stars);
    }

    public static void main(String[] args) {
        printTriange();
    }
}




빈칸 문자를 별(*) 문자로 바꾸기 위해, 위의 소스 코드에서는 StringBuffer.replace() 메소드를 이용하였지만, 다음 소스 코드에서는 StringBuffer.setCharAt() 메소드를 이용하였다.



삼각형 출력 예제 5
/*
 *  Filename: PrintTriangleFn5.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn5.java
 *  Execute: java PrintTriangleFn5
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn5 {

    public static void printTriange() {
        String whites = "                 ";
        String stars  = "*****************";
        StringBuffer line = new StringBuffer(whites);
        int start = 8;
        line = line.replace(start, start, "*");
        System.out.println(line);

        for (int i = 1; i < 8; i++) {
            line = new StringBuffer(whites);
            line.setCharAt(start - i, stars.charAt(start - i));
            line.setCharAt(start + i, stars.charAt(start + i));
            System.out.println(line);
        }

        System.out.println(stars);
    }

    public static void main(String[] args) {
        printTriange();
    }
}




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



삼각형 출력 예제 6
/*
 *  Filename: PrintTriangleFn6.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn6.java
 *  Execute: java PrintTriangleFn6
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn6 {

    public static void printTriange() {
        String whites = "        ";
        String stars  = "********";
        int start = 8;
        StringBuffer line = new StringBuffer(whites);
        line.append('*');
        line.append(whites);
        System.out.println(line);

        for (int i = 1; i < 8; i++) {
            line = new StringBuffer(whites);
            line.setCharAt(start - i, stars.charAt(start - i));
            System.out.print(line);
            System.out.print(" ");
            line.reverse();
            System.out.println(line);
        }

        line = new StringBuffer(stars);
        line.append('*');
        line.append(stars);
        System.out.println(line);
    }

    public static void main(String[] args) {
        printTriange();
    }
}




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



삼각형 출력 예제 7
/*
 *  Filename: PrintTriangleFn7.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn7.java
 *  Execute: java PrintTriangleFn7
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn7 {

    public static void printTriange() {
        int start = 0x100;
        int total = 0;
        int val = start;
        String data;

        for (int k = 0; k < 8; k++) {
            val = (start << k) | (start >> k);
            data = Integer.toString(val, 2);
            for (int i = 0; i < 17 - data.length(); i++) {
                System.out.print(' ');
            }
            for (int i = 0; i < data.length(); i++) {
                if (data.charAt(i) == '0')
                    System.out.print(' ');
                else
                    System.out.print('*');
            }
            System.out.println();
            total += val;
        }

        val = (start << 8) | (start >> 8);
        total += val;
        data = Integer.toString(total, 2);
        for (int i = 0; i < 17 - data.length(); i++) {
            System.out.print(' ');
        }
        for (int i = 0; i < data.length(); i++) {
            if (data.charAt(i) == '0')
                System.out.print(' ');
            else
                System.out.print('*');
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printTriange();
    }
}




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

            total |= val;

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




삼각형 출력 예제 8
/*
 *  Filename: PrintTriangleFn8.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn8.java
 *  Execute: java PrintTriangleFn8
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn8 {

    public static void printTriange() {
        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 = Integer.toString(val, 2);
            line = zeros.substring(0, 17 - data.length()) + data;
            line = line.replaceAll("0", " ");
            line = line.replaceAll("1", "*");
            System.out.println(line);
            total |= val;
        }

        val = (start << 8) | (start >> 8);
        total |= val;
        line = Integer.toString(total, 2);
        line = line.replaceAll("0", " ");
        line = line.replaceAll("1", "*");
        System.out.println(line);
    }

    public static void main(String[] args) {
        printTriange();
    }
}




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



삼각형 출력 예제 9
/*
 *  Filename: PrintTriangleFn9.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn9.java
 *  Execute: java PrintTriangleFn9
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn9 {

    public static void printTriange() {
        int start = 8;
        ArrayList<String> data = new ArrayList<String>();
        ArrayList<String> last = new ArrayList<String>();

        for (int k = 0; k < 17; k++) {
            data.add(" ");
            last.add(" ");
        }
        data.set(start, "*");
        last.set(start, "*");
        for (int i = 0; i < data.size(); i++) {
            System.out.print(data.get(i));
        }
        System.out.println();
        data.set(start, " ");

        for (int k = 1; k < 8; k++) {
            data.set(start - k, "*");
            last.set(start - k, "*");
            data.set(start + k, "*");
            last.set(start + k, "*");

            for (int i = 0; i < data.size(); i++) {
                System.out.print(data.get(i));
            }
            System.out.println();
            data.set(start - k, " ");
            data.set(start + k, " ");
        }

        last.set(start - 8, "*");
        last.set(start + 8, "*");
        for (int i = 0; i < last.size(); i++) {
            System.out.print(last.get(i));
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printTriange();
    }
}




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

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

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




삼각형 출력 예제 10
/*
 *  Filename: PrintTriangleFn10.java
 *            Print a triangle on console.
 *
 *  Compile: javac -d . PrintTriangleFn10.java
 *  Execute: java PrintTriangleFn10
 *
 *      Date:  2008/04/01
 *    Author:  PH Kim   [ pkim (AT) scripts.pe.kr ]
 */

public class PrintTriangleFn10 {

    public static void printTriange() {
        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 = ' ';
                System.out.print(a);
            }
            System.out.println();
        }
    }
}





Creative Commons License

이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

Posted by Scripter
,