프로그래밍공부/C#기초

C# 프로그램 예제연습 - 텍스트게임만들기 - 07

Roslyn 2024. 1. 15. 16:43
반응형

자, 이번에는 이제 보스 몹에 대한 클래스를 만들어 봅시다.

Entities폴더에서 우클릭하여 [추가] - [클래스]를 선택합니다.

 

 

Vampire.cs 를 입력하고 다음과 같이 클래스를 작성합니다.

 

using ConsoleExample.Game01.Abstracts;

namespace ConsoleExample.Game01.Entities
{
    internal class Vampire : Monster, IMonsterAction
    {
        public Vampire()
        {
            this.Name = "뱀파이어";
            this.IsDead = false;
            this.Health = 400;
            this.Attack = 20;
            this.Guard = 5;
        }

        public string GetName()
        {
            return this.Name;
        }


        public bool IsStatus()
        {
            return this.IsDead;
        }

        public int GetHealth()
        {
            return this.Health;
        }

        public Damage AttackOfBats()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack * 3;
            damage.Chance = 20;
            return damage;
        }

        public Damage AttackTeeth()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack * 4;
            damage.Chance = 10;
            return damage;
        }

        public Damage ShadowStepping()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack * 2;
            damage.Chance = 30;
            return damage;
        }

        public Damage NormalAttack()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack;
            damage.Chance = 100;
            return damage;
        }

        public Damage GetDamage()
        {
            Random random = new Random();
            int randomNumber = random.Next(4);
            switch (randomNumber)
            {
                case 0:
                    Console.WriteLine("박쥐들의 습격!");
                    return AttackOfBats();
                case 1:
                    Console.WriteLine("날카로운 이빨공격!");
                    return AttackTeeth();
                case 2:
                    Console.WriteLine("그립자밟기!");
                    return ShadowStepping();
                default:
                    Console.WriteLine("공격!");
                    return NormalAttack();
            }
        }

        public void SetDamage(Damage damage)
        {
            Random random = new Random();
            int randomNumber = random.Next(100);
            if (randomNumber <= damage.Chance)
            {
                Console.WriteLine("적중했습니다!");
                this.Health = this.Health - (damage.Attack - this.Guard);
                if (this.Health <= 0)
                {
                    Console.WriteLine("몬스터가 소멸됩니다.");
                    this.IsDead = true;
                    this.Health = 0;
                }
            }
            else
            {
                Console.WriteLine("공격이 빗나갔습니다.");
            }
        }
    }
}

 

기존에는 if문을 이용해, 랜덤수가 0이냐 1이냐로 나뉘었었지만, 보스는 총 3개의 스킬을 가지고 있기에, switch 문을 이용해 분기했습니다.

결과값을 바로 return 하므로 별도의 break 구문은 필요없습니다.

보스는 그냥 공격을 주고 받으면 재미가 없으니까, 공격을 할때마다 메시지를 출력하도록 했습니다.

 

이렇게 해서 보스몹에 대한 설정도 마쳤습니다.

이제 동일한 로직을 사용자에게도 적용해야 합니다.

다만, 사용자는 공격방식을 랜덤하게 하는 것이 아니라, 선택하여 공격하게 할 것입니다.

 

namespace ConsoleExample.Game01.Entities
{
    internal class User
    {
        public bool IsDead { get; set; }

        public string Name { get; set; }

        public int Health { get; set; }

        public int Attack { get; set; }

        public int Guard { get; set; }

        public int Level { get; set; }


        public User()
        {
            this.IsDead = false;
            this.Name = string.Empty;
            this.Health = 100;
            this.Attack = 10;
            this.Guard = 1;
            this.Level = 1;
        }

        public Damage MagicFireball()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack * 3;
            damage.Chance = 10;
            return damage;
        }

        public Damage MagicArrow()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack + 5;
            damage.Chance = 60;
            return damage;
        }

        public Damage StunAttack()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack * 2;
            damage.Chance = 40;
            return damage;
        }

        public Damage NormalAttack()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack;
            damage.Chance = 100;
            return damage;
        }

        public Damage GetDamage(string num)
        {
            switch (num)
            {
                case "0":
                    Console.WriteLine("파이어볼!");
                    return MagicFireball();
                case "1":
                    Console.WriteLine("매직애로우!");
                    return MagicArrow();
                case "2":
                    Console.WriteLine("스턴공격!");
                    return StunAttack();
                default:
                    Console.WriteLine("내검을 받아라!");
                    return NormalAttack();
            }
        }

        public void SetDamage(Damage damage)
        {
            Random random = new Random();
            int randomNumber = random.Next(100);
            if (randomNumber <= damage.Chance)
            {
                this.Health = this.Health - (damage.Attack - this.Guard);
                if (this.Health < 0)
                {
                    this.IsDead = true;
                    this.Health = 0;
                }
            }
            else
            {
                Console.WriteLine("공격을 회피했습니다.");
            }
        }
    }
}

 

 

