이제 회전하는거랑

블럭 한줄 맞으면 사라지고 점수더해지는거만 구현하면댐!!



and then, rotation and

if block ereasing function! 


얼마전에 올린 대문자를 찾아서 필터링 해주는거랑 비슷.

이번엔 소문자를 찾아서 대문자로 바꿔준다.


15열에서 문자열 입력받고

16열에서 그걸 글자로 조각조각 나눠서 배열에 담은다음에

foreach 로 검사하고 바꿔서 ToUpper()를 써서 다시 저장

그리고 출력 순이다.


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
 class Program
    {
        static char ToUpper(char a)
        {
            char newa = a;
            if (a > 96 && a < 123)
            {
                newa = (char)(a - 32);
            }
            return newa;
        }
 
        static void Main(string[] args)
        {
            string userstr = Console.ReadLine();
            char[] userchar = userstr.ToCharArray();
            int count = 0;
            foreach (char c in userchar)
            {
                userchar[count] = ToUpper(c);
                count++;
            }
            foreach (char c in userchar)
            {
                Console.Write(c);
            }
        }
    }
cs




아래는 참고용 아스키 코드.


아스키 코드라는건 사실 정해져 있는게 아니라고 한다.

나라마다 서로 다른 아스키 코드를 쓰는 일도 있고

변수를 char 타입으로 저장하면 컴퓨터가 알아서 타입을 검사해서 컴퓨터에 저장 되어있는 아스키 타입 글자로 바꿔준다.

그 말은 메모리 어딘가엔 변수의 값 뿐만이 아니라 타입도 저장되어있다는 말이다.

메모리가 나오니까 좀 복잡해지는데 @_@ 뭔가 더 재밌어진다.





지금은 새벽 2시...


비독님의 아이디어(?)를 받아 간단한 프로그램 하나 만들었다. 만들다보니 잼나넹 허허..



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
using System;
using System.Collections.Generic;
using System.IO;
 
namespace test
{
    class Program
    {
        public static List<string> Names = new List<string>();
 
        public static void LoadAndCheckFromFile()
        {
            StreamReader loadfile = new StreamReader(@"C:\temp\temp.txt");
            while (loadfile.Peek() >= 0)
            {
                string name = loadfile.ReadLine();
                char[] namespilt = name.ToCharArray();
                string newname = "";
                int count = 0;
 
                foreach (char letter in namespilt)
                {
                    if ((int)letter > 64 && (int)letter < 91)
                    {
                        count++
                    }
                }
                if(count >0)
                {
                    newname = "!" + name;
                }
                else
                {
                    newname = name;
                }
                Names.Add(newname);
            }
            loadfile.Close();
        }
 
        public static void SaveToFile()
        {
            StreamWriter savefile = new StreamWriter(@"C:\temp\temp.txt");
 
            foreach (string s in Names)
            {
                savefile.WriteLine(s);
            }
            savefile.Close();
        }
 
        static void Main(string[] args)
        {
            LoadAndCheckFromFile();
            SaveToFile();
        }
    }
}
 
cs



근데 어떤분이 엑셀에서 할 수 있는 해결법을 주셨는데 

이걸보니 사람은 정말 똑똑해야 하는구나를 느꼈다.... 

멍청하면 손발이 고생함 ㅠㅠ









직원관리시스템 (Employee Management System)


이거 작성하는데 온종일 퍼부으면서도 3일걸림... 

오늘에서야 괜찮아보인다는 말을 듣고 정리해본다 ㅠㅠ(으어어어)


1. 상식적인 클래스

파칭코 게임 이후에 도형 출력 프로그램 만들면서 

OOP에 대해 배우고 클래스에 대한 개념도 확실히 잡혔겠지!! 하곤 자만했다가

막상 코딩 들어가서 해맨게 한두가지가 아니었다


설명하자면, 일단 아직도 클래스를 섞어서 썼었다.

정보를 다루는 클래스는 정보만 다뤄야 하는데, 받은 정보를 출력한다거나하는 하는 역할의 혼동.

그리고 OOP는 일단 "상식"이 필요한 일이라는걸 알게되었다.

예를들어 말하는 연필을 본적이 있나? 상식적으로 말이 안된다.

근데 코딩을 하다 보면 말하는 연필이 만들어질수도 있다(...)이런걸 조심해야한다.

추상화에 심각하게 어긋나는 방법이다.

매니저 클래스는 매니징만 해야한다. 보려주는건 프로그램 클래스가 해야 한다.

언행일치 하는 클래스와 함수를 만들자.


2. 도스창에서 파일을 만들어봄!!!

처음으로 파일 입출력을 사용해보았다. 사용법은 MSDN[각주:1]나 블로그들[각주:2]에 잘 나와있다.

