C# 게임 만들기 - 1 (키워드 워리어)

krokrai·2025년 12월 13일

키워드 워리어

개요

  • 게임 방식 및 기획
  • 구현된 코드

게임 방식 및 기획

  • 옛날 로그 게임과 같이 console 창에 문자로 그래픽을 구현했습니다.
  • 던전 탐험(던전 크롤러)이며, 선형적인 길방마다 이벤트, 휴식, 전투를 넣어서 최하층에 도착하여 보스를 잡으면, 승리하는 방식입니다.
  • 전투에서 특정 키워드를 받아 조합하여, 기술을 구현해 적들을 물리칠 수 있게 구현할 예정입니다.
  • 이벤트, 휴식, 전투 후 등으로 추가적인 키워드를 얻거나 잃는 방식을 넣을 예정입니다.
  • 난이도는 연습, 쉬움, 보통, 어려움, 오염된 던전 예정에 있습니다.
  • 캐릭터 별로 주워지는 능력치와 키워드의 차별점이 존재할 예정입니다.

구현된 코드

  • 매일 조금씩이라도 업데이트할 예정이며, 현재까지 구현된 코드 및 해설입니다.
  • 함수별로 올릴 예정이며, 마지막 포스팅에 최종 코드를 올리겠습니다.
// 메인 화면 
class Program
{
	static void Main()
    {
    	int isStart = MainMenu()
        while(isStart == 0)
        {
        	// 내부 구현
        }
    }
    
    static MainMenu()
    {
    	byte arrowPos = 0;
        Console.WriteLine("-------------------------------");
        Console.WriteLine("------Keyword Warrior----------");
        Console.WriteLine("-------------------------------\n");
        Console.WriteLine("      -> 게임 시작");
        Console.WriteLine("         게임 종료");
        // 반복문은 다음 상태(게임 시작, 게임종료)가 입력되기 전까지 입력을 받을 수 있게 걸어두었습니다.
        while (true)
        {
        	// 유저에게 문자형식이 아닌, 키를 누르는 즉시 받아오기 위해 ReadKey()로 구현
            // cnKey로 따로 나눈 이유는 if문 마다 검사를 진행 시 원하는 타이밍에 엔터 등이 작동하지 않기 때문입니다.
            ConsoleKey cnKey = Console.ReadKey().Key;
            // DownArrow, UpArrow는 모두 아랫바향키(키패드 옆 화살표), 윗방향키
            if (cnKey == ConsoleKey.DownArrow || cnKey == ConsoleKey.UpArrow)
            {
            	// 코드가 가볍기 때문에 모든 내용을 지우고 새로 불러오는 식으로 구현했습니다.
                // 물론 필요한 부분만, 새로 작성하는 방식이 제일 좋지만, 현제는 구현하지 않겠습니다.
                Console.Clear();
                // 만약, 어디 방향키를 누룬줄 알고 aarrowPos만 처리하는가? 라는 의문이 든다면 아래 코드를 보시다보면, 필요할때 구현하였습니다.
                // 추가로 저는 얼마 사용 안할줄 알고 함수로 따로 분류하지 않아 매 함수마다 작성(...)하였습니다.
                switch (arrowPos)
                {
                	// 0번(게임시작)인 상태에서 아랫방향키를 눌렀을 시 게임 종료로 이동 후 arrowPos를 증가
                    case 0:
                        Console.WriteLine("-------------------------------");
                        Console.WriteLine("------Keyword Warrior----------");
                        Console.WriteLine("-------------------------------\n");
                        Console.WriteLine("         게임 시작");
                        Console.WriteLine("      -> 게임 종료");
                        arrowPos++;
                        break;
                    case 1:
                        Console.WriteLine("-------------------------------");
                        Console.WriteLine("------Keyword Warrior----------");
                        Console.WriteLine("-------------------------------\n");
                        Console.WriteLine("      -> 게임 시작");
                        Console.WriteLine("         게임 종료");
                        arrowPos--;
                        break;
                }
            }
            // 아래와 위가 아니면서, 엔터(확정)을 누를 시 해당 위치를 반환하여, 시작인지 종료인지, 확인하였습니다.
            else if (cnKey == ConsoleKey.Enter)
            {
            	// 메인 화면은 더 이상 필요하지 않기 때문에 화면을 지운 상태에서 넘겨줍니다.
                Console.Clear();
                return arrowPos;
            }
        }
    }
}
  • 아래는 게임 시작 후 화면입니다. 윗코드와 매우 비슷하기 때문에, 추가 설명은 안하겠습니다.
