정상혁정상혁

CCK(Creative Commons Korea)의 Code can be an art 행사에서는 '코드잼’이라는 순서가 있었습니다.

'Code can be an art’라는 문자열을 출력하는 프로그램을 자유롭게 짜서 발표하는 것이였죠.

코드잼 설명 : http://ccsalon.tistory.com/4

저도 이날 점심을 먹는 것도 잊고 나름대로 코드를 준비해 갔는데, 발표를 하지는 못했네요 . 발표자가 적은 분위기면 앞에 나가볼려고 노트북까지 들고 가기는 했었습니다 ^^; 그런데 열띤 호응으로 많은 분들이 발표를 하셨고, MSX 에뮬레이터로 하신 분 등 제가 말하고 싶었던 내용을 다른 분들이 더 훌륭히 말씀해 주셔서 큰 아쉬움은 없습니다.

8bit 화면 같은 행사 로고를 보고 저도 제 세대에 맞게 Quick Basic으로 코드를 짜볼 생각을 해봤습니다. 이 행사 중에 '8bit kid의 생애’라는 패널토론 주제도 있었었죠. ^^; 저는 그 다음 시대인 IBM XT세대입니다. 허큘리스 그래픽카드, 5.25인치 FDD, 조금 지나서 ADLIB card, 2400bps MNP 모뎀 등이 저에게는 가슴을 파고드는 핵심단어들이에요.

ccsalon_banner

그 추억의 시절에 제가 가장 많아 가지고 놀았던 프로그램 언어가 Quick-Basic이였습니다. Basic에서 행번호를 없애고 구조화프로그래밍 개념을 도입한, 당시 저에게는 충격적으로 대단한 언어였어요. 이 도구에다 basic을 배웠던 사람이면 누구나 회상할 추억의 명령어 line(선긋기), play(음악연주), read,data(데이터 읽는 구문)을 넣어서 코딩을 해봐야겠다고 마음 먹었습니다. 대신 제 PC환경상 그때의 Quick-basic 대신 Window XP에 내장되어 있는 q-basic을 사용할 수 밖에 없었어요. 프롬프트에서 qbasic이라고 치면 언제나 튀어나오는 도구죠.

Quick-Basic과 q-basic이 뭐가 다르냐구요? 문법은 거의 똑같은것 같아요. Quick-basic은 따로 패키지로 나와서 버전4.5까지 발표되었었는데, q-basic은 어느 새 MS-DOS의 상위버전에 포함되어서 나오더군요 . Quick-Basic에서는 실행파일(.exe)도 만들 수 있고, 각종 라이브러리도 많았었습니다. 아뭏든 대타로 q-basic을 썼기에 실행할때는 아래와 같이 치면 됩니다.

프롬프트> qbasic/run cba2.bas

단순히 화면에 큰 글자를 찍어주는 것 밖에 없지만, 꽤나 시행착오 작업을 많이 거쳤었습니다. 예전 Quick-Basic에서는 screen 12라는 화면모드를 주로 썼었었는데, 이번 환경에서는 screen 2 밖에 안 먹는 것이였습니다. 화면 전체 해상도가 몇곱하기 몇 인지도 모르고 그냥 무작정 네모를 그리는 숫자값을 바꿔가면서 화면을 만들어 봤습니다. 결국 한참 후에야 그럭저럭 화면중간에 크게 들어간 글자를 얻어낼 수가 있었죠. 평소에 일할 때 이렇게 무식하게 작업을 한다면 스스로 한심하게 느껴졌겠지만 이번에는 그것조차도 옛 추억을 되살리는 즐거움이였습니다.

그리고 이 프로그램에 들어간 멜로디를 아시는 분이라면 아마 저하고 비슷한 컴퓨터 세대이실 것 같아요. 불후의 고전명작게임 'Loom’의 메인테마 입니다. 처음에 노트북을 들고 행사장에 갈때까지만 해도 프로그램에서는 단순히 '도미솔' 정도의 소리만 났었습니다. 그러다가 행사가 끝난 다음 주에 문득 여기에다 듣기좋은 멜로디를 넣어보고 싶다는 충동을 느꼈고, 그때 게임 'Loom’의 음악이 머리 속에 떠올랐습니다. 당연히 악보 같은 건 없었고 기억하는 멜로디를 스스로 휘파람으로 불어서 청음으로 코드를 만들었습니다. 남다른 음감각을 가진 것도 아니어서 계속 시행착오를 거치면서 play문에 들어가는 음표코드를 넣었죠. 어쩐지 박자와 음이 약간 어설프고 불안정한 느낌이 들지 않나요?

