먼지나는 블로그

객체지향 본문

내맘대로 공부/c#

객체지향

고먼지 2021. 6. 15. 22:33
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)
                    continue;
                
                //캐릭터 생성
                Player player;

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

                EnterGame(ref player);
            }
        }
    }
}

 

앞서 작성했던 TextRPG 코드

함수 기반으로 이루어진 코드로 간단한 프로그램을

코딩할 땐 직관적으로 볼 수 있는 장점이 있지만

프로그램이 커질수록 유지보수가 힘든 큰 단점이 있다

 

또한 함수의 호출 순서가 바뀔 경우 로직이

꼬이게 되는 상황이 발생할 수 있다

 

따라서 오늘은 함수 기반이 아닌

객체지향 코드를 작성해보고자 한다

 

1. 클래스와 구조체

using System;

namespace CSharp
{
    class Knight
    {
        public int hp;
        public int attack;
        public void Move()
        {
            Console.WriteLine("Knight Move");
        }
        public void Attack()
        {
            Console.WriteLine("Knight Attack");
        }
    }

    struct Mage
    {
        public int hp;
        public int attack;
        public void Move()
        {
            Console.WriteLine("Mage Move");
        }
        public void Attack()
        {
            Console.WriteLine("Mage Attack");
        }
    }

    class Program
    {
        //객체(OOP Object Oriented Programming

        //knight

        //속성 : hp, attack, pos
        //기능 : Move, Attack, Die
       
        static void Main(string[] args)
        {
            Knight knight = new Knight();
            knight.hp = 100;
            knight.attack = 10;

            knight.Move();
            knight.Attack();
           
        }
    }
}

 

 

같은 내용이 들어가있는 Knight클래스와

Mage구조체는 가장 큰 차이점이 존재한다

 

바로 Knight 클래스의 경우 참조하는 반면

Mage 구조체는 그저 카피한 값에 불과하다

 

using System;

namespace CSharp
{
    //객체(OOP Object Oriented Programming

    //knight

    //속성 : hp, attack, pos
    //기능 : Move, Attack, Die
    //ref 참조
    class Knight
    {
        public int hp;
        public int attack;
        public void Move()
        {
            Console.WriteLine("Knight Move");
        }
        public void Attack()
        {
            Console.WriteLine("Knight Attack");
        }
    }
    
	// 카피
    struct Mage
    {
        public int hp;
        public int attack;
        public void Move()
        {
            Console.WriteLine("Mage Move");
        }
        public void Attack()
        {
            Console.WriteLine("Mage Attack");
        }
    }

    class Program
    {
        static void KillMage(Mage mage)
        {
            mage.hp = 0;
        }

        static void KillKnight(Knight knight)
        {
            knight.hp = 0;
        }

        static void Main(string[] args)
        {
            Mage mage;
            mage.hp = 100;
            mage.attack = 50;
            KillMage(mage);

            Knight knight = new Knight();
            knight.hp = 100;
            knight.attack = 10;
            KillKnight(knight);
           
        }
    }
}

 

따라서 위의 코드를 디버깅을 통해

각 knight와 mage의 hp값이 mage는 그대로 100

knight는 0의 값이 저장된다는 것을 볼 수 있다

 

using System;

namespace CSharp
{
    //객체(OOP Object Oriented Programming

    //knight

    //속성 : hp, attack, pos
    //기능 : Move, Attack, Die
    class Knight
    {
        public int hp;
        public int attack;
        public void Move()
        {
            Console.WriteLine("Knight Move");
        }
        public void Attack()
        {
            Console.WriteLine("Knight Attack");
        }
    }

    struct Mage
    {
        public int hp;
        public int attack;
        public void Move()
        {
            Console.WriteLine("Mage Move");
        }
        public void Attack()
        {
            Console.WriteLine("Mage Attack");
        }
    }

    class Program
    {
        static void KillMage(Mage mage)
        {
            mage.hp = 0;
        }

        static void KillKnight(Knight knight)
        {
            knight.hp = 0;
        }

        static void Main(string[] args)
        {
            Mage mage;
            mage.hp = 100;
            mage.attack = 50;
            KillMage(mage);

            Mage mage2 = mage;
            mage.hp = 0;

            Knight knight = new Knight();
            knight.hp = 100;
            knight.attack = 10;
            KillKnight(knight);

            Knight knight2 = new Knight();
            knight2.hp = 100;
            knight2.attack = 10;
        }
    }
}

 

mage와 mage2 knight와 knight2는

서로 다른 존재로 인식된다

 

하지만 매번 new로 생성하기엔 불편한 부분이

있기 때문에 이런 점을 해결하기 위한 것이

바로 딥카피를 이용하는 것이다

 

using System;

namespace CSharp
{
    //객체(OOP Object Oriented Programming

    //knight

    //속성 : hp, attack, pos
    //기능 : Move, Attack, Die
    class Knight
    {
        public int hp;
        public int attack;
        public Knight Clone()
        {
            Knight knight2 = new Knight();
            knight2.hp = hp;
            knight2.attack = attack;

            return knight2;
        }
        public void Move()
        {
            Console.WriteLine("Knight Move");
        }
        public void Attack()
        {
            Console.WriteLine("Knight Attack");
        }
    }

    struct Mage
    {
        public int hp;
        public int attack;
        public void Move()
        {
            Console.WriteLine("Mage Move");
        }
        public void Attack()
        {
            Console.WriteLine("Mage Attack");
        }
    }

    class Program
    {
        static void KillMage(Mage mage)
        {
            mage.hp = 0;
        }

        static void KillKnight(Knight knight)
        {
            knight.hp = 0;
        }

        static void Main(string[] args)
        {
            Mage mage;
            mage.hp = 100;
            mage.attack = 50;
            KillMage(mage);

            Mage mage2 = mage;
            mage.hp = 0;

            Knight knight = new Knight();
            knight.hp = 100;
            knight.attack = 10;
            KillKnight(knight);

           
        }
    }
}

 

knight2를 knight클래스 내에

클론 함수 내에서 생성하였다

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

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