TextRPG 2

선비Sunbei·2023년 1월 13일
0

C#

목록 보기
15/18
post-thumbnail
post-custom-banner

https://ansohxxn.github.io/c%20sharp/ch7/

해당 사이트를 기준으로 다음과 같이 정리하고, 사이트 코드를 참고하여 맘대로 만들었습니다.

상속 관계도
Creature
- Player
... - Knight
... - Archer
... - Mage
- Monster
... - Slime
... - Orc
... - Skeleton
프로퍼티
Creature
- hp
- attack
- CreatureType
CreatureType
- None
- Player
- Monster
PlayerType
- None
- Knight
- Archer
- Mage
MonsterType
- None
- Slime
- Orc
- Skeleton
Game 객체
- mode
- player
- monster
GameMode
- None
- Lobby
- Town
- Field

// Creature.cs

using System;

namespace TextRPG2
{
    enum CreatureType
    {
        None,
        Player,
        Monster
    }

    abstract class Creature
    {
        private int HP;

        public int hp
        {
            get
            {
                return HP;
            }
            set
            {
                if (value <= 0)
                    HP = 0;
                else
                    HP = value;
            }
        }
        public int attack { get; protected set; }
        public CreatureType cType { get; protected set; } = CreatureType.None;
        static protected Random r;

        public Creature(CreatureType cType){
            this.cType = cType;
            r = new Random();
        }

        protected void setInfo(int hp, int attack)
        {
            this.hp = hp;
            this.attack = attack;
        }
    }
}

hp에 대한 값을 설정할 때 프로퍼티 관련 에러가 발생했었다.

자동 프로퍼티가 아닌 프로퍼티를 만들 시에는 HP와 같이 변수를 따로 선언해야 한다. 만약 선언하지 않고, hp 프로퍼티 안에서 hp 변수를 사용할 경우 무한루프 돌면서 stack overflow가 뜬다.

프로퍼티에서 set을 할 때 if(value<=0) HP=0; 써놓고 왜 안되나 했었다. 이는 else HP=value;를 안해서 였는데 까먹지 말고 HP=value를 써야 한다!

// Monster.cs


namespace TextRPG2
{
    enum MonsterType
    {
        None,Slime,Orc,Skeleton
    }

    abstract class Monster : Creature
    {
        public MonsterType mType { get; protected set; } = MonsterType.None;

        public Monster(MonsterType mType) : base(CreatureType.Monster)
        {
            this.mType = mType;
        }
    }

    class Slime : Monster
    {
        public Slime() : base(MonsterType.Slime)
        {
            setInfo(15 + r.Next(0, 15), 2 + r.Next(0, 3));
        }
    }
    class Orc : Monster
    {
        public Orc() : base(MonsterType.Orc)
        {
            setInfo(30 + r.Next(0, 30), 10 + r.Next(0, 15));
        }
    }
    class Skeleton : Monster
    {
        public Skeleton() : base(MonsterType.Skeleton)
        {
            setInfo(8 + r.Next(0, 3), 5 + r.Next(0, 10));
        }
    }
}
// Player.cs

namespace TextRPG2
{
    enum PlayerType
    {
        None,Knight,Archer,Mage
    }
    abstract class Player : Creature
    {
        public PlayerType pType { get; protected set; } = PlayerType.None;
        public Player(PlayerType pType) : base(CreatureType.Player) 
        {
            this.pType = pType;
        }
    }

    class Knight : Player
    {
        public Knight() : base(PlayerType.Knight)
        {
            setInfo(40 + r.Next(0, 20), 3 + r.Next(0, 5));
        }
    }    
    class Archer : Player
    {
        public Archer() : base(PlayerType.Archer)
        {
        
            setInfo(20 + r.Next(0, 15),/ 6 + r.Next(0, 8));
        }
    }    
    class Mage : Player
    {
        public Mage() : base(PlayerType.Mage)
        {
            setInfo(8 + r.Next(0, 10), 10 + r.Next(0, 20));
        }
    }
}
// Game.cs

using System;

namespace TextRPG2
{
    enum GameMode{
        None,
        Lobby,
        Town,
        Field
    }
    class Game
    {
        protected Player player;
        protected Monster monster;
        protected GameMode mode;
        static protected Random r = new Random();
        string? msg;


        protected void PrintPlayerInfo()
        {
            Console.WriteLine("-------------------------------------");
            Console.WriteLine("플레이어 클래스 : " + player.pType);
            Console.WriteLine("플레이어 공격력 : " + player.attack);
            Console.WriteLine("플레이어 체력 : " + player.hp);
            Console.WriteLine("-------------------------------------");
        }


        public Game()
        {
            mode = GameMode.Lobby;
            Console.WriteLine("게임에 접속했습니다.");
            msg = null;
            Process();
        }