static void Main()
{
	//위에 선언들...
    while (isStart == 0)
    {
    	// 위와 같이 야영지 입장인지, 던전 입장인지, 확인하기 위한 변수
        int tempChoice = GameStartPointScreens();
        if (tempChoice == 0) // 야영지 입장
        {
            // 구현 코드
        }
        else if (tempChoice == 1) // 던전 입장
        {
			//구현 코드
        }
    }
}

static int GameStartPointScreens()
{
	//간단하게 화면에 야영지, 구름(?), 태양(?), 땅, 던전을 만들었습니다.
    Console.WriteLine("                                - O\n" +
                                  "           mm                       |\n " +
                                  "        uuuuu                                 \n" +
                                  "       ↓                                  \n" +
                                  "   _________                   ______\n" +
                                  "  /  야영지 \\                 | 던전 | \n" +
                                  " |          |                 |      | \n" +
                                  " |     □   |                 |  □  | \n" +
                                  "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n" +
                                  "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n");
    byte arrowPos = 0;
    // 윗 코드와 마찬가지로 입력을 위한 무한 반복
    while (true)
    {
        ConsoleKey cnKey = Console.ReadKey().Key;
        // 이번에는 왼쪽과 오른쪽으로 이동할 예정이라, Up, Down에서 Right, Left로 바꿨습니다.
        // 내부 코드는 위와 같기 때문에 설명은 넘기겠습니다.
        if (cnKey == ConsoleKey.RightArrow || cnKey == ConsoleKey.LeftArrow)
        {
            Console.Clear();
            switch (arrowPos)
            {
                case 0:
                    Console.WriteLine("                                - O\n" +
                                  "           mm                       |\n " +
                                  "        uuuuu                                 \n" +
                                  "                                 ↓        \n" +
                                  "   _________                   ______\n" +
                                  "  /  야영지 \\                 | 던전 | \n" +
                                  " |          |                 |      | \n" +
                                  " |     □   |                 |  □  | \n" +
                                  "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n" +
                                  "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n");
                    arrowPos++;
                    break;
                case 1:
                    Console.WriteLine("                                - O\n" +
                                  "           mm                       |\n " +
                                  "        uuuuu                                 \n" +
                                  "       ↓                                  \n" +
                                  "   _________                   ______\n" +
                                  "  /  야영지 \\                 | 던전 | \n" +
                                  " |          |                 |      | \n" +
                                  " |     □   |                 |  □  | \n" +
                                  "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm\n" +
                                  "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n");
                    arrowPos--;
                    break;
            }
        }
        else if (cnKey == ConsoleKey.Enter)
        {
            Console.Clear();
            return arrowPos;
        }
    }
}
  • 야영지 내부 구현입니다. (그래픽 구현을 위한 코드 때문에 매우 깁니다.)

static void Main(string[] args)
{
    Character ch = new Character();
    int isStart = MainMenu();
    while (isStart == 0)
    {
        ch.SelectChar(0);
        int tempChoice = GameStartPointScreens();
        if (tempChoice == 0) // 야영지 입장
        {
            ch.SelectChar(ChoiceCharater(maxCharater));
        }
        else if (tempChoice == 1) // 던전 입장
        {
    		// 코드 구현
        }
    }

}

