오늘는 스파르타 코딩 클럽 unity 게임 개발 과정 12일차(4주차 과제 인터페이스와 Func과 Action)

2023. 11. 15. 00:17스파르타코딩클럽 게임개발

반응형

C#에서 인터페이스 구현하기

코딩 초보자를 위한 C#에서 인터페이스를 구현하는 방법을 알아보겠습니다. 인터페이스는 클래스가 가져야 하는 일련의 동작을 정의하며, 여러 클래스에서 공통적으로 사용되는 메서드, 속성, 이벤트 등을 표준화하는 데 도움이 됩니다.

인터페이스란?

인터페이스는 클래스에서 구현해야 하는 일련의 규칙을 정의하는 일종의 계약(Contract)입니다. 클래스가 특정 인터페이스를 구현하면, 해당 인터페이스에서 정의한 모든 멤버를 반드시 구현해야 합니다.

인터페이스 선언하기

인터페이스는 interface 키워드를 사용하여 선언합니다. 예를 들어, 간단한 로깅 기능을 가진 인터페이스를 만들어보겠습니다.

public interface ILogger
{
    void Log(string message);
}

위의 예제에서 ILogger 인터페이스는 Log라는 메서드를 정의하고 있습니다. 클래스가 이 인터페이스를 구현하려면 Log 메서드를 반드시 포함해야 합니다.

클래스에서 인터페이스 구현하기

클래스에서 인터페이스를 구현하려면 class 키워드 뒤에 콜론(:)을 사용하고, 구현하려는 인터페이스의 이름을 적어줍니다. 구현할 인터페이스가 여러 개라면 콤마로 구분합니다.

public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine($"로그: {message}");
    }
}

위의 예제에서 ConsoleLogger 클래스는 ILogger 인터페이스를 구현하고 있습니다. 따라서 Log 메서드를 반드시 포함하고 있어야 합니다.

인터페이스 활용하기

이제 구현한 인터페이스를 활용해봅시다. 다음은 간단한 예제입니다.

class Program
{
    static void Main()
    {
        ILogger logger = new ConsoleLogger();
        logger.Log("안녕하세요, 인터페이스!");

        // 다른 로깅 클래스를 만들어도 인터페이스를 통해 사용 가능
        // ILogger fileLogger = new FileLogger();
        // fileLogger.Log("파일에 로그 기록");
    }
}

위의 코드에서 ConsoleLogger 클래스는 ILogger 인터페이스를 구현하므로 ILogger 타입으로 선언된 변수에 할당할 수 있습니다. 이를 통해 다양한 로깅 클래스를 인터페이스를 통해 통일된 방식으로 사용할 수 있습니다.

이제 저 같은 코딩 초보자도 간단한 인터페이스 구현에 대한 이해를 갖게 되었을 것입니다. 인터페이스는 코드의 유연성을 높이고, 코드 재사용성을 증가시키는 데에 큰 도움이 됩니다.

Func과 Action 구현하기

C#에서 FuncAction은 대리자(delegate)의 특수한 형태로, 각각 값을 반환하는 메서드와 값을 반환하지 않는 메서드에 대한 대리자를 나타냅니다.

Func

Func은 값을 반환하는 메서드에 대한 대리자입니다. 여러 개의 입력 매개변수를 받을 수 있으며, 마지막 제네릭 매개변수는 반환 타입입니다.

// 하나의 입력 매개변수를 받아 정수를 반환하는 Func
Func<int, int> square = x => x * x;

// 두 개의 입력 매개변수를 받아 합을 반환하는 Func
Func<int, int, int> add = (a, b) => a + b;

// 아무런 입력 매개변수 없이 문자열을 반환하는 Func
Func<string> greet = () => "Hello, World!";

Action

Action은 값을 반환하지 않는 메서드에 대한 대리자입니다. 마찬가지로 여러 개의 입력 매개변수를 받을 수 있습니다.

// 하나의 입력 매개변수를 받는 Action
Action<int> printNumber = x => Console.WriteLine(x);

// 두 개의 입력 매개변수를 받는 Action
Action<int, int> printSum = (a, b) => Console.WriteLine(a + b);

