본문 바로가기
  • 식초 한잔 할래..?
공부/게임 공부

C#으로 간단한 게임 만들기

by 돼지피그푸곰 2025. 10. 13.

비어있는 시간 동안 Text RPG, C#기본기 공부 등을 하고, 추석을 지내며, 여러 과제를 했는데, 그 중 기억에 남는 것들을 정리하는 시간을 가져보도록 하겠습니다.

 

때문에 이번 TIL은 Today가 아니라 This week입니다.

 

가장 기본 문제인 5개 가겠습니다.

 

1. 사용자로부터 입력 받기.

 

과거에 했던 언어와 다르게 C#은 약자를 덜 쓰는 대신 조금 더 긴 것 같습니다.

 

Console.WriteLine의 활용법과, 입력받는 Console.ReadLine()에 대한 문제입닙니다.

Console.Write의 경우 뒤에 Line이 붙는 경우와 안붙는 경우가 있습니다.

Line이 붙은 경우 텍스트 출력 후 줄을 바꿉니다.

즉 \n의 역할이지요.

 

때문에 Console.write만 한 다음에 \n을 쓰는게 더 빠를 것 같긴 한데, Tab을 누르면 대부분 자동완성이 되어서 그냥 Console.WriteLine을 쓰게 됩니다.

 

이건 출력하는 방법이고, 중요한건 입력을 받아야 합니다.

 

Console.ReadLine()

 

이름만 봐도 라인을 읽겠다고 주장하고 있습니다. 콘솔창에 외부 입력값을 치면 그걸 읽어줍니다.

 

때문에 우선 어떤걸 입력 받을지를 어느 정도 알아야 합니다.

예를 들어 나이가 몇 살입니까?

라고 하면 숫자를 입력할 테고,

이름이 무엇입니까?

라고 하면 문자를 입력할 테지요.

 

기본적으로 ReadLine은 문자열로 받기 때문에

문자인 경우)

string name = Console.ReadLine();

으로 받습니다. 이제 name에 입력받은 문자가 저장됩니다.

숫자인 경우)

int age = int.Parse(Console.ReadLine())

으로 받습니다. 문자로 받은걸 숫자로 변형시켜준 다음에 age에 저장합니다.

 

만약에 받는 입력값이 문자인지 숫자인지 모른다면

int.TrtParse()를 이용합니다.

방금 전에 int.Parse는 문자를 순자로 변환해 주는 과정이었습니다.

근데 이번에는 문자인지 숫자인지 모르니까 Try. 시도해 봐라 입니다.

-> 숫자로 변환이 가능한지 확인하는 과정을 거쳐라 입니다.

 

1
2
3
4
5
6
7
8
9
10
11
Console.Write("입력하세요: ");
        string input = Console.ReadLine();
 
        if (int.TryParse(input, out int number))
        {
            Console.WriteLine($"숫자입니다. 값: {number}");
        }
        else
        {
            Console.WriteLine($"문자열입니다. 값: {input}");
        }
cs

 

 

때문에 확인을 거친 다음에 문자면 이렇게, 숫자면 이렇게 라는 식으로 양자택일로 출력해주면 됩니다.




2. 간단한 사칙연산 계산기 만들기

1
2
3
4
5
6
7
8
9
10
Console.Write("첫 번째 숫자를 입력하세요: ");
        double a = double.Parse(Console.ReadLine());
 
        Console.Write("두 번째 숫자를 입력하세요: ");
        double b = double.Parse(Console.ReadLine());
 
        Console.WriteLine($"덧셈: {a + b}");
        Console.WriteLine($"뺄셈: {a - b}");
        Console.WriteLine($"곱셈: {a * b}");
        Console.WriteLine($"나눗셈: {a / b}");
cs

 

int number = int.Parse(Console.ReadLine())으로 숫자를 받은 후

Console.WriteLine("{a + b}")

느낌으로 대괄호를 이용해서 바로 출력시키면 됩니다.

