Имеется модель некоторой "настольной" игры (привожу упрощенно), например, крестики-нолики, в ней определен интерфейс игрока:
interface IPlayer
{
Position GetMove(GameField field);
}
вспомогательные классы (Position
, GameField
, GameState
и т. д.) и, собственно, сам класс игры:
class Game
{
public GameField Field { get; private set; }
public GameState State { get; private set; }
IPlayer first, second;
public IPlayer CurrentPlayer { get; private set; }
public Game(IPlayer first, IPlayer second)
{
this.first = first;
this.second = second;
Reset();
}
public void Reset()
{
Field = new Field();
State = GameState.Proceed;
CurrentPlayer = first;
}
public void NextMove()
{
... // Проверка состояния игры и выброс исключения если ходы уже невозможны
var position = CurrentPlayer.GetMove(Field.Copy());
... // Проверка корректности хода и его применение или выброс исключения
... // Проверка окончания игры и смена статуса
... // Смена текущего игрока
}
}
Игровой цикл, например, в консольном приложении мог бы выглядеть как-то так:
ComputerPlayer first = new ComputerPlayer();
HumanPlayer second = new HumanPlayer();
Game game = new Game();
ShowField(game.Field);
while (game.State != GameState.Completed)
{
game.NextMove();
ShowField(game.Field);
}
С игроком-компьютером всё просто - реализуем в его коде алгоритм поиска лучшего хода. Он не зависит от представления.
Как быть с игроком-человеком? Он ведь по сути жестко связан с представлением. В консольном приложении я мог бы реализовать его примерно так:
class HumanPlayer : IPlayer
{
public Position GetMove(GameField field)
=> ConvertToPosition(Console.ReadLine());
Position ConvertToPosition(string s)
{
...
}
}
Получается, я должен реализовать игрока в части представления VM+V? Или нужно разделить его как-то на модельную и представленческую части? Как организовать игровой цикл? Как предусмотреть возможность игры Человек vs. Человек?
Набросал пока такое решение:
class HumanPlayer : IPlayer
{
TaskCompletionSource<Position> taskSource;
public Position GetMove(GameField gameField)
{
taskSource = new TaskCompletionSource<Position>();
Position result = taskSource.Task.Result;
taskSource = null;
return result;
}
public void SendPosition(Position position)
=> taskSource?.SetResult(position);
}
При вызове метода GetMove
из Game
поток, в котором бежит модель блокируется до того момента, пока кто-то (а это будет VM
) не подтолкнет его вызовом метода SendPosition
.
Надеюсь, кто-нибудь прокомментирует мой вариант и укажет на его недостатки или может кого-то мой ответ натолкнет на мысли и он напишет свой ответ. Буду рад любым комментариям и замечаниям.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Метод Listen запускается в отдельном потоке, должен получать данные с сервера и проигрывать их(это звук)Но вылазит исключение: Необработанное...
Как при помощи Button сделать возможность добавлять сразу множество файлов только формата mp3 в компонент ListView?
Я не понимаю это баг какой то, или разработчики языка просто забыли добавить это свойство? В интернете по этому поводу только одна тема в которой...
Хочу сохранить изображение с PictureBox, но постоянно сохраняется только чёрное изображение или вылетает ошибкаПодскажите в чём проблема