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#에서 Func
과 Action
은 대리자(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
}
}
Func
과 Action
은 더 간결하고 표현력 있는 코드를 작성할 수 있도록 도와주는 유용한 대리자 형식입니다.
이제 상단의 두가지를 활용해서 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을 사용하면 좀 더 실용적인 코드를 짤 수 있다!
'스파르타코딩클럽 게임개발' 카테고리의 다른 글
오늘는 스파르타 코딩 클럽 unity 게임 개발 과정 14일차(팀과제와 열거형 설명) (0) | 2023.11.17 |
---|---|
오늘는 스파르타 코딩 클럽 unity 게임 개발 과정 13일차(팀과제 준비와 싱글톤을 사용하는 법) (1) | 2023.11.16 |
오늘는 스파르타 코딩 클럽 unity 게임 개발 과정 11일차(개인과제 텍스트 RPG) (0) | 2023.11.14 |
엊그제는 스파르타 코딩 클럽 unity 게임 개발 과정 10일차(개인과제 텍스트 RPG) (0) | 2023.11.13 |
오늘은 스파르타 코딩 클럽 unity 게임 개발 과정 9일차(스네이크 게임 발표 준비하기) (5) | 2023.11.10 |