[TIL] 11일차 - TextRPG 완성

김유원·2024년 1월 8일
0

📝24.01.08

TextRPG를 어느정도 완성했다. 10일차 TIL에 언급했던 4가지 사항들을 모두 해결했다.

1) Store 아이템 리스트 개선

아예 Main에 Item List를 선언해주고, 해당 리스트에 함수를 통해 아이템을 추가해주는 방식으로 수정하였다. 참고로 아이템 추가는 레벨업 시 호출하는 메카닉으로 구상했다.

static List<Item> AddStoreList(List<Item> shopItem, int level)
{
    // 레벨업 후 숍 방문시 실행 필요
    Item[] lv1 = { new Item(0, "수련자 갑옷", 0, 0, 5, " 초보자를 위한 수련에 도움을 주는 갑옷.", 500),
                   new Item(1, "낡은 검", 1, 2, 0, " 쉽게 부서질 것 같은 낡은 검.", 300),
                   new Item(2, "청동 도끼", 1, 4, 0, " 방금까지도 나무를 벤 것 같은 흔한 도끼.", 900)};

    Item[] lv2 = { new Item(3,"무쇠 갑옷", 0, 0, 10, " 숙련자가 만든 튼튼한 갑옷.", 1200),
                   new Item(4,"가벼운 은검", 1, 7, 0, " 휴대하기 좋은 날카로운 은검.", 1200)};

    Item[] lv3 = { new Item(5,"장인의 갑옷", 0, 0, 15, " 장인이 만든 갑옷. 1년에 단 1개만 제작된다고 한다.", 2000),
                   new Item(6,"장인의 검", 1, 10, 0, " 장인이 만든 검. 스치기만 해도 치명상을 입는다.", 1600),
                   new Item(7,"장인의 활", 1, 7, 3, " 장인이 만든 활. 먼 거리에서도 화살이 올곧게 날아간다.", 1600)};

    //전설의 전용 무기
    Item[] lv5 = { new Item(8,"이카본의 쌍검", 2, 20, 10, " 초대 군주 이카본이 기사단장에게 수여했다고 전해지는 전설의 검. 기사만이 사용할 수 있다.", 5000),
                   new Item(9,"용병왕의 대검", 3, 15, 15, " 사라진 용병왕의 대검. 용병이 아닌 자는 들 수 없다.", 5000),
                   new Item(10,"아나로즈의 망토", 4, 10, 10, " 수천년을 산 마녀 아나로즈의 망토. 마법사가 아닌 자는 그 용도를 알 수 없다.", 5000)};

    if (level == 1)
    {
        for (int i = 0; i < lv1.Length; i++)
        {
            shopItem.Add(lv1[i]);
        }
    }
    else if (level == 2)
    {
        for (int i = 0; i < lv2.Length; i++)
        {
            shopItem.Add(lv2[i]);
        }
    }
    else if (level == 3)
    {
        for (int i = 0; i < lv3.Length; i++)
        {
            shopItem.Add(lv3[i]);
        }
    }
    else if (level == 5)
    {
        for (int i = 0; i < lv5.Length; i++)
        {
            shopItem.Add(lv5[i]);
        }
    }

    return shopItem;
}

2) Monster 클래스 생성 및 던전 작업

Dungeon 함수

static void Dungeon(Warrior character, List<Item> shopItem)
{
    TextColor("\n[던전]", ConsoleColor.Yellow);

    Console.WriteLine("\n1. 훈련 던전     | 방어력 5 이상 권장");
    Console.WriteLine("2. 일반 던전     | 방어력 11 이상 권장");
    Console.WriteLine("3. 드래곤 던전   | 방어력 20 이상 권장");
    Console.WriteLine("0. 나가기\n");

    int cmd = CheckAction("어느 던전을 들어가시겠습니까?", 0, 3);
    bool isWin = false;
    Console.Clear();
    switch(cmd)
    {
        case 0:
            Village(character, shopItem);
            break;
        case 1:
            Monster troll = new Monster("트롤", 4, 2, 30);
            isWin = Battle(character, troll);
            break;
        case 2:
            Monster goblin = new Monster("고블린", 8, 5, 100);
            isWin = Battle(character, goblin);
            break;
        case 3:
            Monster dragon = new Monster("드래곤", 30, 20, 300);
            isWin = Battle(character, dragon);
            break;
    }

    if(isWin == true)
    {
        character.LevelUP();
        AddStoreList(shopItem, character.Level);
    }

    Village(character, shopItem);
}

Monster 클래스

public class Monster : ICharacter
{
    public string Name { get; set; }
    public int AtkPower { get; set; }
    public int DefPower { get; set; }
    public int Health { get; set; }

    public Monster(string name, int atkPower, int defPower, int health)
    {
        Name = name;
        AtkPower = atkPower;
        DefPower = defPower;
        Health = health;
    }

