2017년 9월 25일 월요일

Hanoi Tower with discription

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include<iostream>
using namespace std;
#define TOWERSIZE 5
class blocks { //하노이탑의 각 블록의 클래스화 입니다.
private:
    int blockSize; //해당 블록이 몇칸짜리인지 이 변수를 통해 알아냅니다.
public:
    void setBlockSize(int num) 
    {
        blockSize = num;
    }
    int getBlockSize() 
    {
        return blockSize;
    }
};
class lists { //from,tmp,to 탑을 클래스화 시켰습니다.
private:
    int top = -1; //stack을 위해 top변수를 만들었습니다.
    blocks blockslist[TOWERSIZE];//각 탑의 층수 입니다.
public:
    int getTop() 
    {
        return top;
    }
    void pushBlock(blocks in) 
    {
        blockslist[++top] = in;
    }
    blocks popBlock() 
    {
        return blockslist[top--];
    }
    int peekBlock() 
    {
        return (blockslist[top]).getBlockSize();
    }
    int peekSelectBlock(int selectedSize) //특정 위치를 peek하기위한 함수
    {
        return (blockslist[selectedSize]).getBlockSize();
    }
};
void printTower(lists *forPrint) {//탑 출력 함수, 세 탑을 인자값으로 받음
    int i = TOWERSIZE-1; //타워의 꼭대기부터 시작합니다. 
    while (i > -1) //1층까지 반복
    {
        cout << " ";
        if (forPrint[0].getTop() >= i) //탑의 꼭대기가, 현제층보다 같거나 클때 
        {
            int j = 0;
            for (; j < forPrint[0].peekSelectBlock(i); j++) //블럭의 사이즈만큼 *을 찍습니다.
                cout << "*";
            if (j != 5) //5칸을 다 못찍었다면
            {
                while (j != 5)  //남은칸은 whitespace
                {
                    cout << " ";
                    j++;
                }
            }
        }
        else //현제층이, 탑의 꼭대기보다 높으면
        {
            cout << "     ";//해당 층에는 아무 블럭도 없습니다.
        }
        cout << " ";
        if (forPrint[1].getTop() >= i)  // 두번째 탑
        {
            int j = 0;
            for (; j < forPrint[1].peekSelectBlock(i); j++) 
                cout << "*";
            if (j != 5) 
            {
                while (j != 5) 
                {
                    cout << " ";
                    j++;
                }
            }
        }
        else 
        {
            cout << "     ";
        }
        cout << " ";
        if (forPrint[2].getTop() >= i) //세번째 탑
        {
            int j = 0;
            for (; j < forPrint[2].peekSelectBlock(i); j++)
                cout << "*";
            if (j != 5) 
            {
                while (j != 5) 
                {
                    cout << " ";
                    j++;
                }
            }
        }
        else 
        {    
            cout << "     ";    
        }
        cout << endl;
        i -= 1; //다음층의 계산을 시작합니다.
    }
    cout << " ----- ----- -----" << endl; // 바닥.
}
void calcHanoi(int num, lists *from, lists *tmp, lists *to, lists *forprint)
{//하노이 계산 함수
    if (num == 1)
    {
        to->pushBlock(from->popBlock());
        printTower(forprint);
        return;//기존과는 달리, 블럭 클래스들을 stack을 이용해 list클래스에 붙혀줍니다.
    }        //118번줄은 이 작업을 담당합니다. 이동후 타워를 출력합니다.
    calcHanoi(num - 1, from, to, tmp, forprint);
    calcHanoi(1, from, tmp, to, forprint);
    calcHanoi(num - 1, tmp, from, to, forprint);
}
void main() {
    int num = TOWERSIZE;
    blocks block[TOWERSIZE]; //블럭 클래스를 생성합니다.
    lists list[3];            //타워 클래스를 생성합니다.
    for (int i = 0; i < num; i++) {
        block[i].setBlockSize(num - i);//블럭을 순서대로 초기화 합니다.
        list[0].pushBlock(block[i]);//from 탑에 순서대로 생성한 블럭을 쌓습니다.
    }
    //여기까지 초기화 작업
    calcHanoi(num, &list[0], &list[1], &list[2], &*list);
    
   cout<<"DONE"<<endl;
}
/*
    Sep,18 2017 19:21
    Creater        : Changwon J.
    Title        : HanoiTower 
    Version        : Ver 1.0
    Discription    : print HanoiTower as ordered, comment added
*/

