먼지나는 블로그

TextRPG 본문

내맘대로 공부/c#

TextRPG

고먼지 2021. 6. 15. 00:04

1. 직업 선택

using System;

namespace CSharp
{
    class Program
    {
        enum ClassType
        {
            None = 0,
            Knight = 1,
            Archer = 2,
            Mage = 3
        }
        static void Main(string[] args)
        {
            ClassType choice = ClassType.None;

            while(true)
            {
                Console.WriteLine("직업을 선택하세요!");
                Console.WriteLine("[1] 기사");
                Console.WriteLine("[2] 궁수");
                Console.WriteLine("[3] 마법사");

                string input = Console.ReadLine();
                switch (input)
                {
                    case "1":
                        choice = ClassType.Knight;
                        break;
                    case "2":
                        choice = ClassType.Archer;
                        break;
                    case "3":
                        choice = ClassType.Mage;
                        break;
                }

                if (choice != ClassType.None)
                    break;
            }
        }
    }
}

 

기본문법들을 이용해 구현해보기 시작한 textRPG

메인 함수안에 모든 동작을 구현할 수도 있겠지만 여러번 재사용하거나

확실한 구분을 위해 직업을 선택하는 과정을 따로 함수로 만들었다

 

using System;

namespace CSharp
{
    class Program
    {
        enum ClassType
        {
            None = 0,
            Knight = 1,
            Archer = 2,
            Mage = 3
        }
        static ClassType ChoiceClass()
        {
            Console.WriteLine("직업을 선택하세요!");
            Console.WriteLine("[1] 기사");
            Console.WriteLine("[2] 궁수");
            Console.WriteLine("[3] 마법사");

            ClassType choice = ClassType.None;
            string input = Console.ReadLine();
            switch (input)
            {
                case "1":
                    choice = ClassType.Knight;
                    break;
                case "2":
                    choice = ClassType.Archer;
                    break;
                case "3":
                    choice = ClassType.Mage;
                    break;
            }
            return choice;
        }
        static void Main(string[] args)
        {
            while(true)
            {
                ClassType choice = ChoiceClass();
                if (choice != ClassType.None)
                    break;
            }
        }
    }
}

 

ChoiceClass 함수를 따로 만들어 관리하기로 했지만

이때 메인에서 choice 변수의 값을 ref나 out으로 넘기지 않고

따로 한번 더 정의해주는 과정을 거쳤다

 

함수 안에서 변수를 선언할 경우 스택이 도는 범위

즉, 해당 함수 내에서만 사용되지만 return할 경우

결국 값은 제대로 받게 되는 상황이 이뤄진다

 

2. 플레이어 생성

using System;

namespace CSharp
{
    class Program
    {
        enum ClassType
        {
            None = 0,
            Knight = 1,
            Archer = 2,
            Mage = 3
        }
        static ClassType ChoiceClass()
        {
            Console.WriteLine("직업을 선택하세요!");
            Console.WriteLine("[1] 기사");
            Console.WriteLine("[2] 궁수");
            Console.WriteLine("[3] 마법사");

            ClassType choice = ClassType.None;
            string input = Console.ReadLine();
            switch (input)
            {
                case "1":
                    choice = ClassType.Knight;
                    break;
                case "2":
                    choice = ClassType.Archer;
                    break;
                case "3":
                    choice = ClassType.Mage;
                    break;
            }
            return choice;
        }
        static void CreatePlayer(ClassType choice, out int hp, out int attack)
        {
            hp = 0;
            attack = 0;
            switch (choice)
            {
                case ClassType.Knight:
                    hp = 100;
                    attack = 10;
                    break;
                case ClassType.Archer:
                    hp = 75;
                    attack = 12;
                    break;
                case ClassType.Mage:
                    hp = 50;
                    attack = 15;
                    break;
                default:
                    hp = 0;
                    attack = 0;
                    break;
            }
        }

        static void Main(string[] args)
        {
            while (true)
            {
                ClassType choice = ChoiceClass();
                if (choice != ClassType.None)
                {
                    //캐릭터 생성
                    int hp;
                    int attack;
                    CreatePlayer(choice, out hp, out attack);

                    //기사(100/10) 궁수(75/12) 법사(50/15)

                    Console.WriteLine($"Hp{hp} Attack{attack}");
                }
            }
        }
    }
}

 

