팀스파르타 코딩

📚 TIL - 2025년 4월 14일 (월) / C# 입문 일지 (배열, 컬렉션, 메서드, 구조체)

creator2041 2025. 4. 14. 17:52

📌 1. 배열 (Array)

✔️ 배열은 같은 자료형의 값들을 순서대로 저장하는 구조야. 메모리 상에 연속적으로 배치돼서 인덱스를 통해 바로바로 접근할 수 있어. 정해진 수의 데이터를 다룰 때는 배열이 아주 편해.

✅ 1차원 배열 선언 및 초기화

👉 1차원 배열은 말 그대로 한 줄로 데이터를 쭉 저장하는 거야. 예를 들면 학생 점수 5개를 저장할 때, 각각의 변수 대신 배열 하나로 처리할 수 있어서 효율적이야.

// 배열 선언
데이터_유형[] 배열_이름;

// 배열 초기화
배열_이름 = new 데이터_유형[크기];

// 배열을 한 줄로 선언 및 초기화
데이터_유형[] 배열_이름 = new 데이터_유형[크기];

// 배열 요소에 접근
배열_이름[인덱스] = 값;
값 = 배열_이름[인덱스];
int[] array1 = new int[5];
string[] array2 = new string[3];
int num = 0;

array1[0] = 1;
array1[1] = 2;
array1[2] = 3;
array1[3] = 4;
array1[4] = 5;

num = array1[0];

✅ 반복문으로 총합 구하기

👉 배열 안에 있는 값들을 전부 더해서 총합을 구할 수 있어. 반복문이랑 궁합이 잘 맞아서 루프로 쭉 돌리면 돼.

int[] itemPrices = { 100, 200, 300, 400, 500 };
int totalPrice = 0;

for (int i = 0; i < itemPrices.Length; i++)
{
    totalPrice += itemPrices[i];
}

Console.WriteLine("총 아이템 가격: " + totalPrice + " gold");

✅ 게임 캐릭터 능력치를 배열로 관리해보기

👉 캐릭터의 공격력, 방어력 같은 능력치를 배열 하나에 넣으면 훨씬 깔끔하게 관리할 수 있어. 랜덤으로 스탯을 부여하면 재미있는 연습도 돼.

int[] playerStats = new int[4]; 
Random rand = new Random();
for (int i = 0; i < playerStats.Length; i++)
{
    playerStats[i] = rand.Next(1, 11);
}

Console.WriteLine("플레이어의 공격력: "  + playerStats[0]);
Console.WriteLine("플레이어의 방어력: "  + playerStats[1]);
Console.WriteLine("플레이어의 체력: "    + playerStats[2]);
Console.WriteLine("플레이어의 스피드: "  + playerStats[3]);

✅ 학생 성적 평균 계산하기

👉 사용자한테 입력받은 점수들을 배열에 저장하고 평균을 내는 코드야. 반복문과 배열을 함께 쓰는 게 자연스러워진다.

int[] scores = new int[5];

for (int i = 0; i < scores.Length; i++)
{
    Console.Write("학생 " + (i + 1) + "의 성적을 입력하세요: ");
    scores[i] = int.Parse(Console.ReadLine());
}

int sum = 0;
for (int i = 0; i < scores.Length; i++)
{
    sum += scores[i];
}

double average = (double)sum / scores.Length; //위에서 둘다 int로 선언했기에
//sum에대해 형변환 진행함.
Console.WriteLine("성적 평균은 " + average + "입니다.");

✅ 배열을 활용한 숫자 맞추기 게임

👉 이건 진짜 재밌는 응용이야. 정답 숫자 3개를 배열에 담아두고, 사용자가 입력한 숫자들과 비교해서 몇 개 맞췄는지 알려주는 게임이야.

Random random = new Random();
int[] numbers = new int[3];

for (int i = 0; i < numbers.Length; i++)
{
    numbers[i] = random.Next(1, 10);
}

