В листинге 5.1 представлен код, реализующий определенный выше конечный автомат. Этот код соответствует диаграмме переходов, представленной в табл. 5.1 и на рис. 5.1. Обратите внимание на то, что в приведенной ниже функции участки кода, соответствующие различным изменениям состояний, содержат вызовы функций, отключенные с помощью символов комментариев. Эти функциональные вызовы представляют ту часть работы, которая должна быть выполнена для соответствующего изменения состояния, и отключены символами комментариев с той целью, чтобы приведенный ниже код можно было компилировать как независимый блок; реализация вызываемых функций остается за вами. Для определения текущего варианта изменения состояния удобно использовать блок операторов switch/case.
Каждый оператор case соответствует одному из вариантов изменения состояния и должен содержать вызов функции, выполняющей всю необходимую для этого работу. Подобного рода централизация и инкапсуляция управления состояниями является одним из наиболее мощных аспектов использования конечных автоматов; все важные изменения состояний приложения определяются и обрабатываются централизованно в одном месте программы.
Листинг 5.1. Простой код конечного автомата для игры с множественным выборомclass MyStateMachineClass {
private enum GameState {
StartScreen, AskQuestion, CongratulateUser, ScoldUser
}
private GameState m_CurrentGameState;
//---------------------------------------------------------------------
//Конечный автомат, воздействующий на пользовательский интерфейс
//и управляющий переходами приложения в другие состояния в соответствии
//c текущим режимом работы пользователя
//---------------------------------------------------------------------
private void StateChangeForGame(GameState newGameUIState) {
//Определить, в какое состояние переходит приложение
switch(newGameUIState) {
case GameState.StartScreen:
//Если переход в данное состояние осуществляется из состояния,
//для которого это запрещено, возбудить исключение
if ((m_CurrentGameState != GameState.CongratulateUser) && (m_CurrentGameState != GameState.ScoldUser)) {
throw new System.Exception("Запрещённый переход!");
}
//ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
// 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
// элементов управления пользовательского интерфейса
// 2. Настройка переменных/состояния игры, соответствующих
// данному режиму работы
//
// SetUpGameStateForStartScreen();
break;
case GameState.AskQuestion:
//Если переход в данное состояние осуществляется из состояния,
//для которого это запрещено, возбудить исключение
if ((m_CurrentGameState != GameState.StartScreen)
&& (m_CurrentGameState != GameState.CongratulateUser)
&& (m_CurrentGameState !=GameState.ScoldUser)) {
throw new System.Exception("Запрещённый переход!");
}
//ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
// 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
// элементов управления пользовательского интерфейса
// 2. Настройка переменных/состояния игры, соответствующих
// данному режиму работы
//
// SetUpGameStateForAskQuestion();
break;
case GameState.CongratulateUser:
//Если переход в данное состояние осуществляется из состояния,
//для которого это запрещено, возбудить исключение
if (m_CurrentGameState != GameState.AskQuestion) {
throw new System.Exception("Запрещённый переход!");
}
//ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
// 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
// элементов управления пользовательского интерфейса
// 2. Настройка переменных/состояния игры, соответствующих
// данному режиму работы
//
// SetUpGameStateForCongratulateUser();
break;
case GameState.ScoldUser:
//Если переход в данное состояние осуществляется из состояния,
//для которого это запрещено, возбудить исключение