내 코드중에서 EmployeeManager class가 가지고 있는 SaveToFile()과 LoadFromFile()이 그것.

의외로 함수들을 그냥 가져다 써서인지 어렵지 않았다...허허


3. 리스트(List<T>) 좋아요

직원들의 목록 관리를 위해 List<T>라는걸 처음 써봤다.

Array랑은 뭐가 다를까 두근두근해 하며 써봤는데 결론은 동일 ㅋㅋ...

처음에 리스트는 어떻게 파라미터로 넘겨받는지 몰라 조금 헤매다가 어찌어찌 성공.

다만 Array는 값이 여러개 들어있는거고, List는 그게 한 박스에 담겨있는 형태라고나 할까

char[] Array랑 string의 차이랑 똑같다고 스승님이 말했다.

 

(3일동안 받은 코드 리뷰들....)   


4. 근데 정렬은 뭐가 뭔지 모르겠어요

List 개념이나 사용방법은 Array랑 크게 다르지 않아서 어렵지 않았는데 문제는 List<T>.Sort()....정렬....

그냥 정렬해줘!! 라고 하면 그냥 정렬해줄 줄 알았더니, 뭔가 정렬할때 쓸 함수가 또 필요하댄다...

구글링해가면서 해결방법은 찾았는데 아직도 완전히 이해가 되질 않아서... 내일 다시한번 뜯어봐야겠다.


5.그 외의 자잘하게

- 함수 이름은 기능이기 때문에 동사를 쓴다. 그리고 첫글자를 대문자로 쓰자.(ex. Get, Set, Display...)

- 클래스 이름은 객체를 만드는 도안같은 역할이기때문에 명사를 쓰자 (ex. System, Program....)

- Enum은 첫글자는 대문자를 쓴다. 그리고 클래스처럼 명사를 쓴다.

- 새로만들어진 클래스가 기존 main()이 들어있는 클래스(여기선 Program)를 참조하게 되면

  나중에 확장성에 문제가 생긴다. 이거 말고 다른 프로그램에서 새 클래스를 가져다 쓰게되면 어떡할껀가?

- Input 이라던가, number같은 딱봐서 어디에 쓰일지 모르겠는 이름은 제발 짓지 말자.(흑... 상상력이 부조카다..)

- 필요없는 else는 생략하는게 좋다.

- 초반엔 매니저 클래스를 static으로 만들려고 했는데, 

  그러면 만약 둘 이상의 회사를 관리하게 될때 여러명의 매니저가 불가능해지기 때문에 그냥 일반 함수들로 구현했다.

  이 클래스가 여럿 복제될 일이 있는지 아니면 한 개로 계속 쓰일지 클래스를 디자인할때 미리 생각하라

- 위와 같은 이유로 직원들 리스트는 프로그램이 아닌 오직 매니저만 가지고 있다. 프로그램이 필요하면 매니저꺼 가져다 쓴다.

- 다시한번 강조. 클래스와 함수가 할 일을 확실히 구분하라. 이름을 보고 얘가 무슨 용도인지 한눈에 파악되게.



이제 드디어 코드들.


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
150
151
152
153
154
155
using System;
using System.Collections.Generic;
 