int attempt = 0;
while (true)
{
    Console.Write("3개의 숫자를 입력하세요 (1~9): ");
    int[] guesses = new int[3];

    for (int i = 0; i < guesses.Length; i++)
    {
        guesses[i] = int.Parse(Console.ReadLine());
    }

    int correct = 0;
    for (int i = 0; i < numbers.Length; i++)
    {
        for (int j = 0; j < guesses.Length; j++)
        {
            if (numbers[i] == guesses[j])
            {
                correct++;
                break;
            }
        }
    }

    attempt++;
    Console.WriteLine("시도 #" + attempt + ": " + correct + "개의 숫자를 맞추셨습니다.");

    if (correct == 3)
    {
        Console.WriteLine("축하합니다! 모든 숫자를 맞추셨습니다.");
        break;
    }
}

✅ 다차원 배열도 직접 만들어보기기

👉 2차원 배열은 행과 열로 이루어진 표 같은 느낌이고, 3차원 배열은 면까지 있어서 좀 더 복잡한 구조를 표현할 수 있어. 게임 맵이나 좌표계 표현에 좋아.

int[,] array3 = new int[2, 3];
array3[0, 0] = 1;
array3[0, 1] = 2;
array3[0, 2] = 3;
array3[1, 0] = 4;
array3[1, 1] = 5;
array3[1, 2] = 6;

int[,] array2D = new int[3, 4] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
int[,,] array3D = new int[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 } }
};
int[,] map = new int[5, 5];
for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        map[i, j] = i + j;
    }
}

for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        Console.Write(map[i, j] + " ");
    }
    Console.WriteLine();
}

✅ 게임 맵을 그려보자

👉 2차원 배열을 타일맵처럼 사용해서 벽은 ■, 길은 □ 로 표현해봤어. 단순하지만 시각적으로 배열을 이해하는 데에 도움이 많이 됐어.

int[,] map = new int[5, 5] 
{ 
    { 1, 1, 1, 1, 1 }, 
    { 1, 0, 0, 0, 1 }, 
    { 1, 0, 1, 0, 1 }, 
    { 1, 0, 0, 0, 1 }, 
    { 1, 1, 1, 1, 1 } 
};

for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        if (map[i, j] == 1)
        {
            Console.Write("■ ");
        }
        else
        {
            Console.Write("□ ");
        }
    }
    Console.WriteLine();
}

✅ 게임 맵을 그려보자(이건 랜덤!!)

👉 2차원 배열을 타일맵처럼 사용해서 벽은 ■, 길은 □ 로 표현해봤어. 단순하지만 시각적으로 배열을 이해하는 데에 도움이 많이 됐어.

            Random random2 = new Random();
            int[ , ] map = new int[5, 5]; // 2차원 배열 선언
            for (int i = 0; i < map.GetLength(0); i++) // 0: 행, 1: 열
            {
                for (int j = 0; j < map.GetLength(1); j++)
                {
                    map[i, j] = random2.Next(0, 2); // 0 또는 1로 초기화
                }
            }

            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    if (map[i, j] == 0)
                    {
                        Console.Write("■");
                    }
                    else if (map[i, j] == 1)
                    {
                        Console.Write("□");
                    }

                }
                Console.WriteLine();// j가 끝나면 줄바꿈
                                    //즉, i가 0일때 j는 0~4까지, i가 1일때 j는 0~4까지, i가 2일때 j는 0~4까지
            }

📌 2. 컬렉션 (Collection)

✔️ 컬렉션(Collection)은 자료를 모아 놓은 데이터 구조를 말해. 배열과 비슷하게 생겼지만, 크기가 가변적이라 훨씬 유연하게 데이터를 다룰 수 있어. 특히 C#에서는 다양한 컬렉션 타입이 있고, 대부분은 System.Collections.Generic 네임스페이스를 사용해.


✅ List

👉 List는 말 그대로 '리스트형 배열'이야. 데이터를 추가하거나 삭제하는 게 자유로워서 실무에서 정말 많이 써. 강의에서는 List가 연속적인 구조라고 했고, LinkedList는 포인터로 연결된 비연속 구조라고 정리해주셨지.

List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
numbers.Remove(2);

foreach(int number in numbers)
{
    Console.WriteLine(number);
}

💬 출력 결과:

1
3

✅ Dictionary