CreatePlayer 함수를 새로 만들어 플레이어의 직업에 따른 hp와 공격력을 정해보자

메인에서 hp와 attack변수를 정의해준 후 out을 통해 넘겨보기로 했다

 

직업에 따라 값을 지정해야하기 때문에 choice값과 함께 나머지 변수들을 넘겨줬다

정상적으로 작동하긴 하지만 관리해야할 것들이 늘어날 때마다 추가해줘야하는

불편함을 갖고 있기 때문에 구조체를 통해 수정해주었다

 

using System;

namespace CSharp
{
    class Program
    {
        enum ClassType
        {
            None = 0,
            Knight = 1,
            Archer = 2,
            Mage = 3
        }
        struct Player
        {
            public int hp;
            public int attack;
        }
        static ClassType ChoiceClass()
        {
            Console.WriteLine("직업을 선택하세요!");
            Console.WriteLine("[1] 기사");
            Console.WriteLine("[2] 궁수");
            Console.WriteLine("[3] 마법사");

            ClassType choice = ClassType.None;
            string input = Console.ReadLine();
            switch (input)
            {
                case "1":
                    choice = ClassType.Knight;
                    break;
                case "2":
                    choice = ClassType.Archer;
                    break;
                case "3":
                    choice = ClassType.Mage;
                    break;
            }
            return choice;
        }
        static void CreatePlayer(ClassType choice, out Player player)
        {
            switch (choice)
            {
                case ClassType.Knight:
                    player.hp = 100;
                    player.attack = 10;
                    break;
                case ClassType.Archer:
                    player.hp = 75;
                    player.attack = 12;
                    break;
                case ClassType.Mage:
                    player.hp = 50;
                    player.attack = 15;
                    break;
                default:
                    player.hp = 0;
                    player.attack = 0;
                    break;
            }
        }

        static void Main(string[] args)
        {
            while (true)
            {
                ClassType choice = ChoiceClass();
                if (choice != ClassType.None)
                {
                    //캐릭터 생성
                    Player player;

                    CreatePlayer(choice, out player);

                    //기사(100/10) 궁수(75/12) 법사(50/15)

                    Console.WriteLine($"Hp{player.hp} Attack{player.attack}");
                }
            }
        }
    }
}

 

구조체 Struct Player를 통해 hp와 attack변수를 관리하게 된다

