📌문자열 연결 방법
string name = "츄냥";
int age = 10;
/* Case 1. '+' 사용하는 방식 (기존에 사용하던 방식) */
string Case1 = "냐아~ 나는 시니어 냥이 " + name + " 이에오. 나이는 " + age;
// 변수와 섞어 쓰면 띄어쓰기도 체크해야 하고 ", + 기호들도 오류가 진짜 많이 났다.
/* Case 2. String.Format 메서드 */
string Case2 = string.Format("냐아~ 나는 시니어 냥이 {0}이에오. 나이는 {1}", name, age);
/* ★ Case 3 ★. 문자열 보간 << 이게 되게 편리해서 글을 적게 됨 */
string Case3 = $"냐아~ 나는 시니어 냥이 {name}이에오. 나이는 {age}";
// 큰따옴표 앞에 $(달러 기호)를 표시하여 사용할 수 있다.
// 큰따옴표 사이에 중괄호를 사용하여 변수를 넣어 사용하면 된다.
📌else if란 무엇인가?
if (Chu == "Dog") >> if (name == ChuDog) >> if (name == ChuDog)
{ >> { >> {
} >> } >> }
else >> else >> else if (name == "ChuNyan")
{ >> if (name == "ChuNyan"){ } >> {
if (Chu == "Cat") { }else >> else >> }
} >> >> else
// 놀랍게도 특정 상황(ex.한 줄 코드)에서는 중괄호를 생략할 수 있다.
// else if문은 중첩된 if문에서 중괄호를 생략한 거라는 게 나의 정설이다.
if (Chu == "Dog")
return true;
// ★ 이런 식으로 사용할 수 있다는 것만 말고 나는 하지 말 것
// ★ 동서고금 막론하고 논쟁이 심하다는 건 지양하는 게 정답이다.
🎉 한 장 요약
#1 상속 #2 인터페이스
class Person : MyTeam, MemberInfo
{
string name = "ChuNyan";
public string Name { get { return name; } set { name = value; } } // 인터페이스 구현
public void TalkStyle() // 인터페이스 구현
{
}
public override void ToDoList() // 부모의 함수를 재정의(override)
{
Work();
}
public Person() // 생성자
{
position = Position.Manager.ToString();
// 상속으로 준 'position'에 열거형의 자료를 대입한다.
}
}
#1 상속
class MyTeam
{
protected string position;
// 접근 제한자 'protected'는 'private'에서 추가로 자식에게 접근 가능하게 해준다.
public virtual void ToDoList() // 자식이 함수를 재정의할 수 있게 한다.(virtual)
{
sleep();
}
}
#2 인터페이스
interface MemberInfo
{
string Name { get; set; } // getset 프로퍼티도 가능
bool isMeet;(사용 불가) // ★ 변수는 사용할 수 없고
void TalkStyle(); // ★ 함수만 가능하다.
}
#3 열거형
enum Position
{ // 기본값 // 값 변경 // 기본값은 0부터 시작
Manager,// 0 // 0 // 값 변경시 다음 것부터는 +1 추가
Staff, // 1 // = 5
Intern // 2 // 6
}
📌 상속은 단 한 개의 클래스만 가능하다. 하지만 상속의 상속은 가능하다.
📌 인터페이스는 추상적인 정의이며, 상속받은 후 직접 정의해 줘야한다.
📌 인터페이스는 여러개 상속도 가능하다.
📌 열거형(enum)의 사용 의미는 가독성이며 스위치 문과 호환성이 좋다.
🎉 한 장 요약
Git URL : https://github.com/Chu-Nyan/TextRPG/blob/main/TextRPG/Program.cs
// 플레이어 클래스
class Player
{
//인벤토리 초기화
public IItem[] Inven = new IItem[1] { new Nullitem() };
// 아이템 추가
public void AddItem(IItem NewItem)
{
for (int num = 0; num < Inven.Length; num++)
{
if (Inven[num].Name == "없음")
{
Console.WriteLine($"{NewItem.Name}을 획득하였습니다.");
Inven[num] = NewItem;
break;
}
else if (num == Inven.Length - 1)
{
Console.WriteLine("인벤토리가 꽉 찼습니다.");
}
}
}
// 인벤토리 확인 하기
public void OpenInven()
{
Console.Write($"0. 돌아가기 ");
for (int num = 0; num < Inven.Length; num++) // 인벤토리 출력
{
Console.Write($"{num + 1}. {Inven[num].Name}");
}
Console.WriteLine("아이템을 선택해주세요.");
switch (Console.ReadKey(true).Key) // 인벤토리 선택
{
case ConsoleKey.D0:
Console.WriteLine("가방을 닫습니다.");
break;
case ConsoleKey.D1:
if (Inven[0].Name == "없음")
{
Console.WriteLine("가방을 비어있습니다.");
break;
}
Inven[0].Use(this); // 아이템을 사용한다.
Inven[0] = new Nullitem(); // 그리고 삭제
break;
default:
break;
}
}
}
// 인벤토리의 빈 공간
class Nullitem
{
string name = "없음";
}
// 증식하는 클래스들 ㄷㄷ...
class HpWater { string name = "HP"; public void Use(){} }
class MpWater { string name = "MP"; public void Use(){} }
class SpWater { string name = "SP"; public void Use(){} }
✅ 배열을 사용하여 제한된 크기의 인벤토리를 만들었다.
다음에는 크기가 자유로운List<>
로 만들어 보자.
✅ 아이템을 추가하는 건 class Player
의 역할이라 생각 하여 다른 class
에 있던
AddItem
을 옮겨 왔다. 스스로 생각하여 단일 책임 원칙을 지켰다!
💭 내가 만든 구조로는 새로운 아이템을 만들면 class
를 또 만들어야한다.
이렇게 하는 게 맞아 ㄷㄷ?
⛔ 배열에 null
을 사용하지 않고 class Nullitem
를 만들어서 null
을 대체하였다.
IItem?[]
로 해줘도 경고가 사라지지 않았다 😥
🎉 한 장 요약
//StringBuilder 선언 방법 자주쓰는 매개변수 : 원하는 문자 최대 길이
StringBuilder stringBuilder = new StringBuilder("고양이와 강아지", 12);
// 문자열 끝에 값을 추가
stringBuilder.Append("와 고슴도치와 왕고슴도치");
// output : 고양이와 강아지와 고슴도치와 왕고슴도치, Length : 21, Capacity : 24
// 최대 길이를 초과하면 용량이 두 배씩 증가한다.
// 문자열 10번째부터 2개 제거
stringBuilder.Remove(10, 2);
// output : 고양이와 강아지와 도치와 왕고슴도치
// 문자열 10번째부터 "고슴" 추가
stringBuilder.Insert(10, "고슴");
// output : 고양이와 강아지와 고슴도치와 왕고슴도치
// "고슴도치"라는 문자를 "코끼리"로 !모두! 변경한다
stringBuilder.Replace("고슴도치", "코끼리");
// output : 고양이와 강아지와 코끼리와 왕코끼리
📌stringBuilder.Length
= 문자열 길이 stringBuilder.Capacity
= 메모리 크기
📌 String
형식을 사용하면 값형식처럼 사라지는 게 아니라고 계속 메모리에 남는다.
따라서 String
을 생성할수록 성능 이슈가 생길 수도 있다.
이런 현상을 방지할 수 있는 방법이 StringBuilder
이다. (진짜 MS 오피셜)
📌 for
문에서는 성능 상향, switch
문은 문자열 조합해서 사용하기 좋다.
🎉 한 장 요약
1. 이해가 안 가는 함수들은 어떻게 이겨낼까?
delegate
event
Lambda
LINQ
등등 아무리 읽어도 어떤 기능인지 혹은 언제 사용하는지 전혀 모르겠다. 이전 전공 책을 보면서도 이 부분에서 막혔는데 좀 더 강해져서 와도 막혔다.
그나마 delegate
와 Lambda
는 직접 코딩해 보면서 조금씩은 감이 잡혔다.
어려운 문법들이 나오면 반드시 해야 할 건 이해하기 전에 직접 코딩해보는 게 아닐까 생각한다.
2. 하고 또 했던 주제의 코딩은 왜 해야 하는가
TextRPG
는 이번이 두 번째이다 다음 주면 과제로 세 번째로 코딩을 해보게 된다.
RPG를 이루는 큰 틀, 플레이어가 있고 마을과 던전이 있고 몬스터가 있다.
똑같은 주제니깐 똑같이 만들어지는 것은 절대 아니며 두 번째 만들 땐 코드의 짜임새를 달리하는 것이 중요하다.
Class Monster
에 자동으로 값을 대입하는 Slime
이 효율적일까?
상속을 받아 Class Slime
을 만드는 게 효율적일까? 더 좋은 효율을 찾는 것이 아닌 또 다른 방법을 찾아보는 것이 올바르지 않을까?
📌 기억해야 할 이번 주 키워드
// true값을 넣어주면 콘솔창에 글자가 입력되지 않는다.
Console.ReadKey(true);
// 매개 변수 ref, out
// ref과 out은 값을 리턴하는 것이 아닌 매개변수로써 값을 밖으로 전달한다.
// 값형을 매개변수로 전달하면
int valueNum = 5;
static void Plus(int A, int B)
{
A += B;
}
Plus(valueNum, 10)
// output valueNum = 5, int A로 값이 복사되었기에 valueNum은 변하지 않는다.
// ref 한정자를 통하여 전달하게 되면
static void PlusRef(int A, int B, ref int C)
{
C = A + B;
}
PlusRef(valueNum, 10, ref valueNum);
// output valueNum : 15; int C는 참조형으로써 valueNum에게 값을 제대로 전달한다.
// out
void PlusMinus(int A, int B, out int plus, out int minus)
{
plus = A + B;
minus = A - B;
}
// out에서 선언을 할 수있다.
PlusMinus(10, 5, out int newInt1, out int newInt2);
//output : newInt1 = 15, newInt2 = 5
// 기존에 있던 변수들도 사용할 수 있다.
int outputPlus = 1234; // 불필요한 값 할당
int outputMinus = 5678;
PlusMinus(10, 5, out outputPlus, out outputMinus);
//output : outputPlus = 15, outputMinus = 5
// out은 메서드 내에서 기존 값을 무시한다.