👉 Dictionary는 키와 값을 한 쌍으로 묶어서 저장해. 마치 '학생 이름 - 점수'처럼, 특정 키를 통해 값을 바로 찾을 수 있는 자료 구조야. 중복된 키는 허용되지 않아.

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);
}

💬 출력 결과:

Alice: 100
Charlie: 90

✅ Stack

👉 Stack은 LIFO(Last-In First-Out), 즉 나중에 들어간 게 먼저 나오는 구조야. 게임에서 행동 기록 저장할 때나, 뒤로가기 기능 구현할 때 유용해.

Stack<int> stack1 = new Stack<int>();
stack1.Push(1);
stack1.Push(2);
stack1.Push(3);

int value = stack1.Pop();
Console.WriteLine("꺼낸 값: " + value);

💬 출력 결과:

꺼낸 값: 3

✅ Queue

👉 Queue는 FIFO(First-In First-Out), 즉 먼저 들어간 게 먼저 나오는 구조야. 대기열이나 순서 처리에 좋아.

Queue<int> queue1 = new Queue<int>();
queue1.Enqueue(1);
queue1.Enqueue(2);
queue1.Enqueue(3);

int value = queue1.Dequeue();
Console.WriteLine("꺼낸 값: " + value);

💬 출력 결과:

꺼낸 값: 1

✅ HashSet

👉 HashSet은 중복을 허용하지 않는 집합이야. 유니크한 값들만 저장하고 싶을 때 딱이야.

HashSet<int> set1 = new HashSet<int>();
set1.Add(1);
set1.Add(2);
set1.Add(3);
set1.Add(2); // 중복은 무시됨

foreach (int element in set1)
{
    Console.WriteLine(element);
}

💬 출력 결과 (순서는 랜덤):

1
2
3

📌 3. 배열과 리스트

✔️ 배열과 리스트는 비슷해 보이지만 각각 장단점이 있어. 리스트는 유연해서 좋지만, 무분별하게 쓰면 오히려 성능에 영향을 줄 수 있어.

  1. 메모리 사용량 증가
    • 리스트는 동적으로 크기를 조정하다 보니까, 배열보다 메모리를 더 많이 쓸 수 있어.
  2. 데이터 접근 시간
    • 리스트는 내부적으로 배열을 쓰긴 해도, 연결리스트 기반 구현도 존재해서 상황에 따라 접근 속도가 느릴 수 있어.
  3. 코드 복잡도
    • 리스트는 편리하지만, 추가·삭제 기능을 남발하면 코드가 복잡해질 수도 있어.

그래서 '무조건 리스트!'보다는 상황에 따라 배열과 리스트를 잘 선택해서 사용하는 게 중요하다고 느꼈어.

 

 

📌 4. 메서드와 구조체 1

01. 메서드

  • 메서드는 반복되는 작업을 하나의 이름 아래 정의하여 여러 번 사용할 수 있게 해주는 기능이다. 예를 들어 양치질처럼 여러 동작(칫솔 들기, 치약 짜기, 양치하기, 헹구기)을 하나의 이름 '양치하기'로 묶는 것처럼, 메서드를 통해 코드를 추상화하고 재사용할 수 있다.
  • Console.WriteLine()도 우리가 자주 사용했던 대표적인 메서드다.
  • 메서드를 사용하면 코드의 재사용성, 모듈화, 가독성, 유지보수성이 향상된다.

📌 5. 메서드 선언과 호출

  • 메서드는 다음과 같은 형식으로 작성된다:
[접근 제한자] [리턴 타입] [메서드 이름]([매개변수])//매개변수는 없으면 안적어도 됨.
{
    // 메서드 실행 코드
}
  • 예시 코드:
// 예시 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;
}
  • 메서드 호출 방법:
AddNumbers(10, 20);
  • 호출 시 매개변수는 선언된 순서와 타입이 일치해야 하며, 메서드는 호출되면 내부 코드가 실행되고 결과가 반환된다.
  • 메서드는 다음과 같은 형식으로 작성된다:
[접근 제한자] [리턴 타입] [메서드 이름]([매개변수])//매개변수는 없으면 안적어도 됨.
{
    // 메서드 실행 코드
}
  • 예시 코드:
// 예시 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;
}
  • 메서드 호출 방법:
AddNumbers(10, 20);
  • 호출 시 매개변수는 선언된 순서와 타입이 일치해야 하며, 메서드는 호출되면 내부 코드가 실행되고 결과가 반환된다.

📌 6. 매개변수와 반환값

  • 매개변수는 메서드에 전달되는 외부 입력값이며, 메서드 내부에서 이 값을 활용해 작업을 수행할 수 있다.
  • 반환값은 메서드가 작업을 마친 뒤 호출자에게 넘겨주는 결과물이다.

✅ 예제 코드들:

void PrintFullName(string firstName, string lastName)
{
    Console.WriteLine("Full Name: " + firstName + " " + lastName);
}

// 메서드 호출
PrintFullName("John", "Doe");
int AddNumbers(int a, int b)
{
    int sum = a + b;
    return sum;
}

// 메서드 호출 및 반환값 사용
int result = AddNumbers(10, 20);
Console.WriteLine("Sum: " + result);
void PrintMessage(string message)
{
    Console.WriteLine("Message: " + message);
}

// 메서드 호출
PrintMessage("Hello, World!");
  • void는 반환값이 없음을 의미하며, 그 경우 메서드는 수행만 하고 아무 값도 돌려주지 않는다.
  • 반대로 int, string 등의 반환 타입이 명시된 메서드는 반드시 return을 통해 값을 반환해야 한다.

📌 7. 오버로딩과 디버깅

  • **오버로딩(Overloading)**은 메서드 이름은 같지만 매개변수의 개수나 타입이 다르게 정의하는 것이다.
  • 메서드를 호출할 때 전달한 인자의 형태에 따라 알맞은 메서드가 자동으로 호출된다.

✅ 예제 코드:

int AddNumbers(int a, int b)
{
    return a + b;
}

int AddNumbers(int a, int b, int c)
{
    return a + b + c;
}

float AddNumbers(float a, float b)
{
    return a + b;
}

static long AddNumbers(int a, int b) // 메서드는 반환값이 아니라 매개변수 시그니처로 구분된다.
{
    return a + b;
}

static void Main(string[] args)
{
    int sum1 = AddNumbers(5, 10);
    float sum2 = AddNumbers(5.5f, 10.5f); // 자동으로 float 오버로딩 호출
    int sum3 = AddNumbers(5, 10, 15); // 매개변수 수에 따라 오버로딩됨

    Console.WriteLine(sum1);
    Console.WriteLine(sum2);
    Console.WriteLine(sum3);
}
  • 오버로딩을 통해 같은 이름의 메서드를 다양한 입력 상황에 맞게 유연하게 사용할 수 있다.
  • 디버깅 시 오버로딩된 메서드가 어떤 방식으로 호출되는지 F11(단계별 실행)을 활용해 따라가보면 이해에 도움이 된다.

📌 8. 재귀 호출

  • **재귀 호출(Recursion)**은 메서드가 자기 자신을 다시 호출하는 방식으로 문제를 해결하는 기법이다.
  • 반복문처럼 반복적인 작업을 수행할 수 있지만, 종료 조건이 반드시 필요하다.
  • 종료 조건이 없으면 Stack Overflow 오류가 발생할 수 있다.

✅ 예제 코드:

void CountDown(int n)
{
    if (n <= 0) // 멈추는 방법을 걸어두지 않으면 무한루프에 빠짐!!!
    {
        Console.WriteLine("Done");
    }
    else
    {
        Console.WriteLine(n);
        CountDown(n - 1);  // 자기 자신을 호출
    }
}

// 메서드 호출
static void Main(string[] args)
{
    CountDown(5);
}
  • 실행 결과:
5
4
3
2
1
Done
  • 재귀는 구조가 단순한 경우 매우 유용하지만, 호출이 깊어질수록 성능에 부담을 줄 수 있다.
  • 재귀 대신 반복문으로 바꾸는 방식도 고려할 수 있으며, 종료 조건을 명확하게 정의하는 것이 핵심이다.

📌 9. 메서드 활용 사례

  • 메서드를 사용하면 중복 코드를 줄이고, 한 곳에서 수정만 해도 여러 곳에 영향을 줄 수 있어 유지보수가 쉬워진다.
  • 특히 계산이나 출력처럼 자주 쓰이는 작업은 메서드로 정의해두면 매우 편리하다.