(변수를 지정할 경우 private이 기본적으로 붙기 때문에

외부에서 사용하게 될 경우 public을 붙여줘야 한다

 

구조체를 이용할 경우 변수 일일히 넘겨주는 것이 하닌

구조체 하나로 뭉뚱그려 세트로 관리할 수 있기 때문에 용이하다

 

3. 몬스터 생성

using System;

namespace CSharp
{
    class Program
    {
        enum ClassType
        {
            None = 0,
            Knight = 1,
            Archer = 2,
            Mage = 3
        }
        enum MonsterType
        {
            None = 0,
            Slime = 1,
            Orc = 2,
            Skeleton = 3
        }
        struct Monster
        {
            public int hp;
            public int attack;
        }
        struct Player
        {
            public int hp;
            public int attack;
        }
      

        static ClassType ChoiceClass()
        {
            Console.WriteLine("직업을 선택하세요!");
            Console.WriteLine("[1] 기사");
            Console.WriteLine("[2] 궁수");
            Console.WriteLine("[3] 마법사");

            ClassType choice = ClassType.None;
            string input = Console.ReadLine();
            switch (input)
            {
                case "1":
                    choice = ClassType.Knight;
                    break;
                case "2":
                    choice = ClassType.Archer;
                    break;
                case "3":
                    choice = ClassType.Mage;
                    break;
            }
            return choice;
        }

        static void CreatePlayer(ClassType choice, out Player player)
        {
            switch (choice)
            {
                case ClassType.Knight:
                    player.hp = 100;
                    player.attack = 10;
                    break;
                case ClassType.Archer:
                    player.hp = 75;
                    player.attack = 12;
                    break;
                case ClassType.Mage:
                    player.hp = 50;
                    player.attack = 15;
                    break;
                default:
                    player.hp = 0;
                    player.attack = 0;
                    break;
            }
        }
        static void CreateRandomMonster(out Monster monster)
        {
            //랜덤으로 1~3 몬스터 중 하나를 리스폰
            Random rand = new Random();
            int randMonter = rand.Next(1, 4);

            switch (randMonter)
            {
                case (int)MonsterType.Slime:
                    Console.WriteLine("슬라임이 스폰되었습니다!");
                    monster.hp = 20;
                    monster.attack = 2;
                    break;
                case (int)MonsterType.Orc:
                    Console.WriteLine("오크가 스폰되었습니다!");
                    monster.hp = 40;
                    monster.attack = 4;
                    break;
                case (int)MonsterType.Skeleton:
                    Console.WriteLine("스켈레톤이 스폰되었습니다!");
                    monster.hp = 30;
                    monster.attack = 3;
                    break;
                default:
                    monster.hp = 0;
                    monster.attack = 0;
                    break;
            }
        }

        static void EnterField()
        {
            Console.WriteLine("필드에 접속했습니다!");

            //몬스터 생성
            Monster monster;
            CreateRandomMonster(out monster);

            Console.WriteLine("[1] 전투모드로 돌입");
            Console.WriteLine("[2] 일정 확률로 마을로 도망");

            string input = Console.ReadLine();

            switch (input)
            {
                case "1":
                    break;
                case "2":
                    break;
            }

            //[1] 전투모드로 돌입
            //[2] 일정 확률로 마을로 도망
        }
        static void EnterGame()
        {
            while(true)
            { 
                Console.WriteLine("마을에 접속했습니다");
                Console.WriteLine("[1] 필드로 가기");
                Console.WriteLine("[2] 로비로 돌아가기");

                string input = Console.ReadLine();
                if (input == "1")
                {
                    EnterField();
                }
                else if (input == "2")
                {
                    break;
                }

                switch (input)
                {
                    case "1":
                        break;
                    case "2":
                        break;
                }
            }
        }
        static void Main(string[] args)
        {
            while (true)
            {
                ClassType choice = ChoiceClass();
                if (choice != ClassType.None)
                {
                    //캐릭터 생성
                    Player player;

                    CreatePlayer(choice, out player);

                    //기사(100/10) 궁수(75/12) 법사(50/15)
                    //Console.WriteLine($"Hp{player.hp} Attack{player.attack}");

                    EnterGame();
                }
            }
        }
    }
}

 

몬스터 생성 역시 플레이어를 생성할 때의 과정과 비슷하게

몬스터 타입을 저장하는 enum과 몬스터의 hp, attack변수를

관리하는 구조체를 만들어준다

 

그 후 세가지 종류의 몬스터중 랜덤으로 몬스터 한마리를

뽑기 위해 CreateRandomMonster 함수를 만들어주고 

Switch문을 통해 랜덤값과 동일한 값을 가진

MonsterType을 뽑아 몬스터를 생성해낸다 

 

4. 전투

using System;

namespace CSharp
{
    class Program
    {
        enum ClassType
        {
            None = 0,
            Knight = 1,
            Archer = 2,
            Mage = 3
        }
        enum MonsterType
        {
            None = 0,
            Slime = 1,
            Orc = 2,
            Skeleton = 3
        }
        struct Monster
        {
            public int hp;
            public int attack;
        }
        struct Player
        {
            public int hp;
            public int attack;
        }
      

        static ClassType ChoiceClass()
        {
            Console.WriteLine("직업을 선택하세요!");
            Console.WriteLine("[1] 기사");
            Console.WriteLine("[2] 궁수");
            Console.WriteLine("[3] 마법사");

            ClassType choice = ClassType.None;
            string input = Console.ReadLine();
            switch (input)
            {
                case "1":
                    choice = ClassType.Knight;
                    break;
                case "2":
                    choice = ClassType.Archer;
                    break;
                case "3":
                    choice = ClassType.Mage;
                    break;
            }
            return choice;
        }

        static void CreatePlayer(ClassType choice, out Player player)
        {
            switch (choice)
            {
                case ClassType.Knight:
                    player.hp = 100;
                    player.attack = 10;
                    break;
                case ClassType.Archer:
                    player.hp = 75;
                    player.attack = 12;
                    break;
                case ClassType.Mage:
                    player.hp = 50;
                    player.attack = 15;
                    break;
                default:
                    player.hp = 0;
                    player.attack = 0;
                    break;
            }
        }
        static void CreateRandomMonster(out Monster monster)
        {
            //랜덤으로 1~3 몬스터 중 하나를 리스폰
            Random rand = new Random();
            int randMonter = rand.Next(1, 4);

            switch (randMonter)
            {
                case (int)MonsterType.Slime:
                    Console.WriteLine("슬라임이 스폰되었습니다!");
                    monster.hp = 20;
                    monster.attack = 2;
                    break;
                case (int)MonsterType.Orc:
                    Console.WriteLine("오크가 스폰되었습니다!");
                    monster.hp = 40;
                    monster.attack = 4;
                    break;
                case (int)MonsterType.Skeleton:
                    Console.WriteLine("스켈레톤이 스폰되었습니다!");
                    monster.hp = 30;
                    monster.attack = 3;
                    break;
                default:
                    monster.hp = 0;
                    monster.attack = 0;
                    break;
            }
        }
        static void Fight(Player player, Monster monster)
        {
            while (true)
            {
                //플레이어가 몬스터 공격 
                monster.hp -= player.attack;
                if (monster.hp <= 0)
                {
                    Console.WriteLine("승리했습니다!");
                    break;
                }
                
                //몬스터 반격
                player.hp -= monster.attack;
                if (player.hp <= 0)
                {
                    Console.WriteLine("패배했습니다!");
                    break;
                }
            }
        }
        static void EnterField(Player player)
        {
            Console.WriteLine("필드에 접속했습니다!");

            //몬스터 생성
            Monster monster;
            CreateRandomMonster(out monster);

            Console.WriteLine("[1] 전투모드로 돌입");
            Console.WriteLine("[2] 일정 확률로 마을로 도망");

            string input = Console.ReadLine();

            switch (input)
            {
                case "1":
                    Fight(player, monster);
                    break;
                case "2":
                    Fight(player, monster);
                    break;
            }

            //[1] 전투모드로 돌입
            //[2] 일정 확률로 마을로 도망
        }
        static void EnterGame(Player player)
        {
            while(true)
            { 
                Console.WriteLine("마을에 접속했습니다");
                Console.WriteLine("[1] 필드로 가기");
                Console.WriteLine("[2] 로비로 돌아가기");

                string input = Console.ReadLine();
                if (input == "1")
                {
                    EnterField(player);
                }
                else if (input == "2")
                {
                    break;
                }

                switch (input)
                {
                    case "1":
                        break;
                    case "2":
                        break;
                }
            }
        }
        static void Main(string[] args)
        {
            while (true)
            {
                ClassType choice = ChoiceClass();
                if (choice != ClassType.None)
                {
                    //캐릭터 생성
                    Player player;

                    CreatePlayer(choice, out player);

                    //기사(100/10) 궁수(75/12) 법사(50/15)
                    //Console.WriteLine($"Hp{player.hp} Attack{player.attack}");

                    EnterGame(player);
                }
            }
        }
    }
}

 

전투를 하기 위해서는 player와 monster의 정보를 알아야되기 때문에

인자로 넘겨주는 선택을 했지만 이때 monster와 달리 player의 정보는

메인함수에서 사용되었기 때문에 main -> EnterGame -> EnterField

총 3번의 과정을 통해 Fight함수까지 넘겨주게 되었다

 

하지만 이때 사용된 플레이어의 정보는 그저 메인에서

카피된 값이기 때문에 Fight함수에서 사용된다한들

실제 player정보에는 영향을 끼치지 못하게 된다

 

때문에 이런 상황에서는 앞서 배웠던 ref를 통해

인자를 넘겨주게되면 해결된다

 

using System;

namespace CSharp
{
    class Program
    {
        enum ClassType
        {
            None = 0,
            Knight = 1,
            Archer = 2,
            Mage = 3
        }
        enum MonsterType
        {
            None = 0,
            Slime = 1,
            Orc = 2,
            Skeleton = 3
        }
        struct Monster
        {
            public int hp;
            public int attack;
        }
        struct Player
        {
            public int hp;
            public int attack;
        }
      

        static ClassType ChoiceClass()
        {
            Console.WriteLine("직업을 선택하세요!");
            Console.WriteLine("[1] 기사");
            Console.WriteLine("[2] 궁수");
            Console.WriteLine("[3] 마법사");

            ClassType choice = ClassType.None;
            string input = Console.ReadLine();
            switch (input)
            {
                case "1":
                    choice = ClassType.Knight;
                    break;
                case "2":
                    choice = ClassType.Archer;
                    break;
                case "3":
                    choice = ClassType.Mage;
                    break;
            }
            return choice;
        }

        static void CreatePlayer(ClassType choice, out Player player)
        {
            switch (choice)
            {
                case ClassType.Knight:
                    player.hp = 100;
                    player.attack = 10;
                    break;
                case ClassType.Archer:
                    player.hp = 75;
                    player.attack = 12;
                    break;
                case ClassType.Mage:
                    player.hp = 50;
                    player.attack = 15;
                    break;
                default:
                    player.hp = 0;
                    player.attack = 0;
                    break;
            }
        }
        static void CreateRandomMonster(out Monster monster)
        {
            //랜덤으로 1~3 몬스터 중 하나를 리스폰
            Random rand = new Random();
            int randMonter = rand.Next(1, 4);

            switch (randMonter)
            {
                case (int)MonsterType.Slime:
                    Console.WriteLine("슬라임이 스폰되었습니다!");
                    monster.hp = 20;
                    monster.attack = 2;
                    break;
                case (int)MonsterType.Orc:
                    Console.WriteLine("오크가 스폰되었습니다!");
                    monster.hp = 40;
                    monster.attack = 4;
                    break;
                case (int)MonsterType.Skeleton:
                    Console.WriteLine("스켈레톤이 스폰되었습니다!");
                    monster.hp = 30;
                    monster.attack = 3;
                    break;
                default:
                    monster.hp = 0;
                    monster.attack = 0;
                    break;
            }
        }
        static void Fight(ref Player player, ref Monster monster)
        {
            while (true)
            {
                //플레이어가 몬스터 공격 
                monster.hp -= player.attack;
                if (monster.hp <= 0)
                {
                    Console.WriteLine("승리했습니다!");
                    Console.WriteLine($"남은 체력 : {player.hp}");
                    break;
                }
                
                //몬스터 반격
                player.hp -= monster.attack;
                if (player.hp <= 0)
                {
                    Console.WriteLine("패배했습니다!");
                    Console.WriteLine($"남은 체력 : {player.hp}");
                    break;
                }
            }
        }
        static void EnterField(ref Player player)
        {
            while (true)
            {
                Console.WriteLine("필드에 접속했습니다!");

                //몬스터 생성
                Monster monster;
                CreateRandomMonster(out monster);

                Console.WriteLine("[1] 전투모드로 돌입");
                Console.WriteLine("[2] 일정 확률로 마을로 도망");

                string input = Console.ReadLine();

                if (input == "1")
                {
                    Fight(ref player, ref monster);
                }
                else if (input == "2")
                {
                    //33%
                    Random rand = new Random();
                    int randValue = rand.Next(0, 101);

                    if (randValue <= 33)
                    {
                        Console.WriteLine("도망치는데 성공했습니다!");
                        break;
                    }
                    else
                    {
                        Fight(ref player, ref monster);
                    }
                }
            }
            //[1] 전투모드로 돌입
            //[2] 일정 확률로 마을로 도망
        }
        static void EnterGame(ref Player player)
        {
            while(true)
            { 
                Console.WriteLine("마을에 접속했습니다");
                Console.WriteLine("[1] 필드로 가기");
                Console.WriteLine("[2] 로비로 돌아가기");

                string input = Console.ReadLine();
                if (input == "1")
                {
                    EnterField(ref player);
                }
                else if (input == "2")
                {
                    break;
                }

                switch (input)
                {
                    case "1":
                        break;
                    case "2":
                        break;
                }
            }
        }
        static void Main(string[] args)
        {
            while (true)
            {
                ClassType choice = ChoiceClass();
                if (choice != ClassType.None)
                {
                    //캐릭터 생성
                    Player player;

                    CreatePlayer(choice, out player);

                    //기사(100/10) 궁수(75/12) 법사(50/15)
                    //Console.WriteLine($"Hp{player.hp} Attack{player.attack}");

                    EnterGame(ref player);
                }
            }
        }
    }
}

 

이로써 기본적인 RPG게임을 간단하게나마 만들어보았다

'내맘대로 공부 > c#' 카테고리의 다른 글

객체지향  (0) 2021.06.15
ref와 out / 오버로딩  (0) 2021.06.07
코드 흐름제어  (0) 2021.06.02
데이터 갖고놀기  (0) 2021.06.02