간만에 코드짜니깐 겁나 더러운것.
혹시 과제 빼낄친구들이 있을수도 있으니,
9월 25일 이후에 공개할것.

2017년 9월 24일 일요일

MsSQL2012 설치

교수가 설치법을 몰라서 당황..

당연하게도 MS사의 sql은 비쌈. 넘나비싼것.

그래서 평가판이 있다능.

https://www.microsoft.com/ko-kr/download/details.aspx?id=29062


...

걍 받고설치하면 되는데? 왜 그렇게 당황했는지 아무도 몰라..

2017년 9월 19일 화요일

c+ 다수의 소스나 헤더 적용법과 에러

오늘 배운 수업중 하낙가, 다수의 소스와 헤더파일의 구동법이었는데, 일전에 언리얼 코드를 뜯어본 기억이 새록새록 돋아나 흥미롭게 들었습니다.

겪어 본 이후로 더욱 더 실감하지만, 하나의 프로잭트에 여러명이 붙는순, 학생들이 배우는 방식의 코드작업은 지옥을 초래하게 됩니다.

(하나의 소스파일로 두세명이 작업하는것도 무리인데, 회사의 경우는 두세명이 아닐태니깐!)

그러한 이유로 우리는 여러개의 소스 파일과 헤더들을 이용하여 쉽게 지옥을 물리칠 수 있습니다.

우선적으로 우리가 컴파일을 시작하면, 프로잭트의 모든 Source 파일들을 읽기 시작하죠.

그 중 #include 문이 있다면,include가 가리키는 라이브러리, 혹은 헤더파일을 방문하여 읽게 됩니다.

미리 define된 라이브러리 함수들은 꺽쇠인 < > 로 include를 합니다.

하지만 우리가 만드는 사용자정의 Header는, 보통 하나의 프로젝트 내에 있기 때문에, 단순히 #include "Header이름.h" 를 사용하면 됩니다.

이렇게 선언된 글을 컴파일러가 읽게되면, 만든 header로 방문하게 되어, 선언문들을 읽은뒤, 마저 Source들을 읽게 됩니다.

저와 같은 기초반을 들었던 사람들이라면 흔히 봤을 광경입니다.


기초과정이기도 하고, 중점 교과과목은 자바였기 때문에, 깊게 파고들지 않아서 하나의 예제당 하나의 프로젝트를 만드는게 아닌, 이렇게 소스파일만 새로 만들어서, 이전 예제는 컴파일 재외를 했었습니다.

저는 개인적으로 하면서, 왜 제외해야하나몹시 궁금했었고, 고급과정을 하는동안 까마득히 잊고있었습니다.

정답은 프로젝트를 컴파일하면, 내부의 모든 소스파일들을 컴파일러가 읽어버리기 때문이었습니다.

유일하게 하나이어야만 하는 main 함수, 하나의 프로젝트에 여러번 나오게 될 경우 당연히 문제가 발생했기 때문에, 우리는 귀찮게도 이전 예제 소스파일들을 하나하나 컴파일 예외  시켰습니다.

그럼 이제 여러개의 소스파일을 컴파일 하는방법이 감이 오네요! 여태까지 안하게 막고있었으니, 그 작업만 한하면 되는거였네 ㅎㅎ;

그럼 간단한 stack 을 만들어 봅니다.
목표는
1. 클래스로 두개의 스택구조를 만들것,
2. int타입을 100개 stack 가능하며,
3. 메인 소스파일과, 함수 소스파일은 별개로 만들 것 입니다.

클래스 선언은 Header에서 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Stack
{
private : 
    int arr[100];
    int top;
public  :
    Stack() {
        for (int i = 0; i < 100; i++) 
            arr[i] = 0;
        top = -1;
    }
    void push(int value);
    int pop();
};

클래스에서는 push와 pop함수를 내장하고 있습니다. 두개의 동일한 stack구조를 만들것 이기때문에, 하나의 클래스에 모조리 넣었습니다.
하지만, 함수를 선언만 가능하며, 함수의 내용은 Header에서 함수의 내용을 적지는 않습니다.


 

헤더의 사용 이유는 이러합니다.
SourceA.cpp
----------
void FuncA(){
 FuncB();
}
-----------

SourceB.cpp
-----------
void FuncB(){
}
-----------
의 케이스에서, 우리 기대와는 달리 SourceA에 FuncB() 는 인식하지 않습니다.
이를 해결하기 위해서는