        protected void CreateMonster()
        {
            switch (r.Next(0,3))
            {
                case 0:
                    monster = new Orc();
                    break;
                case 1:
                    monster = new Skeleton();
                    break;
                case 2:
                    monster = new Slime();
                    break;
            }
        }

        protected void Fight()
        {
            while (true)
            {
                switch (r.Next(0, 2))
                {
                    case 0:
                        Console.WriteLine("Player가 " + monster.mType + "를 공격했습니다.");
                        monster.hp -= player.attack;
                        break;
                    case 1:
                        Console.WriteLine(monster.mType + "가 Player를 공격했습니다.");
                        player.hp -= monster.attack;
                        break;
                }
                Console.WriteLine("Player 체력 : " + player.hp + ", Monster 체력 : " + monster.hp);
                Console.ReadKey();
                if (player.hp <= 0)
                {
                    Console.WriteLine("GameOver");
                    Environment.Exit(0);
                }
                if (monster.hp <= 0)
                {
                    msg = "전투에서 승리했습니다.";
                    mode = GameMode.Town;
                    return;
                }
            }
        }

        protected void EnterField()
        {
            CreateMonster();
            PrintPlayerInfo();
            Console.WriteLine("몬스터 " + monster.mType + "을 만났습니다.");
            Console.WriteLine("어떤 행동을 하시겠습니까?");
            Console.WriteLine("[1] 몬스터와 전투");
            Console.WriteLine("[2] 일정 확률로 마을로 도망");
            string sel;
            while (true)
            {
                Console.Write("선택 : ");
                sel = Console.ReadLine();
                switch (sel)
                {
                    case "1":
                        Fight();
                        return;

                    case "2":
                        Console.Clear();
                        if (r.Next(0, 10) <= 6)
                        {
                            msg = "도망에 성공했습니다.";
                            mode = GameMode.Town;
                            return;
                        }else
                        {
                            Console.WriteLine("도망에 실패했습니다.");
                            Console.WriteLine("몬스터에게 데미지를 입었습니다.");
                            player.hp -= monster.attack;
                            if (player.hp <= 0)
                            {
                                Console.WriteLine("GameOver");
                                Environment.Exit(0);
                            }
                            PrintPlayerInfo();
                            Console.WriteLine("어떤 행동을 하시겠습니까?");
                            Console.WriteLine("[1] 몬스터와 전투");
                            Console.WriteLine("[2] 일정 확률로 마을로 도망");
                            break;
                        }
                }
            }
        }
        protected void EnterTown()
        {
            PrintPlayerInfo();
            Console.WriteLine("어떤 행동을 하시겠습니까?");
            Console.WriteLine("[1] 필드로 접속");
            Console.WriteLine("[2] 로비로 이동");
            string sel;
            while (true)
            {
                Console.Write("선택 : ");
                sel = Console.ReadLine();
                switch (sel)
                {
                    case "1":
                        mode = GameMode.Field;
                        msg = "필드로 이동했습니다.";
                        return;
                    case "2":
                        mode = GameMode.Lobby;
                        msg = "로비로 이동했습니다.";
                        return;
                }
            }
        }

        protected void EnterLobby()
        {
            Console.WriteLine("직업을 선택해주세요.");
            Console.WriteLine("[1] Knight");
            Console.WriteLine("[2] Archer");
            Console.WriteLine("[3] Mage");

            string sel;
            while (true)
            {
                Console.Write("선택 : ");
                sel = Console.ReadLine();
                switch (sel)
                {
                    case "1":
                        player = new Knight();
                        Console.Clear();
                        Console.WriteLine("기사를 선택했습니다.");
                        mode = GameMode.Town;
                        return;
                    case "2":
                        player = new Archer();
                        Console.Clear();
                        Console.WriteLine("궁수를 선택했습니다.");
                        mode = GameMode.Town;
                        return;
                    case "3":
                        player = new Mage();
                        Console.Clear();
                        Console.WriteLine("마법사를 선택했습니다.");
                        mode = GameMode.Town;
                        return;
                }
            }
        }

        private void Process()
        {
            while (true)
            {
                Console.Clear();
                if(msg != null)
                {
                    Console.WriteLine(msg);
                    msg = null;
                }
                
                switch (mode)
                {
                    case GameMode.Field:
                        EnterField();
                        break;

                    case GameMode.Lobby:
                        EnterLobby();
                        break;

                    case GameMode.Town:
                        EnterTown();
                        break; 
                }
            }
        }

    }
}

계속 모드를 설정하고서 return을 안 해서 수정을 여러번 했었다.

string msg는 모드n에서 모드m으로 넘어올 때, 메시지를 전하고 싶은 경우를 위해서 사용했다.

(Console.Clear()로 이전에 콘솔에 적은 것은 다 사라지기 때문에)

// Program.cs


namespace TextRPG2
{
    class Program
    {
        static void Main(string[] args)
        {
            Game game = new Game();
        }
    }
}
post-custom-banner

0개의 댓글