    public void Attack(ICharacter Enemy)
    {
        Random rand = new Random();
        double damage = (AtkPower * rand.Next(50, 151)) * 0.01;
        if(damage - Enemy.DefPower < damage / 2)
        {
            damage /= 2;
        } else
        {
            damage -= Enemy.DefPower;
        }
        Enemy.Health -= (int)Math.Round(damage);
        Console.WriteLine("{0} 은(는) {1}의 데미지를 받았다!", Enemy.Name, (int)Math.Round(damage));
    }
}

Dungeon 클래스를 생성하는 대신 던전은 같은 메카닉으로 운영하고, 그 안에 나타나는 Monster를 다르게 생성하는 것으로 구상했다.

3) 게임 저장하기

Json 파일로 저장하였다.

static void SaveJson(Warrior character, List<Item> shoplist)
{
    Console.Clear();
    TextColor("[저장하기]\n", ConsoleColor.Yellow);

    string filepath = "character.json";
    string json = JsonConvert.SerializeObject(character);
    File.WriteAllText(filepath, json);

    filepath = "shoplist.json";
    json = JsonConvert.SerializeObject(shoplist);
    File.WriteAllText(filepath, json);

    Console.WriteLine("\n저장했습니다.\n");
    CheckAction("0. 나가기\n", 0, 0);
    Village(character, shoplist);
}

static Warrior LoadCharacter()
{
    string json = File.ReadAllText("character.json");
    Warrior character = JsonConvert.DeserializeObject<Warrior>(json);

    return character;
}

static List<Item> LoadShop()
{
    string json = File.ReadAllText("shoplist.json");
    List<Item> shopList = JsonConvert.DeserializeObject<List<Item>>(json);

    return shopList;
}

SaveJson(), LoadCharacter(), LoadShop() 세 가지 메서드를 이용해 게임을 저장하고 불러올 수 있도록 하였다. 이 과정에서 기존의 Warrior 클래스에서 생성자의 jobint 형태고 가지고 있는 Jobstring 형태여서 Load에 오류가 나는 것을 수정하기 위해 Jobstring이 아닌 int 형태로 수정했다.

public int Job { get; set; }

4) HP 회복

Heal()

public void Heal()
{
    Health = maxHP;
    Console.WriteLine("체력을 모두 회복했습니다.");
}

Hospital()

static void Hospital(Warrior character, List<Item> shopItem)
{
    TextColor("\n[병원]", ConsoleColor.Yellow);
    Console.WriteLine("체력을 회복할 수 있습니다.\n");

    Console.WriteLine("현재 체력 : " + character.Health + " / " + character.maxHP);

    while(true)
    {
        Console.WriteLine("\n1. 회복하기");
        Console.WriteLine("0. 나가기\n");
        int cmd = CheckAction("어떤 행동을 하시겠습니까?", 0, 1);

        if (cmd == 0)
        {
            Village(character, shopItem);
        }
        else
        {
            if (character.Health == character.maxHP)
            {
                Console.WriteLine("이미 체력이 가득 찬 상태입니다.");
                continue;
            } else if(character.Gold >= 500)
            {
                character.Heal();
                character.Gold -= 500;
                Console.WriteLine("500 G 를 지불하였습니다.");
                continue;
            }
            else
            {
                Console.WriteLine("골드가 부족합니다.");
                continue;
            }
        }
    }
}

체력이 가득 차 있을 때는 회복할 수 없고, 돈이 부족할 때도 회복할 수 없도록 제어문을 제작해주었다.


이상이 지난주에 고치고자 했던 부분들이다. 물론 이외에도 중간중간 수정한 사안이 많다. 대표적으로 저장 기능을 새로 만들었기 때문에 저장파일이 있는 경우와 없는 경우를 나누었고 이에 따라 무조건적으로 나오던 캐릭터 생성 화면을 조건부 호출로 바꾸기 위해 함수로 따로 구현한 것이 있다. 하지만 이렇게 만들고 나서도 팀원들의 코드와 비교해보았을 때 상당히 미흡한 부분이 많이 보여 어떻게 더 수정해야할 지 고민이 크다.

어쨌든 이에 대한 코드는 github에 다시 수정되어 업로드했다.

🔗 : https://github.com/purangi/TextRPG




이외에 아마도 내일부터 시작할 것 같은 알고리즘 문제 시트의 두 문제를 미리 풀이하였다. 쉬운 문제더라도 내 풀이와 다른 사람들의 풀이를 짚어가면서 포스트를 작성해 볼 예정이다.

오늘 작성한 두 포스트이다.

📕

1) [프로그래머스] 배열 두 배 만들기

2) [프로그래머스] 배열 뒤집기

profile
개발 공부 블로그

0개의 댓글

관련 채용 정보