✅ 예제 코드:

// 원의 넓이를 계산하는 메서드
double CalculateCircleArea(double radius)
{
    double area = Math.PI * radius * radius;
    return area;
}

// 사각형의 넓이를 계산하는 메서드
double CalculateRectangleArea(double width, double height)
{
    double area = width * height;
    return area;
}

// 메서드 활용
double circleArea = CalculateCircleArea(5.0);
double rectangleArea = CalculateRectangleArea(3.0, 4.0);

Console.WriteLine("원의 넓이: " + circleArea);
Console.WriteLine("사각형의 넓이: " + rectangleArea);
  • 실행 결과:
원의 넓이: 78.5398163397448
사각형의 넓이: 12
  • 이처럼 메서드는 같은 이름으로 다양한 기능을 정리해놓거나, 복잡한 수식을 쉽게 사용할 수 있게 해주는 도구다.

📌 10. 구조체 (Struct)

  • 구조체(Struct)는 여러 데이터를 하나의 덩어리로 묶어서 표현할 수 있는 사용자 정의 데이터 형식이다.
  • 값 형식(Value Type)으로 분류되며, 변수와 메서드를 함께 가질 수 있다.
  • struct 키워드를 사용하여 정의하며, 보통 작은 데이터 단위를 표현할 때 사용된다.

✅ 예제 코드:

struct Person
{
    public string Name;
    public int Age;

    public void PrintInfo()
    {
        Console.WriteLine($"Name: {Name}, Age: {Age}");
    }
}
  • 구조체는 변수로 선언해서 사용할 수 있고, 구조체 내부 멤버에는 . 연산자를 이용해 접근한다.
  • Console. 으로 접근하는 것도 결국 Console이라는 구조체(혹은 클래스)의 멤버에 접근하는 것과 동일한 원리다.

✅ 사용 예시:

Person person1;
person1.Name = "John";
person1.Age = 25;
person1.PrintInfo();
  • 출력 결과:
Name: John, Age: 25
  • 구조체는 가볍고 단순한 데이터를 표현할 때 적합하며, 클래스(class)보다 메모리 효율적일 수 있다.

📌 11. 실습 과제 - 숫자 맞추기 게임

이번 실습 과제는 1~100 사이의 숫자 중 무작위 숫자를 맞추는 게임을 만드는 것이었다.

✅ 최종 제출한 코드:

static void Main(string[] args)
{
    Random random = new Random();

    int number = random.Next(1, 100);

    int guess = 0;
    int attempts = 0;

    Console.WriteLine("1~100까지의 숫자 중 하나를 맞춰보세요!");
    Console.WriteLine("숫자를 입력하세요.");
    int input = int.Parse(Console.ReadLine());

    if (0 < input && input < 100)
    {
        guess = input;

        // 무한 루프를 사용하여 정답을 맞출 때까지 반복
        while (input != number)
        {
            if (input < number)
            {
                Console.WriteLine("UP!");
                attempts++;
            }
            else if (input > number)
            {
                Console.WriteLine("DOWN!");
                attempts++;
            }

            Console.WriteLine("숫자를 입력하세요.");
            Console.WriteLine("현재까지 시도횟수: " + attempts);
            input = int.Parse(Console.ReadLine());

            // 입력 범위 확인 (1~100 사이)
            if (input <= 0 || input >= 100)
            {
                Console.WriteLine("1~100 사이의 숫자를 입력하세요.");
                continue; //범위 밖이면 다시 입력받기
            }
        }

        // 정답을 맞췄을 때 - 루프를 빠져나온 후 실행됨
        Console.WriteLine("정답입니다!");
        Console.WriteLine("시도횟수: " + attempts);
    }
    else
    {
        Console.WriteLine("1~100 사이의 숫자를 입력하세요.");
    }
}