namespace managementsystem
{
    class Program
    {
        static void Main(string[] args)
        {
            EmployeeManager manager = new EmployeeManager();
 
            while (true)
            {
                Console.Clear();
                Console.WriteLine("::Employee Management System::");
                Console.WriteLine("[1] Input the New Employee");
                Console.WriteLine("[2] Check All Employees");
                Console.WriteLine("[3] Save");
                Console.WriteLine("[4] Load");
                Console.WriteLine("[5] Exit");
 
                MainMenuOption mainmenunumber = (MainMenuOption)Int32.Parse(Console.ReadLine());
 
                switch (mainmenunumber)
                {
                    case MainMenuOption.Newemployee:
                        {
                            Console.Clear();
                            Console.WriteLine("[1] Input the New Employee---");
                            manager.CreateEmployee(InputForm());
                            break;
                        }
                    case MainMenuOption.Check:
                        {
                            bool editpage = true;
                            while (editpage)
                            {
                                Console.Clear();
                                Console.WriteLine("[2] Check All Employees---");
                                DisplayEmployees(manager.Employees);
                                Console.WriteLine("---------END--------");
                                Console.WriteLine("[1] Edit Employee");
                                Console.WriteLine("[2] Delete Employee");
                                Console.WriteLine("[3] Delete All Employees");
                                Console.WriteLine("[4] Sort(Name) Employees");
                                Console.WriteLine("[5] Find Employee by First Name");
                                Console.WriteLine("[6] Back to the Mainpage");
                                Console.WriteLine("[7] Exit");
 
                                EditMenuOption editmenunumber = (EditMenuOption)Int32.Parse(Console.ReadLine());
 
                                switch (editmenunumber)
                                {
                                    case EditMenuOption.Edit:
                                        {
                                            Console.Write("[Edit] which number? : ");
                                            int editnumber = Int32.Parse(Console.ReadLine());
                                            manager.EditEmployee(editnumber, InputForm());
                                            break;
                                        }
                                    case EditMenuOption.Delete:
                                        {
                                            Console.Write("[Delete] which number? : ");
                                            int deletenumber = Int32.Parse(Console.ReadLine());
                                            manager.DeleteEmployee(deletenumber);
                                            break;
                                        }
                                    case EditMenuOption.DeleteAll:
                                        {
                                            Console.Write("[Delete All] Do you want delete all?");
                                            Console.Write(" y / n : ");
                                            string delete = Console.ReadLine();
                                            if (delete == "y")
                                            {
                                                manager.DeleteAllEmployee();
                                            }
                                            break;
                                        }
                                    case EditMenuOption.Sort:
                                        {
                                            manager.Sort();
                                            break;
                                        }
                                    case EditMenuOption.Find:
                                        {
                                            Console.Write("- Name : ");
                                            List<Employee> findresult = manager.FindByName(Console.ReadLine()); 
                                            DisplayEmployees(findresult);
                                            string pause = Console.ReadLine();
                                            break;
                                        }
                                    default:
                                    case EditMenuOption.BackToMain:
                                        {
                                            editpage = false;
                                            break;
                                        }
                                    case EditMenuOption.Exit:
                                        {
                                            return;
                                        }
                                }
                            }
                            break;
                        }
                    case MainMenuOption.Save:
                        {
                            Console.WriteLine("Input File Name : ");
                            string filename = Console.ReadLine();
                            manager.SaveToFile(filename);
                            Console.WriteLine("---Done!---");
                            System.Threading.Thread.Sleep(300);
                            break;
                        }
                    case MainMenuOption.Load:
                        {
                            Console.WriteLine("Input File Name : ");
                            string filename = Console.ReadLine();
                            manager.LoadFromFile(filename);
                            Console.WriteLine("---Done!---");
                            System.Threading.Thread.Sleep(300);
                            break;
                        }
                    default:
                    case MainMenuOption.Exit:
                        return;
                }
            }
        }
 
        public static Employee InputForm()
        {
            Console.Write("- Name : ");
            string name = Console.ReadLine();
            Console.Write("- Department : ");
            string department = Console.ReadLine();
            Console.Write("- Title : ");
            string title = Console.ReadLine();
 
            return new Employee(name, department, title);
        }
 