다만 int로 하면 정수만 나오게 되니 float나 double등으로 소수점까지 나올 수 있게 하면 더 좋을 것 같습니다.

 

 

 


 


 


숫자 맞추기 게임 만들기

 

갑자기 난이도 확 올라갔습니다. 숫자를 맞추는 게임입니다.

 

만들기 전에 어떤 식으로 만들지 생각을 해봅니다.

 

1. 1~100까지의 랜덤한 숫자 하나를 답으로 정한다.

2. 사용자에게 입력값을 받는다

3. 입력받은 값이 답보다 크거나 작은지 대답해준다.

4. 입력받은 값과 답이 일치하면 정답이라고 알려준다.

 

정리해보면, if문을 사용해서 미리 정해둔 답보다 큰 값일 땐 더 작다고, 작은 값일 땐 더 크다고 출력해주는 조건문을 달아준 후, 일치할 때는 정답이라고 답변하게 하면 됩니다.

 

답은 answer로 정하고, 외부에서 입력받는 값을 guess로 정하면, 

C#에서 준비해져 있는 Random()을 사용하면 됩니다.

int answer = random.Next(1,101)

로써, 1~100까지의 숫자 중 하나를 answer로 입력했습니다.

guess또한 위와 같이 = int.Parse(ConsoleReadLine())으로 입력받은 값을 정수로 변환한 후 받아줍니다.

 

이후에는 if문을 활용하겠습니다.

if(guess > answer)

else if(guess < answer)

else //(guess == answer)

 

위의 3가지 경우에 대해서 어떻게 출력할건지만 정해주면 끝입니다.

else뒤는 안적어도 됩니다. 남은 경우의 수가 저것 뿐이기 때문에 알아서 저 조건으로 되지만 주석으로 단 느낌입니다.

 

완성하면 아래와 같습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Random random = new Random();
        int answer = random.Next(1101);  // 1~100 사이 랜덤 정답
        int guess = 0;                     // 사용자의 입력값 저장용
        int count = 0;                     // 시도 횟수 기록용
 
        Console.WriteLine("1부터 100 사이의 숫자를 맞혀보세요!");
 
        while (guess != answer)
        {
            Console.Write("숫자 입력: ");
            guess = int.Parse(Console.ReadLine());
            count++;
 
            if (guess > answer)
                Console.WriteLine("더 작은 수입니다.");
            else if (guess < answer)
                Console.WriteLine("더 큰 수입니다.");
            else
                Console.WriteLine($"정답입니다! 시도 횟수: {count}");
        }
cs

 




틱택토 게임 만들기

 

무슨 게임인지 몰라서 알아보니 외국인들이 많이 하는 미니 오목입니다.

 

정상적으로 하면 무승부가 날 수 밖에 없는 게임인데 도대체 이걸 왜 하는지 이해는 가지 않습니다.

 

결론부터 말하자면 저는 아직 못했습니다.

제가 배열이 좀 많이 약합니다.

수능 수학에서도 확률가 배열이 제일 싫었거든요..!

 

그래서 봐도 봐도 헷갈립니다. 때문에 이건 다음에 하고 그 다른 주제인 Text RPG에 대해서 이야기 좀 해보겠습니다.

 




 

 

 

 

각 단계별로 기능을 추가하면서 확장해 보았다.

이 외에도 필수 기능의 구현이 완료되면 도전 기능들도 준비되어 있다.

 

때문에 처음에는 단계별로 필수 기능들만 구현을 진행하였는데, 이 과정에서 힘들었던 부분들이 있었다.

 

'확장성'

 

현재 연습중인 부분이기 때문에, 미래에 확장할 부분은 생각 못한 채, 각 기능들을 마치 작은 문제를 풀듯이 완성형으로 만들어 내는 문제가 있다.

 

대문에 캐릭터 정보 만들기 부분은, 정보를 만들긴 하지만, 미래에 그 정보가 변환될 생각은 하지 못한 채 고정 값으로 만들었다.