static int ChoiceCharater(int limitChar)
{
    Console.WriteLine("               ↓                                                           \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                                      \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ?????????????  | ?????????????  | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ?????????????  | ?????????????  | ????????????? |_______\n");
    int arrowPos = 0;
    while (true)
    {
        ConsoleKey cnKey = Console.ReadKey().Key;
        // 이번에는 4방향으로 움직여야하기 때문에, 모든 방향키를 입력받게 만들었습니다.
        if (cnKey == ConsoleKey.RightArrow || cnKey == ConsoleKey.LeftArrow || cnKey == ConsoleKey.DownArrow || cnKey == ConsoleKey.UpArrow)
        {
        	// 위에서 언급하였듯, 방향에 따라 어디로 이동하였는지 추적하 및 표시하게 만들었습니다.
            // 1차적으로 어디로 이동하였는지 추적하기 위해 switch를 이용하여 방향키에 대한 검사를 했습니다.
            switch (cnKey)
            {
                case ConsoleKey.LeftArrow:
                	// 3항 연산자를 사용하여 간단하게 구현하였습니다.
                    // 풀이 : 왼쪽 방향키를 눌렀을 시, 현제 arrowPos -1(<-으로 이동하기 때문에)을 한 후 해당 값이 0 미만인가?
                    // 0미만인 경우, 끝으로 이동, 0 미만이 아닌 경우 -1
                    arrowPos = ((arrowPos - 1) < 0) ? 11 : arrowPos - 1;
                    break;
                case ConsoleKey.RightArrow:
                	// 위와 계산 방식은 동일
                    arrowPos = ((arrowPos + 1) > 11) ? 0 : arrowPos + 1;
                    break;
                case ConsoleKey.UpArrow:
                	// 위쪽 방향키를 눌렀을 시 수직으로 이동하기 때문에 -3을 합니다.
                    // 중간을 기준으로 위로 이동하면, 수가 작아지기 때문에 감소시키는 것입니다.
                    // 0 1 2
                    // 3 4 5
                    // 6 7 8
                    // 9 10 11
                    
                    // 해당 값이 0 보다 작을 경우, +9(0에서 위로 이동시 9이기 때문)
                    arrowPos = ((arrowPos - 3) < 0) ? arrowPos + 9 : arrowPos - 3;
                    break;
                    // 위와 계산 방식은 동일합니다.
                case ConsoleKey.DownArrow:
                    arrowPos = ((arrowPos + 3) > 11) ? arrowPos - 9 : arrowPos + 3;
                    break;
            }
            Console.Clear();
            //아래 switch는 위 코드들과 구현 방식이 같기 때문에 설명은 없습니다.
            switch (arrowPos)
            {
                case 0:
                    Console.WriteLine("               ↓                                                           \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                                      \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 1:
                    Console.WriteLine("                               ↓                                           \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                                      \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 2:
                    Console.WriteLine("                                               ↓                      \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                                      \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 3:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |       ↓                                                                             \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 4:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                       ↓                                                   \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 5:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                       ↓                               \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 6:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                                   \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |       ↓                                                                             \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 7:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                             \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                       ↓                                                   \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 8:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                             \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                       ↓                                    \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                       \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 9:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                                      \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |       ↓                                                                             \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 10:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                          \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                       ↓                                                   \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
                case 11:
                    Console.WriteLine("                                                                          \n" +
                                  " ------|  균형과 조화  |  겁화의 상징  | 얼어붙은 심장 | ---------- \n" +
                                  "       |                                                                      \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                                                                 \n" +
                                  "       | ????????????? | ????????????? | ????????????? |\n" +
                                  "       |                                       ↓                               \n" +
                                  "_______| ????????????? | ????????????? | ????????????? |_______\n");
                    break;
            }
        }
        else if (cnKey == ConsoleKey.Enter)
        {
        	// arrowPos를 통하여, 위치를 정확히 추적했기 때문에, 반환값으로 해당 위치(arrowPos)를 반환합니다.
            // limitChar는 현재 구현된 캐릭터 수이며, 현재 구현된 캐릭터는 0개지만, 임시 구조를 갖인 캐릭터 0번이 있습니다.
            if (arrowPos < limitChar)
            {
                Console.Clear();
                return arrowPos;
            }
            continue;
        }
    }
   	class Character
    {
        private double healthPoint;
        private double healthRegen;
        private double attackDamage;
        private double armor;
        private double abilityPower;
        private double magicResistnce;
        private double speed;
        private int level;

        public void SelectChar(int c)
        {
            switch (c)
            {
                case 0:
                    //균형과 조화
                    healthPoint = 100;
                    healthRegen = 1;
                    attackDamage = 1;
                    armor = 1;
                    abilityPower = 1;
                    magicResistnce = 1;
                    speed = 100;
                    level = 0;
                    break;
                case 1:
                    // 겁화의 상징

                    break;
                case 2:
                    // 얼어붙은 심장

                    break;
                default:
                    healthPoint = 100;
                    healthRegen = 1;
                    attackDamage = 5;
                    armor = 1;
                    abilityPower = 5;
                    magicResistnce = 1;
                    speed = 100;
                    level = 0;
                    break;
            }
        }

        public void SelectMonster(int m)
        {
            switch (m)
            {
                case 0:
                    // 몬스터 1
                    healthPoint = 20;
                    healthRegen = 1;
                    attackDamage = 1;
                    armor = 1;
                    abilityPower = 1;
                    magicResistnce = 1;
                    speed = 60;
                    level = 0;
                    break;
                case 1:

                    break;
                case 2:

                    break;
                default:
                    healthPoint = 100;
                    healthRegen = 1;
                    attackDamage = 1;
                    armor = 1;
                    abilityPower = 1;
                    magicResistnce = 1;
                    speed = 100;
                    level = 0;
                    break;
            }
        }
    }

}
}
  • 아래 코드가 현재 구현된 코드의 마지막이자 핵심입니다.
  • 미완성된 코드로 일부만이 구현되어 있습니다.
  • 해당 코드는 다른 코드와 상호작용 준비가 되어 있지 않아, Main에 해당 함수만 담았습니다.

static Void Main()
{
	// 점화(공격능력), 강화(보조능력), 복사(보조능력)
    // 점화는 설명을 생략하겠습니다.
    // 강화는 바로 뒤에 있는 공격 능력 등에 레벨을 높입니다.
    // 복사는 바로 뒤에 있는 공격, 보조 능력 등을 복사합니다.
    // 
	KeywordsActive("점화 강화 복사 점화 강화");
}

static int KeywordsActive(string s)
{
	// Main에서 넘겨준 문자열을 공백으로 나눴습니다.
    string[] keyWords = s.Split(' ');
    // 레벨을 저장할 변수이며, 변경될 수 있습니다.
    int lv = 0;
    // 최대 5개의 키워드만 받을 예정이기 때문에 5 이상이면, -1로 반환하여 재입력을 받을 예정입니다.
    if (keyWords.Length > 5)
        return -1;
    for (int i = 0; i < keyWords.GetLength(0); i++)
    {
        //공격과 방어 능력(방어는 미구현)을 우선 감지 할 예정입니다.
        switch (keyWords[i])
        {
            case "점화":
                // EnchantedSkill 함수를 만들어 키워드와 현제 위치, 반환 값을 받을 예정입니다.
                EnchantedSkill(keyWords, ref i, out lv);
                // 강화 등이 완료된 능력을 실현합니다.
                AbilityActive("점화", lv);
                break;
        }
    }
    return 0;
}

static void AbilityActive(in string s,in int lv)
{
	// 어떤 능력이 어떤 레벨로 실현되었는 지 표시합니다.
    Console.WriteLine($"{s} Lv.{lv} 공격!");
}

static bool EnchantedSkill(in string[] ss, ref int aa, out int lv)
{
	// 기본 능력 레벨은 0이므로, 0을 기본값으로 초기화합니다..
    lv = 0;
    // 우선 복제가 있는지 검사한 후 복제가 있을 경우 바로 앞에 있는 능력을 복제합니다.
    // 복제가 가장 앞에 있을 경우는 가정하지 않았기 때문에 후에 수정예정입니다.
    for (int i = aa + 1; i < ss.GetLength(0); i++)
    {
        switch (ss[i])
        {
            case "복제":
                ss[i] = ss[i-1];
                break;
        }
    }
    // 강화 등, 복제가 아닌 능력을 실현합니다.
    for (int i = aa+1; i < ss.GetLength(0); i++)
    {

        switch (ss[i])
        {
            case "강화":
                 lv += 1;
                break;
            default:
                return true;
        }
    }
    return false;
}
  • "점화 강화 강화 점화 강화" 일경우
점화 Lv.2 공격!
점화 Lv.1 공격!
  • "점화 복제 강화 점화 강화" 일경우
점화 Lv.0 공격!
점화 Lv.1 공격!
점화 Lv.1 공격!
  • 현재 구현되어 있는 코드는 여기까지이며, 이후 포스팅에서 남은 코드부분을 완성 후 올리겠습니다.
profile
게임을 좋아하고 만들고 싶은 개발자 지망생입니다.

0개의 댓글