        public static void DisplayEmployees(List<Employee> Employees)
        {
            int count = 0;
            foreach (Employee e in Employees)
            {
                Console.Write("<{0}> ", count);
                Console.WriteLine(e.GetEmployeeInformation());
                count++;
            }
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
public enum MainMenuOption
{
    Newemployee = 1,
    Check,
    Save,
    Load,
    Exit
}
c  s


1
2
3
4
5
6
7
8
9
10
public enum EditMenuOption
{
    Edit = 1,
    Delete,
    DeleteAll,
    Sort,
    Find,
    BackToMain,
    Exit
}
cs


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
using System;
namespace managementsystem
{
    class Employee
    {
        public string Department { get; private set; }
        public string Name { get; private set; }
        public string Title { get; private set; }
 
        public Employee(string name, string department, string title)
        {
            Name = name;
            Department = department;
            Title = title;
        }
 
        public string GetEmployeeInformation()
        {
            return "-Name: " + Name + " -Department: " + Department + " -Title: " + Title;
        }
 
        public static int compare(Employee a, Employee b)
        {
            return a.Name.CompareTo(b.Name);
        }
    }
}
 
cs


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
using System;
using System.IO;
using System.Collections.Generic;
 
namespace managementsystem
{
    class EmployeeManager
    {
        public List<Employee> Employees = new List<Employee>();
 
        public void CreateEmployee(Employee newEmployee)
        {
            Employees.Add(newEmployee);
        }
 
        public void EditEmployee(int editnumber, Employee newEmployee)
        {
            Employees[editnumber] = newEmployee;
        }
 
        public void DeleteEmployee(int deletenumber)
        {
            Employees.RemoveAt(deletenumber);
        }
 
        public void DeleteAllEmployee()
        {
            Employees.Clear();
        }
 
        public List<Employee> FindByName(string name)
        {
            int count = 0;
            List<Employee> findresult = new List<Employee>();
            foreach (Employee e in Employees)
            {
                if (e.Name == name)
                {
                    findresult.Add(e);
                }
                count++;
            }
            return findresult;
        }
 
        public void Sort()
        {
            Employees.Sort(Employee.compare);
        }
 
        public void SaveToFile(string filename)
        {
            StreamWriter savefile = new StreamWriter(@"C:\temp\" + filename + ".txt");
            foreach (Employee e in Employees)
            {
                savefile.WriteLine(e.Name);
                savefile.WriteLine(e.Department);
                savefile.WriteLine(e.Title);
            }
            savefile.Close();
        }
        public void LoadFromFile(string filename)
        {
            Employees.Clear();
            StreamReader loadfile = new StreamReader(@"C:\temp\"+ filename + ".txt");
            while (loadfile.Peek() >= 0)
            {
                Employees.Add(new Employee(loadfile.ReadLine(), loadfile.ReadLine(), loadfile.ReadLine()));
                // name line, department line, title line.
            }
            loadfile.Close();
        }
    }
}
 
cs











  1. MSDN File 클래스 : https://msdn.microsoft.com/ko-kr/library/system.io.file(v=vs.110).aspx [본문으로]
  2. 엑시노아의 비공정 파일 입출력 : http://exynoa.tistory.com/154 [본문으로]


0.

이번 코딩은 처음 도형그리기를 만들고 나서, 도형을 상속받는식으로 또 고친 후, 팩토리 패턴으로 다시 만들었다.

그리고 OOP[각주:1]라는걸 몇번 들어보기도 했고, 중요하다는 이야기도 들었지만 그동안 확실하게 개념이 잡혀있던게 아니었던지라

처음 이번 코드를 OOP로 작성하면서 확실하게 개념을 잡아보자 라는 생각으로 진행했다.

참고로 OOP의 기본 원칙은 추상화(Abstraction), 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism)이다.


1.

보통 VS에서 처음 프로젝트랑 파일을 만들면 클래스(Program라는 이름의...)를 하나 자동으로 만들어주는데 난 그동안 이게 뭔지 몰랐다...ㄷㄷ

이번에 다른 클래스들을 만들어보면서 클래스라는게 사실 일종의 도안(청사진)같은거고, 

기본적으로 그 클래스 안의 함수들을 사용하려면 클래스를 기반으로하는 객체를 만들어줘야 사용가능하다는걸 알았다.

static을 쓰는 이유도 몰랐는데, 

static을 클래스 안의 함수앞에 붙여주면 후에 생성해줄 객체들이 그 함수를 가져가서 작동하는게 아니라

클래스가 그 함수를 가지게 되어 객체를 만들지 않아도 클래스를 바로 불러서 직접 사용이 가능하다.

main 클래스가 static인건 위의 이유에서다.


2.

그리고 한 클래스당, 한 개의 파일을 두는게 일반적이다.

이게 어찌보면 캡슐화의 한 종류인듯하다. A클래스에서 B클래스로 접근이 자유로우면 정보은닉이 힘드므로...

(Enum(열거형식) 도 마찬가지)


3.

클래스들은 나중에 객체가 될 정보(변수나 함수)들을 가지고 있다.

클래스가 연필 도안이라면 객체는 연필이다.

연필 도안에는 연필 크기(변수)가 얼만큼일지, 연필 색(변수)은 무엇인지, 연필이 수행해야 할 기능(함수)등이 들어있다.

이게 추상화다. 일반적으로 작동하는 것들을 프로그래밍화 시키는것.


4.

근데 만약에 후에 내가 지우개달린 연필을 만들고 싶어졌다면? 기존에 있는 클래스(도안)을 수정할것인가?

물론 수정해도 되겠지만 그럼 다시는 지우개가 없는 연필을 만들긴 어려울것이다.

이 때 사용하는게 상속. ( class 내클래스 : 부모클래스 이런식으로 쓴다)

지우개연필 클래스에, 연필 클래스(도안)을 상속받으면 내가 따로 정해주지 않아도 

이미 연필클래스의 크기나 기능은 지우개연필 클래스 안에 모두 가져와진다.


5.

근데 또 만약에 다시 연필 색을 빨간색으로 바꾸고 싶어졌다. 기존 클래스를 수정하면 다시는 검은 연필을 만들수가 없다.

그럼 어떻게 할까?

원래 연필 클래스로 돌아가서 "나중에 바꿀수 있게 해줘"라고 표시해준 후,

"바꿀 수 있게 된"연필 클래스를 상속받아 색깔 정보를 "덮어씌워서" 색연필 클래스를 만들면 된다.

여기 쓰이는 키워드가 (바꿀 수 있게)virtual과 (덮어씌우는)override다. 이게 다형성.


6.

내코드에서 다른 도형클래스들이 상속받은 클래스(shape)는 객체 생성을 해도 할수있는게 없다. 

그래서 아예 처음부터 순수가상클래스(absract)로 만들었다. 가상클래스는 객체 생성이 불가능하다. 그리고 후에 override가 가능하다.


7.

근데 아무 기능도 없는데 왜 상속을 받냐고? 

상속을 받으면 부모클래스의 하위 타입(Type)이 되어서 나중에 한꺼번에 관리하기가 편하다.

triangle과 circle은 서로 다른 클래스고 객체가 만들어져도 각각 triangle타입, circle타입이라 관리하기가 복잡한데,

shape을 상속받게되면 triangle 객체도 shape, circle 객체도 shape 타입으로 관리가 가능해진다.


8.

그리고 "팩토리 패턴"은 사실 OOP랑은 좀 거리가 있는 디자인 패턴의 한 종류라고 하는데,

어쨌든, 연필 만들고 싶을 때 마다 매번 사용자가 만들어주는게 아니라, 찍어내는 공장을 만들어서

원할때마다 그 공장을 가동시키기만 하면 연필이 나오는(...) 걸 만드는게 목적이라고 할 수 있겠다. 


이번 코드에서는 static을 쓰지 않고 팩토리를 만들었는데, 굳이 공장이 여러개일 필요가 없다면

객체들(공장들)을 따로 만들지 않고 static으로 코드를 짜도 무방하겠다.(하지만 여러개가 될 수도 있지!!캬캬)


길게도 적었네...

여기까지가 이번 코딩에서 배운점이고.(빼먹은게 있을 수 있음 ㅠㅠ)

몇몇 참고로 생각나는 부분은 각주로.


아래는 이제 코드들.


코드를 간략히 설명하면, 

1. 5개의 입력을 차례로 받은 후,

2. 도형을 그려주는 팩토리에게 넘긴 후

3. 다섯번 팩토리가 도형을 골라서 만들어 저장한 후

4. 그려주자.



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

using System;
 
namespace drawshapefactory
{
    class Program
    {
 
        static void PrintInstruction(ShapeType shape)
        {
            Console.WriteLine(shape.ToString() + ": " + (int)shape);
        }
        static void Main(string[] args)
        {
            PrintInstruction(ShapeType.Triangle);
            PrintInstruction(ShapeType.Circle);
            PrintInstruction(ShapeType.Rectangle);
            PrintInstruction(ShapeType.Square);
 
            Shape[] inputShape = new Shape[5];
 
            int length = inputShape.Length;
            ShapeFactory shapefactory = new ShapeFactory();    //
 
            for (int i=0; i < length; i++)
            {
                Console.Write("Please input number :");
                int inputnumber = Int32.Parse(Console.ReadLine());
                inputShape[i] = shapefactory.CreateShape((ShapeType)inputnumber);
            }
 
            foreach (Shape i in inputShape)
            {
                i.Draw();
            }
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
 
namespace drawshapefactory
{
    public enum ShapeType [각주:2]
    {
        Triangle,
        Circle,
        Rectangle,
        Square
    };
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
namespace drawshapefactory
{
    public abstract class Shape
    {
        protected int Size { get; private set; }[각주:3]
 
        public Shape(int size)
        {
            Size = size;
        }
        public virtual void Draw()
        {}
    }
}
 
cs


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
 
using System;
 
namespace drawshapefactory
{
    class Triangle : Shape
    {
        public Triangle(int size) : base(size)
        {}
 
        public override void Draw()
        {
            for (int i = 1; i < Size; i++)
            {
                for (int k = Size/2; k > i / 2; k--)
                {
                    Console.Write(" ");
                }
                for (int j = i; j > 0; j--)
                {
                    Console.Write("#");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }
    }
}
 
cs
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
 
using System;
 
namespace drawshapefactory
{
    class Rectangle : Shape
    {
        protected int Height { get; private set; }
 
        public Rectangle(int size, int height) : base(size)
        {
            Height = height;
        }
        
        public override void Draw()
        {
            base.Draw();
 
            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    Console.Write("#");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }
    }
}
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
namespace drawshapefactory
{
    class Square : Rectangle
    {
        public Square(int size) : base(size)
        {}
 
        public override void Draw()
        {
            base.Draw();
        }
    }
}
 
cs
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
 
using System;
 
namespace drawshapefactory
{
    class Circle : Shape
    {
        public Circle(int size) : base(size)
        {}
 
        public override void Draw()
        {
            base.Draw();
 
            int radial = Size / 2;      
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    if (radial * radial > (i - radial) * (i - radial) + (j - radial) * (j - radial))
                    {
                        Console.Write("#");
                    }
                    else
                    {
                        Console.Write(" ");
                    }
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }
    }
}
 
cs
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
namespace drawshapefactory
{
    public class ShapeFactory
    {
        public Shape CreateShape(ShapeType s)
        {
            const int size = 16;                 //basic size.
            const int rectangleheight = 10;      //
 
            switch (s)
            {
                case ShapeType.Triangle:
                    return new Triangle(size);
 
                case ShapeType.Circle:
                    return new Circle(size);
 
                case ShapeType.Rectangle:
                    return new Rectangle(size, rectangleheight);
 
                case ShapeType.Square:
                    return new Square(size);
 
                default:
                    return null;
            }
        }
    }
}
cs

아 이제 직원 관리 시스템 코딩 한것도 분석하러가야됨 ㅠㅠ 헉헉 바쁘다 바빠.

근데 왜 티스토리 에디터에는 consola 폰트가 없지?



  1. OOP 한글위키 : https://goo.gl/pYKp6i [본문으로]
  2. Enum : https://msdn.microsoft.com/ko-kr/library/sbbt4032(v=vs.120).aspx [본문으로]
  3. 프로퍼티 : http://mrw0119.tistory.com/15 [본문으로]
c#


이번엔 코드보다 일단 설명


뭔가(문자열로) 입력을 받고 그걸 뒤집는걸 구현해보자는게 이번 취지.

밴쿠버 불꽃놀이를 5시에 가서(....) 10시까지 기다리기 지루해서 

아이패드 앱으로 코딩했다가 집에와서 다시 코딩.


7번 줄에 보면,

나는 ReverseStr()클래스가 char[]행렬을 받는다.

나는 string형을 받아서 함수 내에서 string을 char[]행렬로 바꾸는게 더 깔끔하다고 생각했는데

포프님 생각은 완전 반대. 왜 굳이 함수에서 바꿔서 메모리를 더 잡아먹게 하느냐는것.

(별 차이 없는거 같은데 엉엉 ㅠㅠ)

그래서  Main() 함수에서 받자마자 바로 변환시킨후에 함수로 넘겨줬다.


사실 이게 버전 2.5쯤 되는데, 처음 1.0버전은 입력받은걸 거꾸로 출력만(...)하는게 목적이었는데

출력보단 아예 스트링을 뒤집는게 더 좋을꺼라고(반협박) 하셔서 고쳤다.

2.0버전은 ReverseStr()클래스가 string형을 받는것, 그리고 아래 코드가 최종본이다.


20번 줄에서 입력받은 string 

21번 줄에서 char[]행렬로 바꿔주고

22번 줄에서 ReverseStr()함수호출

그리고 24번부터 출력 순이다.


-----------------------

 

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
using System;
 
namespace ReverseString
{
    class Program
    {
        static void ReverseStr(char[] str)      
{
            int length = str.Length;
            for (int i = 0; i < length/2;  i++)
            {
                char temp = str[i];
                str[i] = str[length - i - 1];
                str[length - i - 1= temp;
            }
        }
 
        static void Main(string[] args)
        {
            string input = Console.ReadLine();
            char[] str = input.ToCharArray();
            ReverseStr(str);
 
            foreach(char s in str)
            {
                Console.Write(s);
            }
            Console.WriteLine();
        }
    }
}
 
cs

-------------------------








c#




 최종코드---

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace pachinkogame
{
    class pachinko
    {
 
        /////////////////////////////
 
        static int money = 100;    //first money
        static int score = 0;
        static char a, b, c;
 
        static Random r = new Random();
        ///////////////////////////////
 
        static char createcharacter()
        {
            System.Threading.Thread.Sleep(50);    
            int random = r.Next(06);
 
            char character;
            switch (random)              //  0 ~ 4 (A, #, V, $, %)
            {
                case 0:
                    character = 'A';
                    break;
                case 1:
                    character = '#';
                    break;
                case 2:
                    character = 'V';
                    break;
                case 3:
                    character = '$';
                    break;
                default:
                    character = '%';
                    break;
            }
            return character;
        }
 
        static void printresult()
        {
            Console.SetCursorPosition(106);
            Console.WriteLine("STOP!");
 
            if (a == b && b == c)
            {
                score = 30;
                Console.SetCursorPosition(108);
                Console.WriteLine("WIN! +30");
            }
            else
            {
                score = -5;
                Console.SetCursorPosition(108);
                Console.WriteLine("LOSE -5");
            }
 
            money = money + score;
 
            System.Threading.Thread.Sleep(1000);
        }
 
        static void play()
        {
            while (money > 0)
            {
                if (Console.KeyAvailable == true)
                {
                    printresult();
 
                    Console.ReadKey(true);      //erase key insert
                }
 
                else if (Console.KeyAvailable == false)
                {
                    while (Console.KeyAvailable == false)
                    {
                        Console.SetCursorPosition(106);
                        Console.WriteLine("---------    NOW MONEY : {0}  ", money);
                        Console.SetCursorPosition(108);
                        Console.WriteLine("---------");
 
                        Console.SetCursorPosition(107);
                        Console.Write("- ");
 
                        a = createcharacter();
                        b = createcharacter();
                        c = createcharacter();
 
                        Console.Write("{0} {1} {2}", a, b, c);
                        Console.WriteLine("-");
                    }
                }
            }
        }
 
        static void Main(string[] args)
        {
            play();                 // if money is 0, game is end.
 
            Console.SetCursorPosition(1010);
            Console.WriteLine("Thank you for playing!");
 
            System.Threading.Thread.Sleep(1500);
 
        }
    }
}
 
 
cs



-------------------------------------


1. 하노이의 탑을 만들라고 했었는데, 결국 뭘 만들라는건지 질문 자체를 이해못해서 파칭코 게임으로 만들게 됐다.


2. 이번엔 사람의 도움이 아니라, 필요한 코드들은 직접 짜고

막히는 부분은 인터넷에서 찾고 찾아서 얼기설기 코드를 만들었더니

왜 여기서 이렇게 하면 버그가 나는걸까 싶은 부분도 아직 그대로 있다ㅜㅜ 

해결은 해서(자리를 바꾼다거나 해서) 버그는 없이 돌아가지만 그냥 왜 거기서 버그가 났었는지 아직도 모름.....


3. 파칭코가 빙글빙글 돌아가는걸 보여주고 싶었음.

 while문 하나를 키 입력 받기 전까지 무한으로 돌게 하려고 

( while (Console.KeyAvailable == false) ) 이런것도 써봄 ㅋㅋ 

근데 한번 입력하니까 계속 입력된걸로 인식해서 진행이 안됨 ㅠㅠㅋ 찾다보니 

(Console.ReadKey(true);) 요렇게 해주면 왠지 입력이 리셋될것 같아서 해보니 진짜 리셋됨!! 올레!

(그럼 false 하면 어떻게 될까......?!)


4. if문 안의 무한 루프를 돌던 while에서, 입력을 받은 후 빠져나와, 다음 else if로 갈 줄 알았던 분기문이, 

if가 끝났다고 if else로 안가고 바로 다음 구문으로 넘어가 버려서 멘붕. 

(사실 방금까지 왜 그런건지 모르고 있었는데 블로그에 정리하면서 깨달았다.... 

if를 두개쓰면 되는 문제였는데..... 이걸 왜 몰랐었니 ㅇ<-< 으아)


5. 랜덤함수는 아무래도 시간의 영향을 받는거 같은데, 한 랜덤함수에서 한번에 3개의 글자를 "짠!" 하고 구해버리면

항상 같은 글자가 나온다는 문제점이 있어서(...) 글자 사이에 시간차를 준 후 랜덤 함수를 두개 구해서 곱해버림.

(글쓰다보니 두개 구할 필요가 없네? 내일 코드 고쳐야지.)

(글쓰다보니 나머지를 따로 구할 필요도 없잖아? 나 뭐니)


6. 4번의 이유 때문에 코드 사이에 약간의 텀을 주는 함수가 없을까 찾다가 

유용한 녀석(System.Threading.Thread.Sleep(MiliSec.)) 발견.


7. 한번 그려진 그래픽(이라기엔 좀 민망하지만ㅋ) 위에 새로운 그래픽을 그리기 위해

커서 위치를 조정하는 함수도 써봄(Console.SetCursorPosition(x,y);). 우오오

잼남 신남! 뭔가 실시간?으로 돌아가는 게임을 만든 느낌!!ㅋㅋ


8. 점수랑, 점수에 계산해줄 그 턴의 점수는 아예 전역변수로 선언해버림.

원랜 play 함수 안에 넣었는데, play 함수가 재귀로 한바퀴 돌때마다 리셋 되어버리길래

(리셋은 내가 할꺼야!! 누구맘대로!!) 걍 맨 첨으로 꺼내버렸다.... 이래도 되는걸까?ㄷㄷ


9. 정말 한글로 된 블로그들보단 영문 블로그가 훠어얼씬 방대하고 자료가 많다.

위의 함수들은 그나마 대중적이지만, 조금만 생소한 함수들로만 들어가도 (특히)네이버에선 전혀 찾을수가 없다.

그러니까 구글링합시다 여러분.


10. I wanna make different function 이라고 적어놓은 부분은

원래대로라면 따로 함수로 때고 싶었는데, 저 a, b, c 요녀석들이 문제여서 따로 떼질 못했다.

밤이 늦어서 머리가 제대로 안돌아간건지... 내일 다시 보고 따로 떼야지.

그래야 부가적인 다른 기능들도 넣을 수 있을듯.



흐으.. 벌써 자정이 넘었다 ㅠ


나중에 좀 더 물어보고 아쉬운 부분 몇 군데 더 고칠생각.

잘자용.


-----다음날 추가수정----


1. 랜덤 수를 매번 구해 줄 필요가 없어서, 전역변수로 뺌.


2. a, b, c도 비교하기위해 밖으로 뺌. 

근데 생각해보니 비교할때 char형을 int형으로 비교했는데도 비교가 되더라 ㄷㄷ지적받고 놀람.


3. 이전 코드에서 print()던 함수를 createcharacter()로 (지적받고)바꿨다.

일단 이름만으로 뭘 하는지 알아야 하는데, 그게 불가능했고, 이 함수가 하는 일과 정확히 매치되지도 않았고

그래서 함수 안에 프린트 하는 부분을 아예 함수밖으로 빼고, 캐릭터 생성하는 함수로 정리함.


4. 재귀로 돌던 함수는 몇만번을 돌게되면 뻑(크래쉬)이 날 수 있다는 이야길 듣고

while문으로 바꿨다. 동시에 돈이 0원이 되면 함수에서 나와서 게임이 종료되도록 바꿨다.


5. 그 외에 자잘하게, 이기면 WIN, 지면 LOSE 라고 출력하는걸 만들었다.



c#

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace quicksort

{

    class Program

    {

        static void swap(int[] numbers, int a, int b)

        {

            int temp = numbers[a];

            numbers[a] = numbers[b];

            numbers[b] = temp;

        }


        static void sort(int[] numbers, int left, int right)

        {

            if(right <= left)       //exit condition

            {

                return;

            }

            

            int pivot = right;      //rightest bececome a new pivot


            int i = left;

            int j = right-1;


            while(i<j)              //compare with i and j (left and right)

            {

                if(numbers[i]<=numbers[pivot])

                {

                    i++;

                }

                else if(numbers[j] >= numbers[pivot])

                {

                    j--;

                }

                else

                {

                    swap(numbers, i, j);

                    i++;

                }

            }

            int newpivot = j;       //j become a new pivot

            swap(numbers, pivot, newpivot);     //switch a old pivot value and a new pivot



            /////////////////// recursive function

            sort(numbers, newpivot + 1, right);

            sort(numbers, left, newpivot - 1);

            //////////////////

            

        }


        static void Main(string[] args)

        {

            int[] numberArray = { 1, 6, 352, 56, 3, 43, 57, 47, 5, 2, 63, 0, 96 };      //random input

            int length = numberArray.Length;

            sort(numberArray, 0, length - 1);



            ////////////////////print

            Console.WriteLine("Sort result::");

            for(int i = 0; i < length; i++)

            {

                Console.Write("{0} ", numberArray[i]);

            }

            ////////////////////

        }

    }

}





-----------------------------------------
완성하는데 한달 가까이 걸림....
한번 다 완성하고, 집에와서 첨부터 다시 짜보니 30분도 안걸림.....헉

구글에 퀵소트 검색해서 나온 위키페이지만 믿고(예제가 잘못되어 있다...틀린건 아닌데ㅜ)고생하다가
결국은 거의 도움으로 짠듯 ㅠㅠ

여기서 배운건
1. 나는 내가 하고 있는 일을 설명할 줄 모른다(논리력이 부조카다) *중요
2. 퀵소트는 재귀함수다. 재귀함수로만 할 수 있는 일도 있다.
3. 재귀함수를 나가는 조건은(exit condition) 함수의 제일 처음에 있는게 (무조건)좋다.
4. 두 위치을 비교하면서 진행할땐, 한번에 한쪽 위치만 바꿔주는게 좋다. 안그러면 두 위치가 뒤집힐 수 있다.
5. 조금이라도 고쳤으면 디버깅을 하자.
6. 버그가 10개건 100개건 일단 당장 고치려고 하는 버그 하나에만 집중하자. 안그러면 절대 못고친다.
7. 심플하게 만들 수 있는걸 굳이 복잡하게 만들지 말자. 함수 하나만 거치면 될껄 두개 세개를 거치게 하면 더 복잡해진다.
8. 함수를 만들었으면 그 함수를 믿어라. 내가 만든 함수는 내가 넣은 값을 받아서 결과값을 도출해준다. 
일단 만들어진거라면 내부에서 어떻게 값을 도출해 내는지는 중요하지 않다.
9. sort 함수는 "숫자가 들어있는 행렬과 (왼쪽 오른쪽)위치값을 받아서 그 위치사이의 행렬이 가진 값을 정렬"해준다. 


+ Recent posts