SourceA.cpp
----------
void FuncB();
...

void FuncA(){
 FuncB();
}
-----------
요로코럼 Forward declaration을 해야만 합니다.

이 작업이 수많은 소스파일들도 다 해주어야만 하면, 끔찍하고 지루한 반복작업이 되기떄문에, 이를 해결하기 위해 나온것이 헤더인 것 입니다.

선언을 돕는거죠.



2017년 9월 7일 목요일

Callback Function과 Iterator

재귀함수와 이터레이터는 일찍이 알았습니다만, 재귀함수를 자주 이용하지는 않았습니다.

처음으로 재귀함수를 응용했던것이 C 자료구조 수업에서 quick sort를 만들때 였으며,
그때 정말 눈 돌아갈 정도로 복잡했었기 때문에 사용을 꺼려하고 있었습니다.

재귀함수와 이터레이터는 같은 기능을 제공합니다.특정 기능을 반복하는 행위이지요.

하지만 두 기능은 상황에 따라 작업속도의 차이가 생기게 됩니다.
간단한 예를 들어 피보나치 수열 계산일때 :

반복문을 이용했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int itrway(int var)
{
    if(var<3) return 1;
    else
    {
        int cur=1,prev=1,tmp=0;
        for(int i=2;i<var;i++)
        {
            tmp=cur;
            cur+=prev;
            prev=tmp;
        }
        return cur;
    }
}
재귀함수를 이용했습니다.
1
2
3
4
5
6
7
int functionway(int var){
    
    if(var<=2) return 1;
    else return functionway(var-2)+functionway(var-1);
    
}














같은 기능을 수행하지만, 동작시간은 상이합니다.

number input : 45

1 . function call
 result :1134903170
 exec time :19.725

2 . Iterator call
 result: 1134903170
 exec time :4.724

반복문의 경우에는, 단순하게 수열을 순서대로 더했습니다. 아마..44번 계산이 전부이죠.

반면, 재귀함수의 경우에는 하나의 함수에서 2번의 함수 호출을 합니다.인자값이 1과 2가 아닌이상 또 2번 호출을 하게되고요. 불필요하게 같은 수를호출하게 될 것 입니다.

고작 45라는 숫자이기에 커다란 차이는 없지만, 숫자가 커질수록 작업 횟수와 시간은 기하급수적으로 늘어날 것 입니다.

그렇다고 재귀함수가 항상 안좋은 것은 아닙니다.
대표적인 예로, 검색 알고리즘에서는,
이터레이터 방식의 검색인 버블소트는, 굉장히 쉽게 설계가 되지만, 제가 사용했던 퀵 소트를 비교한다면, 엄청난 수준의 시간 차이가 발생했습니다.

예제를 찍어내는건 담에 하고 ㅠ

이러한 이유로, 수월하고 가벼운 프로그램을 짜기 위해서는, 우리는 최대한 경량화 작업, 그러니깐 좋은 알고리즘을 짜는 방식을 만들기 위해 반복문과 재귀함수중 어느것이 상황에 따라 더 유리한지 찾아야 할 것 입니다.


9월 08일

오랫동안 업데이트가 되지 못했습니다.
작업의 마무리를 위해 눈만뜨면 컴퓨터위로 기어올라가는 일상을 보냈기 때문이라고 변명합니다..

마무리는 거의 끝났습니다.
그 무엇보다 모델링의 부재로 인해 결국 계획됬던 많은 기능들이 사라졌습니다.
만족스럽지 못하지만, 현실적으로 봐야죠.

아직까지 모델링 부분은 끝마치지 못했습니다.
남은 일주일간 건물 모델링에 투자가 될 것 입니다.

그나마 만족스러운 결과물을 얻길 바라며..

2017년 8월 7일 월요일

8월 04일

8월 04일

주간보고

주간 있었던 일을 빠르게 보고하겠습니다.
1. 메뉴작업 착수
2. DB관리 착수
3. 매장 템플릿 추가 작업 착수

로 크게 나눌 수 있겠습니다.



1. 메뉴작업 착수

우선은 크게 네가지 매뉴를 준비했습니다.
홈 메뉴
공지사항 메뉴
캐릭터 커스터마이징 메뉴
옷입히기 메뉴