행사 때 김국헌님께서 발표하시는 분들마다 물어보셨던 말이 있었습니다. '이 작업을 하시면서 즐거웠습니까?'' 저도 여기에 그떄 다른 분들이 하셨던 말과 똑같이 '네. 굉장히 즐거웠습니다’라고 말할 수 밖에 없네요. 한 때는 왠만한 단축키는 다 외웠었던 Quick-Basic이였는데 오랜만에 쓸려니 함수 선언방법 조차도 가물가물 하더군요. 그래도 기억을 되살려 가면서 작업을 하다보니 이런 도구로 고등학교 때 축제 전시회 때 내놓을 게임을 만들던 일이 생각이 났었습니다. 그 때 정말 밥 먹는 시간도 잊어 버릴 정도로 매달려서 어설픈 게임을 만들었고, 어쩌면, 아니 확실히 그런 기억들 때문에 지금도 컴퓨터 코드를 짜는 일을 하고 있다는 사실도 새삼스럽게 떠올랐습니다.

뭐 어떤 분들은 이 글을 보시면, 몇줄 안되고 실행결과도 허접한 프로그램 짜놓고 제목은 아트니 뭐니 되어 있고 되게 거창한 척을 한다고 느끼실 것 같습니다. 하지만 누가 뭐래든 이 코드를 짜던 순간, 그리고 Quick-Basic이 어떤거니 하는 , 요즘은 별 정보도 되지 않을 이런 글을 주절주절 쓰고 있는 이 순간까지도 행복감의 여운을 느낌니다.

다 해놓고 보니 코드는 그리 길지는 않네요~

DECLARE SUB display (c$, p$)

SCREEN 2
lg$ = " Code can be an art! "
DATA "t90O1p4","e8","a8","b8",">c+8","g8","f8","<a8"
DATA ">d8","c+8","<e2","e8","a4","b8",">c+4","<b8","a2","e2","p4","p4","p4","p4"
FOR i = 1 TO LEN(lg$)
    READ p$
    display MID$(lg$, i, 1), p$
NEXT i
SCREEN 0
END

SUB display (c$, p$)
PLAY p$
CLS
PRINT c$
FOR i = 0 TO 10
  FOR j = 0 TO 10
    IF POINT(j, i) THEN LINE (j * 60 + 80, i * 25 + 10)-(j * 60 + 140, i * 25 + 40), 1, BF
  NEXT j
NEXT i
LOCATE 1, 1
PRINT " "

END SUB
정상혁정상혁

2007년 회사 워크샵 갔었을 때 풀었던 문제와 답

문제

image

풀이

정상혁&이상미 조의 풀이 답입니다.

public class MatrixMain {
    public static void main(String[] args) {
       Matrix mp = new Matrix(5,5);
       mp.locateNumbers();
       mp.print();
    }
}

public class Matrix {

    public static final int RIGHT = 0;
    public static final int DOWN = 1;
    public static final int LEFT = 2;
    public static final int UP  = 3;

    private static final int INIT_VALUE = -1;

    private int m = 0;
    private int n = 0;
    private int[][] matrix;

    public Matrix(int m, int n){
        this.m = m;
        this.n = n;
        matrix = new int[m][n];
    }

    public void print(){
        for (int i=0;i< m ;i++){
            for (int j=0;j<n;j++) System.out.print(matrix[i][j] + "\t");
            System.out.println();
       }
    }

    public void locateNumbers() {
       init();
       int[] startPosition = new int[]{0,0};
       matrix[0][0]= 0;
       int direction = RIGHT;
       while(move(startPosition ,direction)) direction ++;
    }

    private void init() {
        for (int i=0;i< m ;i++){
            for (int j=0;j<n;j++) matrix[i][j] = INIT_VALUE;
        }
    }

    private boolean move(int[] position, int direction){
        int nowNumber = matrix[position[0]][position[1]];
        boolean moved = false;
        int[] nextPosition =getNextPosition(position,direction);
        while(isMovable(nextPosition[0],nextPosition[1])){
            moved = true;
            nowNumber++;
            position[0] = nextPosition[0];
            position[1] = nextPosition[1];
            matrix[position[0]][position[1]]= nowNumber;
            nextPosition = getNextPosition(position,direction);
        }
        return moved;
    }

    private int[] getNextPosition(int[] position,int direction){
        int x = position[0];
        int y = position[1];
        int nowDirection = direction%4;
        if (nowDirection == RIGHT) y++;
        else if (nowDirection == DOWN) x++;
        else if (nowDirection == LEFT) y--;
        else if (nowDirection == UP) x--;
        return new int[]{x,y};
    }

    private boolean isMovable(int x, int y){
        if (x>=m) return false;
        if (y>=n) return false;
        if (x<0) return false;
        if (y<0) return false;
        if (matrix[x][y]!= INIT_VALUE) return false;
        return true;
    }
}

결과

0   1   2   3   4

15  16  17  18  5

14  23  24  19  6

13  22  21  20  7

12  11  10  9   8

이동하는 좌표를 사이즈가 2인 int배열에다 담았는데, 이걸 따로 클래스로 빼서 만들까 하다가 클래스를 더 늘리기 싫어서 그만뒀습니다. 소스에서 position[0], position[1] 이라고 표시된 부분이 좌표를 나타내는 부분입니다.

main메서드에서 Matrix mp = new Matrix(5,5);` 부분이 5*5 행렬을 만든다는 의미입니다. 사이즈를 바꿀려면 이 부분을 고치시거나, 사용자 입력에서 온 값을 연결시키면 됩니다.