Литмир - Электронная Библиотека
Содержание  
A
A
НА ЗАМЕТКУ

Я решил привести в таблице все возможные перестановки переменных, указанных в столбцах "Состояние" и "Внешний ввод", чтобы проиллюстрировать тот факт, что не любое изменение состояния разрешено. Переходы между состояниями, указанными в строках, для которых в столбце "Следующее состояние" содержится пояснение "Запрещенный переход!", недопустимы в нашем приложении. Если приложение пытается каким-либо образом осуществить такое изменение состояния, значит, в логике его выполнения присутствуют ошибки. В случае если предпринимается попытка выполнения недействительного перехода, логика конечного автомата должна возбуждать исключение или, по крайней мере, использовать оператор ASSERT в режиме отладки. Явная идентификация запрещенных переходов между состояниями облегчает отладку приложений.

В листинге 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:

   //Если переход в данное состояние осуществляется из состояния,

   //для которого это запрещено, возбудить исключение

   if (m_CurrentGameState != GameState.AskQuestion) {

    throw new System.Exception("Запрещённый переход!");

39
{"b":"947732","o":1}