마찬가지로 GetDamage와 SetDamage를 작성했지만, 다른 점은 GetDamage가 파라미터로 문자열 숫자값을 받는다는 겁니다.

숫자에 따라 사용하는 스킬 또는 평타 공격으로 나뉩니다.

 

파이어볼 마법은 강력한 데미지를 주지만 확률이 낮습니다.  매직애로우는 데미지는 적지만 높은 적중률을 보입니다.

3가지 스킬과 평타 공격으로 몹들을 상대하면 됩니다.

 

이제 한가지 함수를 더 만들어 줍니다.  바로 레벨업 함수입니다.

 

public void LevelUp()
{
    this.Level += 1;
    this.Health = 100 + (this.Level * 10);
    this.Attack += 1;
    this.Guard = ((this.Level % 2) == 0) ? this.Guard + 1 : this.Guard;
}

 

몹을 잡을 때마다 이 함수를 호출해 줍니다.

레벨이 오르면서 체력도 같이 오르고, 공격력도 증가합니다.

여기서 유심히 봐야할 부분은 마지막입니다.

여기서 사용된 표현식은 이른바 "삼항연산자"라고 불리우는 표현방법입니다.

 

this.Guard의 값은 다음에 오는 괄호 안에 조건식이 참(True)이면 물음표(?) 뒤에 첫번째 값이 적용되고, 거짓(false)이면 콜론(:) 뒤에 값이 적용됩니다.

또한 숫자 연산에 퍼센트(%)기호가 보일텐데, 이건 나머지를 구하는 연산자 입니다.

 

현재 레벨을 2로 나누어서 0으로 떨어지면, 즉 현재 레벨이 짝수라면, 방어력에 1을 더해주고, 그렇지 않다면(홀수라면) 현재 방어력을 유지하라고 하는 겁니다.

방어력을 공격력처럼 매번 올려주게 되면 방어력이 너무 올라가 버리므로, 레벨업 두번 당 1씩만 증가시키기 위한 코드입니다.

이런식에 코드는 게임쪽에서 쉬이 볼 수 있는 코드라고 할 수 있습니다.

 

완성된 User.cs 파일의 내용은 다음과 같습니다.

** 마찬가지로 특정 상황마다 메시지를 출력하도록 했습니다. **

namespace ConsoleExample.Game01.Entities
{
    internal class User
    {
        public bool IsDead { get; set; }

        public string Name { get; set; }

        public int Health { get; set; }

        public int Attack { get; set; }

        public int Guard { get; set; }

        public int Level { get; set; }


        public User()
        {
            this.IsDead = false;
            this.Name = string.Empty;
            this.Health = 100;
            this.Attack = 10;
            this.Guard = 1;
            this.Level = 1;
        }

        public Damage MagicFireball()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack * 3;
            damage.Chance = 10;
            return damage;
        }

        public Damage MagicArrow()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack + 5;
            damage.Chance = 60;
            return damage;
        }

        public Damage StunAttack()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack * 2;
            damage.Chance = 40;
            return damage;
        }

        public Damage NormalAttack()
        {
            Damage damage = new Damage();
            damage.Attack = this.Attack;
            damage.Chance = 100;
            return damage;
        }

        public Damage GetDamage(string num)
        {
            switch (num)
            {
                case "0":
                    Console.WriteLine("파이어볼!");
                    return MagicFireball();
                case "1":
                    Console.WriteLine("매직애로우!");
                    return MagicArrow();
                case "2":
                    Console.WriteLine("스턴공격!");
                    return StunAttack();
                default:
                    Console.WriteLine("내검을 받아라!");
                    return NormalAttack();
            }
        }

        public void SetDamage(Damage damage)
        {
            Random random = new Random();
            int randomNumber = random.Next(100);
            if (randomNumber <= damage.Chance)
            {
                Console.WriteLine("가격당했습니다!");
                this.Health = this.Health - (damage.Attack - this.Guard);
                if (this.Health < 0)
                {
                    Console.WriteLine("\"으윽....\"  당신은 쓰러집니다.");
                    this.IsDead = true;
                    this.Health = 0;
                }
            }
            else
            {
                Console.WriteLine("공격을 회피했습니다.");
            }
        }

        public void LevelUp()
        {
            Console.WriteLine("레벨업했습니다!");
            this.Level += 1;
            this.Health = 100 + (this.Level * 10);
            this.Attack += 1;
            this.Guard = ((this.Level % 2) == 0) ? this.Guard + 1 : this.Guard;
            Console.WriteLine("=========================================================");
            Console.WriteLine($" 당신의 레벨은 {this.Level} 입니다");
            Console.WriteLine($" 공격력 : {this.Attack} / 방어력 {this.Guard} / 체력 : {this.Health}");
            Console.WriteLine("=========================================================");
        }
    }
}

 

다음 시간에는 이제 본격적인 동굴 탐험을 시작해 보도록 하겠습니다.

 

 

 

 

반응형