Я изучал C # летом и теперь чувствую, что хочу сделать небольшой проект из того, что я сделал до сих пор. Я выбрал своего рода текстовую приключенческую игру.
Основная структура игры будет включать в себя несколько секторов (или комнат). При входе в комнату будет выведено описание и ряд действий, которые вы можете предпринять; способность исследовать, подбирать, использовать вещи в этой комнате; возможно, боевая система и т. д. и т. д. Сектор может быть связан с 4 другими секторами.
Во всяком случае, набрасывая идеи на бумаге о том, как разработать код для этого, я ломаю голову над структурой части моего кода.
Я выбрал класс игрока и класс «уровень», который представляет уровень / подземелье / область. Этот класс уровня будет состоять из нескольких взаимосвязанных «секторов». В любой момент времени игрок будет присутствовать в одном определенном секторе на уровне.
Так вот путаница:
Логически можно ожидать такой метод, как player.Move(Dir d)
Такой метод должен изменить поле «текущий сектор» в объекте уровня. Это означает, что класс Игрок должен знать о классе Уровень . Хммм.
И Level , возможно, придется манипулировать объектом Player (например, игрок входит в комнату, попал в засаду, теряет что-то из инвентаря). Так что теперь Level также необходимо удерживать ссылку на объект Player ?
Это не очень приятно; все, что должно содержать ссылку на все остальное.
В этот момент я вспомнил, что читал о делегатах из книги, которую я использую. Хотя я знаю о указателях функций из C ++, глава о делегатах была представлена с примерами с некой «основанной на событиях» точки зрения программирования, с которой у меня не было особого понимания.
Это дало мне идею спроектировать классы следующим образом:
Игрок:
class Player
{
//...
public delegate void Movement(Dir d); //enum Dir{NORTH, SOUTH, ...}
public event Movement PlayerMoved;
public void Move(Dir d)
{
PlayerMoved(d);
//Other code...
}
}
Уровень:
class Level
{
private Sector currSector;
private Player p;
//etc etc...
private void OnMove(Dir d)
{
switch (d)
{
case Dir.NORTH:
//change currSector
//other code
break;
//other cases
}
}
public Level(Player p)
{
p.PlayerMoved += OnMove;
currSector = START_SECTOR;
//other code
}
//etc...
}
Это хороший способ сделать это?
Если бы глава делегата не была представлена так, как она была, я бы не подумал об использовании таких «событий». Итак, что было бы хорошим способом реализовать это без использования обратных вызовов?
У меня есть привычка делать очень подробные сообщения ... извините, v__v