🧠 느낀 점 & 코드 리뷰

  • 처음 작성 시에는 while (true)break를 썼지만, 정답 조건과 입력 범위 조건이 명확히 나뉘는 구조로 변경하면서 코드의 가독성이 좋아졌다.
  • attempts 카운트 위치가 적절했음. 정답 입력은 카운트 제외되도록 설계하여 정확한 시도 횟수 추적 가능.
  • if (input <= 0 || input >= 100) 조건이 루프 내부에 반복적으로 있어서 다소 중복처럼 보일 수 있으나, 잘못된 입력 방지를 확실히 처리한 점이 실무적으로도 중요.
  • 추후에는 이 코드를 CheckGuess() 같은 메서드로 분리하면 더 깔끔하게 재사용 가능한 형태로 만들 수 있을 것 같다.
  • Random, int.Parse, Console.ReadLine() 등 다양한 기본 문법을 종합적으로 적용해 볼 수 있어 좋은 복습과 연습이 됨.

이 실습은 메서드, 조건문, 반복문, 예외 처리의 복합 연습으로서, 메서드 분리의 필요성과 입력 검증의 중요성도 체감할 수 있는 유익한 과제였다. ✍️

 

 

📌 오늘을 돌아보며 - 완전 초보자의 C# 첫걸음 회고

오늘은 정말 많은 걸 배운 하루였다. 그동안 막연하게만 들었던 "배열", "컬렉션", "메서드", "구조체"라는 단어들이 실제 코드에서 어떻게 쓰이는지를 직접 보고, 써보면서 체감할 수 있었다.

🧩 처음엔 너무 복잡하게 느껴졌던 개념들

  • 배열은 같은 자료형을 한 줄로 나열한다는 건 알겠는데, 왜 쓰는지 몰랐다. 그런데 직접 아이템 가격을 계산해보거나 캐릭터 능력치를 저장해보니 "아, 이런 식으로 데이터를 정리하는 거구나!" 하고 감이 잡혔다.
  • 2차원 배열로 맵을 출력하는 건 정말 신기했다. 마치 미니 게임의 기초를 만든 기분!
  • 컬렉션은 가변적이고 더 유연한 느낌이었고, 특히 ListDictionary의 사용법은 실제 프로그램에서 많이 쓰일 것 같았다.

🛠️ 메서드는 왜 쓰는지 이해가 됐다!

  • 반복되는 코드를 함수로 빼는 게 왜 필요한지 잘 몰랐는데, PrintLine() 같은 간단한 메서드를 만들어서 호출해보니 코드가 엄청 간결해졌다.
  • return을 통해 값을 돌려주는 것은 그저 막연히 기능만 알았으나 강사님의 치약을 바꾸는 비유가 재밌었고, 오버로딩으로 같은 이름의 메서드를 메개변수에 따라 다양하게 쓰는 것도 신기했다.
  • 무엇보다 디버깅(F11)을 통해 함수 내부로 들어가서 실행 흐름을 추적하는 과정이 아주 큰 도움이 됐다.

🧠 실습 과제: 숫자 맞추기 게임에서 느낀 점

  • 실습을 통해 지금까지 배운 문법들이 하나로 연결되는 걸 느꼈다.
  • 특히 무한루프, 조건문, 입력검사, 시도 횟수 추적 같은 구조를 짜면서, 프로그래밍은 퍼즐처럼 조립하는 작업이라는 느낌을 받았다.
  • 내가 직접 만든 게임이 내 입력에 반응할 때의 기분은 정말 짜릿했다.

💬 초보자의 시선에서

  • 아직도 헷갈리는 게 많고, 코드를 짜다 보면 에러도 자주 나서 결국은 깃헙 코파일럿 나으리의 도움을 조금씩은 받고있지만, 오늘은 배운 것을 내 손으로 직접 구현해본 날이라 더 기억에 남는다.
  • 앞으로 배울 클래스, 상속 같은 것들도 지금처럼 '손으로 써보고 실행해서 확인하는 방식'으로 배우면 무서울 게 없을 것 같다.
  • "할 수 있을까?"에서 "조금씩 보인다!"로 넘어가는 기분이었다.

이제 시작이지만, 오늘 하루는 정말 뿌듯하다.
내일은 더 어려운 개념이 나오더라도 두려워하지 않고, 하나씩 내 것으로 만들 수 있을 거란 자신감이 생겼다. 💪