2024. 1. 2. 17:35ㆍ카테고리 없음
최종프로젝트 전 부족한 실력을 채우기 위해 다시 처음부터 복습을 하고자 한다.
1. 조건문과 반복문
If 조건문
if(true 조건이 되었을 때 )
{
중괄호 안의 내용이 실행된다.
}
else if(위의 if 조건 외의 다른 조건이 true가 되었을 때)
{
중괄호 안의 내용이 실행
}
else
{
위의 조건문들을 다 제외하고 나머지 조건일 때 실행
}
Switch 조건문
switch(조건이 되는 변수 / Enum을 사용하면 편리할 것 같다.)
{
case 1:
실행되는 함수
break;
case 2:
실행되는 함수
break;
default:
실행되는 함수
break;
}
case 1,2,3 에 해당하는 숫자들 대신에 변수들을 넣고 싶다면
enum을 사용하여
namespace ConsoleApp6
{
internal class Program
{
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
void SeasonIssue(Season stage)
{
switch (stage)
{
case Season.Spring:
Console.WriteLine("봄"); //봄Scene으로 SceneManager.LoadScene("Spring");
break;
case Season.Summer:
Console.WriteLine("여름");
break;
case Season.Autumn:
Console.WriteLine("가을");
break;
case Season.Winter:
Console.WriteLine("겨울");
break;
}
}
}
}
반복문 For, While, Do-While ,Foreach
for(int i = 0, i < 10, i++)
{
i가 0부터 9까지 반복할 코드를 작성한다.
}
---------------------------------------------------------
int i = 0
while(i < 10)
{
i가 0에서 9까지 반복할 코드를 작성한다.
i++ 반복을 돌면서 i가 10이 되면 반복을 멈추도록 종료지점을 정확하게 해준다.
}
---------------------------------------------------------
int i = 11;
do
{
// 원래는 11이 10보다 크기 때문에 싱행되면 안됩니다.
// 하지만 do while 에서는 무조건 한번은 실행됩니다.
// 11을 한번 출력하고 종료됩니다.
Console.WriteLine(i);
i++;
}
while(i <= 10)
---------------------------------------------------------
static void Main(string[] args)
{
string[] games = new string[3] { "League of Legends", "메이플 스토리", "디아블로" };
foreach (string gameTitle in games)
{
// 0번째 반복시 gameTitle : League of Legends
// 1번째 반복시 gameTitle : 메이플 스토리
// 2번째 반복시 gameTitle : 디아블로
Console.WriteLine(gameTitle);
}
}
실행결과
League of Legends
메이플 스토리
디아블로
2. 배열과 컬렉션
Array
string[] game = new game[3]; //Array의 사용형태
game[0] = "Leage of Legends"
game[1] = "메이플 스토리"
Console.WriteLine(game[0]); // 출력 - Leage of Legends
Console.WriteLine(game[1]); // 출력 - 메이플 스토리
컬렉션
List
List <string> game = new List<string>(); //List의 사용형태
game.Add( "Leage of Legends" ); // 리스트에 데이터 추가
game.Add( "메이플 스토리" );
game.Add( "디아블로" );
game.Remove( "메이플 스토리" ); // 리스트에서 데이터 삭제
foreach(int number in numbers) // 리스트 데이터 출력
{
Console.WriteLine(number);
}
-
- Dictionary
- 딕셔너리(Dictionary)는 키와 값으로 구성된 데이터를 저장
- 딕셔너리는 중복된 키를 가질 수 없으며, 키와 값의 쌍을 이루어 데이터를 저장
using System.Collections.Generic; Dictionary<string, int> scores = new Dictionary<string, int>(); // 빈 딕셔너리 생성 scores.Add("Alice", 100); // 딕셔너리에 데이터 추가 scores.Add("Bob", 80); scores.Add("Charlie", 90); scores.Remove("Bob"); // 딕셔너리에서 데이터 삭제 foreach(KeyValuePair<string, int> pair in scores) // 딕셔너리 데이터 출력 { Console.WriteLine(pair.Key + ": " + pair.Value); }
- Stack
- Stack은 후입선출(LIFO) 구조를 가진 자료 구조
-
Stack<int> stack1 = new Stack<int>(); // int형 Stack 선언 // Stack에 요소 추가 stack1.Push(1); stack1.Push(2); stack1.Push(3); // Stack에서 요소 가져오기 int value = stack1.Pop(); // value = 3 (마지막에 추가된 요소)
- Queue
- Queue는 선입선출(FIFO) 구조를 가진 자료 구조
-
Queue<int> queue1 = new Queue<int>(); // int형 Queue 선언 // Queue에 요소 추가 queue1.Enqueue(1); queue1.Enqueue(2); queue1.Enqueue(3); // Queue에서 요소 가져오기 int value = queue1.Dequeue(); // value = 1 (가장 먼저 추가된 요소)
-
- HashSet
- HashSet은 중복되지 않은 요소들로 이루어진 집합
HashSet<int> set1 = new HashSet<int>(); // int형 HashSet 선언 // HashSet에 요소 추가 set1.Add(1); set1.Add(2); set1.Add(3); // HashSet에서 요소 가져오기 foreach (int element in set1) { Console.WriteLine(element); }
-
3. 메서드와 구조체
Void - 반환값이 없다.
자료형(int, string, float) - 반환값이 있다.
매개변수 - 함수 내에서 사용되는 변수
// 예시 1: 반환 값이 없는 메서드
public void SayHello()
{
Console.WriteLine("안녕하세요!");
}
// 예시 2: 매개변수가 있는 메서드
public void GreetPerson(string name)
{
Console.WriteLine("안녕하세요, " + name + "님!");
}
// 예시 3: 반환 값이 있는 메서드
public int AddNumbers(int a, int b)
{
int sum = a + b;
return sum;
}
메서드 오버로딩(같은 함수명 다른 매개변수 사용)
void PrintMessage(string message)
{
Console.WriteLine("Message: " + message);
}
void PrintMessage(int number)
{
Console.WriteLine("Number: " + number);
}
// 메서드 호출
PrintMessage("Hello, World!"); // 문자열 매개변수를 가진 메서드 호출
PrintMessage(10); // 정수 매개변수를 가진 메서드 호출
구조체란? 여러 개의 데이터를 묶어서 하나의 사용자 정의 형식으로 만들기 위한 방법
함수 내에 자료형을 여러개 사용하고 싶을 때 struct 사용
구조체의 멤버에는 접근할 때 . 연산자를 사용합니다.
4. 클래스와 객체
클래스 기본 구조
class Person 클래스명 선언
{
public string Name; 필드에 클래스에서 사용 될 변수를 선언
public int Age;
public void PrintInfo() 메서드(함수) 생성
{
Console.WriteLine("Name: " + Name);
Console.WriteLine("Age: " + Age);
}
}
메서드를 호출하기 위해서는 해당 메서드가 속해 있는 클래스의 인스턴스를 생성(붕어빵을 만든다.)
Person p = new Person();
p.Name = "John";
p.Age = 30;
p.PrintInfo(); // 출력: Name: John, Age: 30
- 구조체는 값 형식이며, 스택에 할당되고 복사될 때 값이 복사됩니다.
- 클래스는 참조 형식이며, 힙에 할당되고 참조로 전달되므로 성능 측면에서 다소 차이가 있습니다.
class Person
{
public string Name; // 외부에서 자유롭게 접근 가능
private int Age; // 같은 클래스 내부에서만 접근 가능
protected string Address; // 같은 클래스 내부와 상속받은 클래스에서만 접근 가능
}
- 프로퍼티란?
- 프로퍼티는 클래스 멤버로서, 객체의 필드 값을 읽거나 설정하는데 사용되는 접근자(Accessor) 메서드의 조합입니다.
- get 접근자는 프로퍼티의 값을 반환하고, set 접근자는 프로퍼티의 값을 설정합니다.
자동 프로퍼티를 사용한 예시
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person person = new Person();
person.Name = "John"; // 값을 설정
person.Age = 25; // 값을 설정
Console.WriteLine($"Name: {person.Name}, Age: {person.Age}"); // 값을 읽어 출력
5. 상속과 다형성(전혀 이해안됌)
상속의 개념
- 상속은 기존의 클래스(부모 클래스 또는 상위 클래스)를 확장하거나 재사용하여 새로운 클래스(자식 클래스 또는 하위 클래스)를 생성하는 것입니다
// 부모 클래스
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public void Eat()
{
Console.WriteLine("Animal is eating.");
}
public void Sleep()
{
Console.WriteLine("Animal is sleeping.");
}
}
// 자식 클래스
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Dog is bark.");
}
}
public class Cat : Animal
{
public void Sleep()
{
Console.WriteLine("Cat is sleeping.");
}
public void Meow()
{
Console.WriteLine("Cat is meow.");
}
}
// 사용 예시
Dog dog = new Dog();
dog.Name = "Bobby";
dog.Age = 3;
dog.Eat(); // Animal is eating.
dog.Sleep(); // Animal is sleeping.
dog.Bark(); // Dog is barking
Cat cat = new Cat();
cat.Name = "KKami";
cat.Age = 10;
cat.Eat();
cat.Sleep();
cat.Meow();
동물이라는 부모클래스를 강아지와 고양이 자식클래스에 상속을 시켜 새로운 함수를 생성한다.
무브라는 부모클래스에 사람과 몬스터 자식클래스를 상속시켜 움직임을 구현하는데, 추가로 달리기와 점프 함수를 생성할 수 있는 방법이다.
가상(Virtual) 메서드
- 가상 메서드는 기본적으로 부모 클래스에서 정의되고 자식 클래스에서 재정의할 수 있는 메서드입니다
- 가상 메서드는 virtual 키워드를 사용하여 선언되며, 자식 클래스에서 필요에 따라 재정의될 수 있습니다.
- 이를 통해 자식 클래스에서 부모 클래스의 메서드를 변경하거나 확장할 수 있습니다.
public class Unit
{
public virtual void Move()
{
Console.WriteLine("두발로 걷기");
}
public void Attack()
{
Console.WriteLine("Unit 공격");
}
}
public class Marine : Unit
{
}
public class Zergling : Unit
{
public override void Move()
{
Console.WriteLine("네발로 걷기");
}
}
유닛이라는 클래스에 함수는 무브와 어택이 있는데, 이중에서 Move() 함수는 두발로 걷기를 실행하게 되는데, 유닛 클래스를 Zergling 클래스에 상속시켜 virtual로 쓰여진 함수에 override 덮어씌우는 것이다.
// 사용 예시
// #1 참조형태와 실형태가 같을때
Marine marine = new Marine();
marine.Move();
marine.Attack();
Zergling zergling = new Zergling();
zergling.Move();
zergling.Attack();
// #2 참조형태와 실형태가 다를때
List<Unit> list = new List<Unit>();
list.Add(new Marine());
list.Add(new Zergling());
foreach (Unit unit in list)
{
unit.Move();
}
marine.Move() 는 "두발로 걷기"
zergling.Move() 는 "네발로 걷기"
#2 참조형태와 실형태가 다를때...?
Unit 이라는 List를 만들어주고 마린과 저글링을 추가한다.
foreach 반복문을 사용하여 list에서 unit 들을 사용할 것인데, unit.Move() 함수를 실행한다.
고급 문법 및 기능(제너릭 / out ref 키워드)
제너릭
- 제너릭은 클래스나 메서드를 일반화시켜 다양한 자료형에 대응할 수 있는 기능입니다.
- 제너릭을 사용하면 코드의 재사용성을 높일 수 있습니다.
- C#에서는 <T> 형태의 키워드를 이용하여 제너릭을 선언합니다.
- 제너릭 클래스나 메서드에서 사용할 자료형은 선언 시점이 아닌 사용 시점에 결정됩니다.
- 제너릭 클래스나 메서드를 사용할 때는 <T> 대신 구체적인 자료형을 넣어줍니다.
// 제너릭 클래스 선언 예시
class Stack<T>
{
private T[] elements;
private int top;
public Stack()
{
elements = new T[100];
top = 0;
}
public void Push(T item)
{
elements[top++] = item;
}
public T Pop()
{
return elements[--top];
}
}
// 제너릭 클래스 사용 예시
Stack<int> intStack = new Stack<int>();
intStack.Push(1);
intStack.Push(2);
intStack.Push(3);
Console.WriteLine(intStack.Pop()); // 출력 결과: 3
제너릭 싱글톤 사용법
out, ref 키워드
- out, ref 키워드는 메서드에서 매개변수를 전달할 때 사용합니다.
- out 키워드는 메서드에서 반환 값을 매개변수로 전달하는 경우에 사용합니다.
- ref 키워드는 메서드에서 매개변수를 수정하여 원래 값에 영향을 주는 경우에 사용합니다.
- out, ref 키워드를 사용하면 메서드에서 값을 반환하는 것이 아니라, 매개변수를 이용하여 값을 전달할 수 있습니다.
// out 키워드 사용 예시
void Divide(int a, int b, out int quotient, out int remainder)
{
quotient = a / b;
remainder = a % b;
}
int quotient, remainder;
Divide(7, 3, out quotient, out remainder);
Console.WriteLine($"{quotient}, {remainder}"); // 출력 결과: 2, 1
// ref 키워드 사용 예시
void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
int x = 1, y = 2;
Swap(ref x, ref y);
Console.WriteLine($"{x}, {y}"); // 출력 결과: 2, 1
- 값의 변경 가능성: ref 매개변수를 사용하면 메서드 내에서 해당 변수의 값을 직접 변경할 수 있습니다. 이는 예기치 않은 동작을 초래할 수 있으므로 주의가 필요합니다.
- 성능 이슈: ref 매개변수는 값에 대한 복사 없이 메서드 내에서 직접 접근할 수 있기 때문에 성능상 이점이 있습니다. 그러나 너무 많은 매개변수를 **ref**로 전달하면 코드의 가독성이 떨어지고 유지보수가 어려워질 수 있습니다. 적절한 상황에서 **ref**를 사용하는 것이 좋습니다.
- 변수 변경 여부 주의: out 매개변수는 메서드 내에서 반드시 값을 할당해야 합니다. 따라서 out 매개변수를 전달할 때 해당 변수의 이전 값이 유지되지 않으므로 주의해야 합니다.
6. 인터페이스와 열거형(인터페이스 모르겠음)
열거형(Enum)
enum MyEnum
{
Value1,
Value2,
Value3
}
열거형 사용
MyEnum myEnum = MyEnum.Value1;
열거형 형변환
int intValue = (int)MyEnum.Value1; // 열거형 값을 정수로 변환
MyEnum enumValue = (MyEnum)intValue; // 정수를 열거형으로 변환
복습 switch문에서 열거형 사용방법
// 월 열거형
public enum Month
{
January = 1,
February,
March,
April,
May,
June,
July,
August,
September,
October,
November,
December
}
// 처리하는 함수
static void ProcessMonth(int month)
{
if (month >= (int)Month.January && month <= (int)Month.December)
{
Month selectedMonth = (Month)month;
Console.WriteLine("선택한 월은 {0}입니다.", selectedMonth);
// 월에 따른 처리 로직 추가
}
else
{
Console.WriteLine("올바른 월을 입력해주세요.");
}
}
// 실행 예제
static void Main()
{
int userInput = 7; // 사용자 입력 예시
ProcessMonth(userInput);
}
7. 예외처리 및 값형과 참조형(예외처리 이해못함)
- 1) 값형(Value Type)
- 값형은 변수에 값을 직접 저장합니다.
- int, float, double, bool 등의 기본 데이터 타입들이 값형에 해당합니다.
struct MyStruct
{
public int Value; // int 형태의 Value 선언
}
MyStruct struct1 = new MyStruct(); //MyStruct 구조체에 struct1 이라는 객체를 생성
struct1.Value = 10; //struct1 객체에 int 형 Value 값을 10으로 초기화
MyStruct struct2 = struct1; //struct2라는 객체 생성과 동시에 struct1 값을 복사
struct2.Value = 20; //struct2의 객체 값을 20으로 초기화
Console.WriteLine(struct1.Value); // 출력 결과: 10
- 2) 참조형(Reference Type)
- 참조형은 변수가 데이터에 대한 참조(메모리 주소)를 저장합니다.
- 클래스, 배열, 인터페이스 등이 참조형에 해당합니다.
class MyClass
{
public int Value;
}
MyClass obj1 = new MyClass();
obj1.Value = 10;
MyClass obj2 = obj1; // obj2는 obj1과 동일한 객체를 참조
obj2.Value = 20;
Console.WriteLine(obj1.Value); // 출력 결과: 20
8. 델리게이트 람다 및 LINQ
9. 알고리즘
10. 인풋시스템
New Input System
Input Action: 입력 행동을 정의합니다. 예를 들어 "점프", "공격" 등의 행동을 정의하고, 이러한 행동을 트리거하는 키 또는 버튼을 지정할 수 있습니다.
캐릭터 컨트롤러 스크립트 작성(Action<> 개념활용)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TopDownCharacterController : MonoBehaviour
{
public event Action<Vector2> OnMoveEvent; //이동관련 이벤트
public event Action<Vector2> OnLookEvent; //카메라 시야 관련 이벤트
public void CallMoveEvent(Vector2 direction)
{
OnMoveEvent?.Invoke(direction);
}
public void CallLookEvent(Vector2 direction)
{
OnLookEvent?.Invoke(direction);
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerInputController : TopDownCharacterController
{
private Camera _camera;
private void Awake()
{
_camera = Camera.main;
}
public void OnMove(InputValue value)
{
// Debug.Log("OnMove" + value.ToString());
Vector2 moveInput = value.Get<Vector2>().normalized;
CallMoveEvent(moveInput);
}
public void OnLook(InputValue value) //마우스 커서에 따라서 카메라가 따라가도록
{
// Debug.Log("OnLook" + value.ToString());
Vector2 newAim = value.Get<Vector2>();
Vector2 worldPos = _camera.ScreenToWorldPoint(newAim); //월드포인트 스크린을 기준으로 에임을 설정
newAim = (worldPos - (Vector2)transform.position).normalized; //normalized 단위길이를 곱해준다
if (newAim.magnitude >= .9f)
// Vector 값을 실수로 변환
{
CallLookEvent(newAim);
}
}
public void OnFire(InputValue value)
{
Debug.Log("OnFire" + value.ToString());
}
}
using System.Collections.Generic;
using UnityEngine;
public class TopDownMovement : MonoBehaviour
{
private TopDownCharacterController _controller;
private Vector2 _movementDirection = Vector2.zero;
private Rigidbody2D _rigidbody;
private void Awake()
{
_controller = GetComponent<TopDownCharacterController>();
_rigidbody = GetComponent<Rigidbody2D>();
}
private void Start()
{
_controller.OnMoveEvent += Move;
}
private void FixedUpdate()
{
ApplyMovment(_movementDirection);
}
private void Move(Vector2 direction)
{
_movementDirection = direction;
}
private void ApplyMovment(Vector2 direction)
{
direction = direction * 5;
_rigidbody.velocity = direction;
}
}
위의 내용들을 강의를 복습하며 기억나지 않는 부분들을 앞으로 채우고자 한다.
튜터님의 " 실전 프로젝트를 임하는 자세" 영상을 보고나서 느낀점이 내가 강의 내용에 대한 이해를 전혀 못하고 있는 상태라는 것이다. 숙련 주차나 심화 주차 강의를 파기보다는 다시 기초로 돌아가서 공부하는 걸 시작하는 것이 코딩에 더욱 도움이 될 것 같다.