입니다.
작업은 끝이났습니다. 최대한 추가작업의 편의성을 위해 캐릭터 커스터마이징과 옷입히기 메뉴는 함수화를 구현하는데 중점을 두었습니다만, 아직까지 옷입히기 메뉴에서는 소트나 검색의 기능이 없는 상태입니다.

이 작업은 여유가 생기면 추가 할 작업으로 남겨두었습니다.

그 전에 우선 해야할 일이 있습니다.



2. DB관리

가 다음 작업 사항입니다.

기본적으로 캐릭터 DB에는
캐릭터의 종류, 그 캐릭터에 맞는 각 부위별 신체사이즈 가 있으며,
추후 최저, 최고치 신체사이즈가 입력되어 제한을 걸 수 있도록 해야할 것 입니다.

이부분에서 잠깐 멈춘 이유는, 남아있는 3주동안, 여성 캐릭터의 UV를 올바르게 펴지 못하는 문제에 봉착했으며, 사이즈 증감에 따른 올바른 값을 구하는 방법이 아직 정해지지 못했기 때문입니다.

작업의 진행을 위해 저희팀은, 과감히 4개의 캐릭터를 포기하고, 하나의 캐릭터로 우선작업을 결정했습니다.
디자이너가 가장 가슴아파 하고있습니다만, 그 역시 사태의 심각성을 파악하고 있기 때문에, 시간이 나면 반드시 여성 캐릭터를 추가해 줘야한다 하며 이해해 주었습니다.

그래서 현제 캐릭터 커스터마이징 상태는 170 키의 캐릭터 하나만이 존재 할 뿐입니다.

두번째로 옷 관련 DB입니다.
이곳에서는 테이블이 재법 많고, 생각할 거리도 많아집니다.

우선은 테스트를 위해 순서/이름/이미지경로/메쉬경로/타입/디테일정보 정도로 가볍게 만들었으며, 그 값들을 올바르게 나타내는것에는 무리가 없습니다.

여기서 sort 나 search 등을 이용하기 위해서는 테이블의 확장이 필요합니다.

이는 다음주 부터 이야기를 해 나가야 할 사항입니다.

팀장과의 최대한 빠른 타협을 이끌어내야, 메뉴의 완성과 예외처리를 할 수 있을것 입니다.


3. 매장 템플릿 추가

이부분 또한 VR에 없어서는 안될 작업임은 분명합니다.

개인적인 생각은 다르지만, 전체적인 팀원의 의견은 시각적으로 보여줄것이 많아야 흥미를 유도할 수 있는 요소이다고 주장이 유지되고 있기때문에, 탬플릿을 귀하고 매장을 꾸미는 일은 멈출 수 없습니다.

이부분은 디자이너와 팀장의 콜라보만이 이루어 지고 있기때문에, 제가 자세한 정보는 구하기 힘든 부분입니다.

간간히 마야나 맥스의 작업중 문제가 생기면 기술적인 지원을 같이 하고는 있습니다. 결론적으로 제가 보기에 커다란 문제는 없다고 판단되고 있습니다.


4.다음주를 향해서..

이제 주간 보고를 마무리 지으며, 남아있는 3주에 대한 계획을 시작합니다.
발표준비도 있어야 하기 때문에, 실질적으로 주어진 시간은 2주 이하입니다.

현실적으로 불가능한 작업은 접고들어가야 할 것이며,끈임없는 타협의 시간이 될거 같습니다.
아쉬움이 많이 남지만, 아직 끝이 아니기에, 더 높은 완성도를 목표로 레이스를 완주 해야 할 것 입니다.

2017년 8월 2일 수요일

7월 28일

7월 28일
주간보고

지난 한주간 너무나 바쁘고 타이트한 스케쥴로 인해 보고서는 커녕, 잠조차 똑바로 자지 못했었습니다.

아직도 급한 사정은나아지지 않았기 때문에, 현제 프로잭트의 상태와 방향, 문제점들을 간단하게 언급 해 보겠습니다.


남은 기한은 한달입니다.
이제는 기능구현단계를 벗어나야 했습니다.
현실과 절충안을 위해 토의를 오랫동안 했으며, 우선적으로 적용된 기능을 기반으로 완성을 하도록 합니다.

첫번째 작업물은 아마도 :

 옷 입히기의 원시적인 형태
 캐릭터 커스터마이징의 원시적인 형태
 vr환경의 원시적인 형태

이 될것입니다.

이젠 정말 바쁜 한달이 될 것 입니다.