이 과정을 반복하다 보니, 후에 새로운 기능들을 추가할 때 어디서 부터 손을 대어야 할지, 손을 대고 생기는 오류가 전체적으로 생겼을 때 어떻게 해결을 해야 할지 막막해 지는데,

이때 사용한 Chat GPT의 도움으로 기능은 구현이 되었지만, 조언에 따라 바꾸다 보니 사실상 처음부터 다시 만든 수준으로 변경이 되었다.

 

class Game
{
    static void Main()
    {
        Logic logic = new Logic();
        logic.Menu();
    }
}

 

때문에 각 class를 나누어서 보았다.

Charcter, Inventory, Status, Adventure, Train 등등

각각의 기능에 대한 함수를 구성 후 불러내는 형식이다.

 

다만 이를 Logic class 내에 전부 만들다 보니, Logic이 무거워 졌다.

 

 

 

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
 
    public void Menu()
    {
        while (true)
        {
            Console.Clear();
            int width = Console.WindowWidth;
            string title = "스파르타 마을에 오신 여러분을 웰컴";
            string line = new string('=', title.Length + 20);
            Console.ForegroundColor = ConsoleColor.Yellow;
 
            int leftPadding = (width - line.Length) / 2;
            Console.WriteLine(line.PadLeft(line.Length + leftPadding));
            Console.WriteLine(title.PadLeft(title.Length + (width - title.Length) / 2));
            Console.WriteLine(line.PadLeft(line.Length + leftPadding));
            Console.ResetColor();
            Console.WriteLine(
                @"
이곳에서 던전으로 들어가기 전 활동을 할 수 있습니다.
 
1. 상태 보기
2. 인벤토리
3. 랜덤 모험
4. 마을 순찰
5. 훈련
0. 종료");
 
            string input = GetInput("\n원하시는 행동을 입력해주세요\n>>");
 
            switch (input)
            {
                case "1":
                    Status();
                    break;
                case "2":
                    Inventory();
                    break;
                case "3":
                    Adventure();
                    break;
                case "4":
                    Patrol();
                    break;
                case "5":
                    Train();
                    break;
                case "0":
                    return;
                default:
                    Console.WriteLine("잘못된 입력입니니다");
                    Console.ReadKey();
                    break;
            }
        }
    }
 
 
 
 
 
메인 메뉴에서 각 함수를 호출하게끔 구성하였고, 각 함수는 각자의 기능을 한다.
 
이 과정에서 제일 어려웠던건 역시 배열과 토글이다.
 
익숙하지 않아서 그런지 번뜩 떠오르지 않는다.
 
 
 
if (input == "0"break;
if (int.TryParse(input, out int index) && index >= 1 && index <= items.Length)
{
    items[index - 1].IsEquipped = !items[index - 1].IsEquipped;
}
else
{
    Console.WriteLine("잘못된 입력입니다.");
    Console.ReadKey();
}
 
 
 
장비를 장착하는 토글 코드이다.
 
 
 
만약 입력받은 값이 장비를 선택하는 값과 같다면, 반전시켜준다.
 
그리고 그 전에 bool값으로 false, true인 두 가지 경우의 수만 받을 수 있게 설정해 둔다.
 
만약 false면 아무런 상태도 아니짐나 true면 장착이 되는 형식이다.
 
여기에는 없지만 장착이 되면 장비 앞에 [E] 표시도 추가된다.
 
 string mark = items[i].IsEquipped ? "[E]" : "";
 
 
 
이해는 되지만 실전에서 쓸 때마다 흠칫하게 된다.
 
 
 
 string mark = items[i].IsEquipped ? "[E]" : "";
 string type = items[i].Type == ItemType.Attack ? "공격력" : "방어력";
 Console.WriteLine($"{mark}{items[i].Name.PadRight(12)} | {type} +{items[i].Value,-5} | {items[i].Description.PadRight(30)}");
 
 
 
때문에 Inventory함수가 가장 힘들었다.
cs