// 아무런 입력 매개변수 없이 동작하는 Action
Action greetAction = () => Console.WriteLine("Hello, World!");

사용 예제

class Program
{
    static void Main()
    {
        // Func 사용 예제
        Func<int, int, int> addFunc = (a, b) => a + b;
        int result = addFunc(3, 7); // 결과: 10

        // Action 사용 예제
        Action<int, int> printSumAction = (a, b) => Console.WriteLine(a + b);
        printSumAction(5, 8); // 출력: 13
    }
}

FuncAction은 더 간결하고 표현력 있는 코드를 작성할 수 있도록 도와주는 유용한 대리자 형식입니다.

 

 

이제 상단의 두가지를 활용해서 4주차 과정인 전투를 구현해보겠습니다.

# 전투 스테이지를 나타내는 클래스

```csharp
// 전투 스테이지를 나타내는 클래스
public class Stage
{
    // 전투에 참여하는 캐릭터들을 생성
    Warrior warrior = new Warrior
    {
        Name = "킹왕짱짱맨",
        Attack = 75,
        Health = 200,
        IsDead = true,
        Speed = 10
    };
    Goblin goblin = new Goblin
    {
        Name = "고블린 대마왕",
        Attack = 20,
        Health = 200,
        IsDead = true,
        Speed = 5
    };
    Dragon dragon = new Dragon
    {
        Name = "마룡 카시라스",
        Attack = 50,
        Health = 300,
        IsDead = true,
        Speed = 20
    };

    // 고블린과의 전투를 처리하는 메서드
    private void StoreGoblin()
    {
        Console.WriteLine("앗! 고블린을 만났다!");

        // 콜백 설정
        warrior.SetChangedCallback(health =>
        {
            if (health <= 0)
            {
                Console.WriteLine("플레이어 사망!");
                warrior.IsDead = false;
            }
        });
        goblin.SetChangedCallback(health =>
        {
            if (health <= 0)
            {
                Console.WriteLine("고블린 사망!");
                goblin.IsDead = false;
            }
        });

        // 전투 진행
        while (true)
        {
            if (!warrior.IsDead || !goblin.IsDead) { break; }

            // 용사가 고블린을 공격
            Console.WriteLine("용사가 고블린을 공격했다!");
            goblin.TakeDamage(warrior.Attack);
            Thread.Sleep(1000);
            Console.WriteLine($"용사의 공격으로 고블린은 {warrior.Attack}만큼 피해를 입었다!");
            Console.WriteLine($"고블린의 피는 {goblin.Health} 남았다!");
            Thread.Sleep(1000);

            if (!warrior.IsDead || !goblin.IsDead) { break; }

            // 고블린이 용사를 공격
            Console.WriteLine("고블린이 용사를 공격했다!");
            warrior.TakeDamage(goblin.Attack);
            Thread.Sleep(1000);
            Console.WriteLine($"고블린의 공격으로 용사는 {goblin.Attack}만큼 피해를 입었다!");
            Console.WriteLine($"용사의 피는 {warrior.Health} 남았다!");
            Thread.Sleep(2000);
        }
    }

    // 드래곤과의 전투를 처리하는 메서드
    private void StoreDragon()
    {
        Console.WriteLine("앗! 드래곤을 만났다!");

        // 콜백 설정
        warrior.SetChangedCallback(health =>
        {
            if (health <= 0)
            {
                Console.WriteLine("플레이어 사망!");
                warrior.IsDead = false;
            }
        });
        dragon.SetChangedCallback(health =>
        {
            if (health <= 0)
            {
                Console.WriteLine("드래곤 사망!");
                dragon.IsDead = false;
            }
        });

        // 전투 진행
        while (true)
        {
            if (!warrior.IsDead || !dragon.IsDead) { break; }

            // 용사가 드래곤을 공격
            Console.WriteLine("용사가 드래곤을 공격했다!");
            dragon.TakeDamage(warrior.Attack);
            Thread.Sleep(1000);
            Console.WriteLine($"용사의 공격으로 드래곤은 {warrior.Attack}만큼 피해를 입었다!");
            Console.WriteLine($"드래곤의 피는 {dragon.Health} 남았다!");
            Thread.Sleep(1000);

            if (!warrior.IsDead || !dragon.IsDead) { break; }

            // 드래곤이 용사를 공격
            Console.WriteLine("드래곤이 용사를 공격했다!");
            warrior.TakeDamage(dragon.Attack);
            Thread.Sleep(1000);
            Console.WriteLine($"드래곤의 공격으로 용사는 {dragon.Attack}만큼 피해를 입었다!");
            Console.WriteLine($"용사의 피는 {warrior.Health} 남았다!");
            Thread.Sleep(2000);
        }
    }

    // 게임 시작
    public void Start()
    {
        // 고블린과의 전투
        StoreGoblin();
        if

 (!warrior.IsDead)
        {
            Console.WriteLine("아 죽었다!");
            return;
        }

        // 휴식 후 드래곤과의 전투
        Console.WriteLine();
        Console.WriteLine("용사는 휴식 했다.");
        warrior.Health = 100;
        Console.WriteLine();
        StoreDragon();
        if (!warrior.IsDead)
        {
            Console.WriteLine("퍄 망했다!");
        }
    }
}

몬스터를 나타내는 기본 클래스

// 몬스터를 나타내는 기본 클래스
public class Monster : ICharacter
{
    public Action<float> ChangedCallback;

    private float _health;
    public float Health
    {
        get { return _health; }
        set
        {
            _health = value;
            ChangedCallback?.Invoke(_health);
        }
    }

    public string Name { get; set; }
    public float Attack { get; set; }
    public float Speed { get; set; }
    public bool IsDead { get; set; }

    // 데미지를 입는 메서드
    public void TakeDamage(float damage)
    {
        Health -= damage;
    }

    // 콜백 설정 메서드
    public void SetChangedCallback(Action<float> callback)
    {
        ChangedCallback = callback;
    }
}

// 고블린 몬스터 클래스
public class Goblin : Monster
{
    public Goblin() { }
}

// 드래곤 몬스터 클래스
public class Dragon : Monster
{
    public Dragon() { }
}

전사 캐릭터를 나타내는 클래스

// 전사 캐릭터를 나타내는 클래스
public class Warrior : ICharacter
{
    public Action<float> ChangedCallback;

    private float _health;
    public float Health
    {
        get { return _health; }
        set
        {
            _health = value;
            ChangedCallback?.Invoke(_health);
        }
    }

    public float Attack { get; set; }
    public string Name { get; set; }
    public float Speed { get; set; }
    public bool IsDead { get; set; }

    // 데미지를 입는 메서드
    public void TakeDamage(float damage)
    {
        Health -= damage;
    }

    // 콜백 설정 메서드
    public void SetChangedCallback(Action<float> callback)
    {
        ChangedCallback = callback;
    }
}

캐릭터의 기본 인터페이스 및 아이템을 나타내는 인터페이스

// 캐릭터의 기본 인터페이스
public interface ICharacter
{
    string Name { get; }
    float Health { get; }
    float Attack { get; }
    float Speed { get; }
    bool IsDead { get; }
    void TakeDamage(float damage);
}

// 아이템을 나타내는 인터페이스
interface IItem
{
    string name { get; }
    void Use(Warrior warrior);
}

// 게임 내에서 상점을 나타내는 클래스
public class Reder
{
    Dictionary<string, List<string>> Stores = new Dictionary<string, List<string>>();
    List<string> store = new List<string>();
}

// 체력 회복 아이템 클래스
public class HealthPotion : IItem
{
    public string name { get; }

    // 아이템 사용 시 체력 회복
    void Use(Warrior warrior)
    {
        warrior.Health += 50;
    }
}

// 힘 강화 아이템 클래스
public class StrengthPotion : IItem
{
    public string name { get; }

    // 아이템 사용 시 공격력 증가
    void Use(Warrior warrior)
    {
        warrior.Attack += 20;
    }
}

// 메인 프로그램
internal class Program
{
    static void Main(string[] args)
    {
        // 게임 스테이지 시작
        Stage stage = new Stage();
        stage.Start();
    }
}

 

 

 

오늘의 느낀점!

인터페이스와 Func과 Action을 사용하면 좀 더 실용적인 코드를 짤 수 있다!

반응형