2013-02-21 2 views
2

Я разрабатываю игру BlackJack для iOS. Отслеживание текущего состояния и того, что необходимо сделать, становится сложным. Например, у меня есть класс C++, который отслеживает текущую игру:Дизайн шаблона для ожидания взаимодействия с пользователем в iOS?

class Game { 
    queue<Player> playerQueue; 
    void hit(); 
    void stand(); 
} 

В настоящее время я его реализации с помощью событий (метод А):

- (void)hitButtonPress:(id)sender { 
    game->hit(); 
} 

void Game::hit() { 
    dealCard(playerQueue.top()); 
} 

void Game::stand() { 
    playerQueue.pop(); 
    goToNextPlayersTurn(); 
} 

по мере добавления все больше и больше опций к игре, создание событий для каждого из них становится утомительным и трудно отслеживать.

Другой способ, которым я думал о его реализации, как так (метод В):

void Game::playersTurn(Player *player) { 
    dealCards(player); 
    while (true) { 
    string choice = waitForUserChoice(); 
    if (choice == "stand") break; 
    if (choice == "hit") 
     dealCard(player); 
    // etc. 
    } 
    playerQueue.pop(); 
    goToNextPlayersTurn(); 
} 

Где waitForUserChoice это специальная функция, которая позволяет пользователю взаимодействовать с UIViewController и когда пользователь нажимает на кнопку, только потом возвращает управление обратно в функцию playersTurn. Другими словами, он приостанавливает программу, пока пользователь не нажмет кнопку.

С методом A мне нужно разделить свои функции каждый раз, когда мне нужно взаимодействие с пользователем. Метод B позволяет все немного контролировать. По существу разница между методом А и В заключается в следующем:

A:

function A() { 
    initialize(); 
    // now wait for user interaction by waiting for a call to CompleteA 
} 

function CompleteA() { 
    finalize(); 
} 

B:

function B() { 
    initialize(); 
    waitForUserInteraction(); 
    finalize(); 
} 

Обратите внимание, как B сохраняет код более организованным. Есть ли способ сделать это с помощью Objective-C? Или есть другой метод, который я не упомянул ранее?

Третий вариант, о котором я могу думать, это использование конечного автомата. Я слышал о них немного, но я уверен, что это поможет мне в этом случае или нет.

Какова рекомендуемая модель дизайна для моей проблемы?

+0

Обычно вы подписываетесь на события, которые сообщают вам, когда пользователь внес какой-либо ввод. При кодировании игр у вас обычно есть цикл, в котором вы проходите, также проверяя ввод пользователя. В этом случае вы обычно хотите взглянуть на Cocos2D и функцию обновления. – Daniel

+0

блоки могут помочь вам решить это легко. – holex

ответ

1

Я понимаю дилемму, с которой вы сталкиваетесь. Когда я впервые запустил iOS, мне очень тяжело было обернуть голову вокруг отказа от управления и от операционной системы.

В целом, iOS будет поощрять вас к использованию метода A. Обычно у вас есть переменные в вашем ViewController, которые установлены в методе A(), а затем они проверяются в CompleteA(), чтобы убедиться, что A() запущен первым и т. Д. .

Что касается вашего вопроса о конечных машинах, я думаю, что это может помочь вам решить вашу проблему. Самое первое, что я написал в прошивкой был FSM (там это очень плохой код), однако вы можете посмотреть здесь (в нижней части FlipsideViewController.m:

https://github.com/esromneb/ios-finite-state-machine

Основная идея заключается в том, что вы помещаете это в свой .h-файл внутри блока @interface

static int state = 0; 
static int running = 0; 

И в вашем.м у вас есть это:

- (void) tick { 

    switch (state) { 
     case 0: 
      //this case only runs once for the fsm, so setup one time initializations 

      // next state 
      state = 1; 

      break; 
     case 1: 
      navBarStatus.topItem.title = @"Connecting..."; 
      state = 2; 
      break; 
     case 2: 
      // if something happend we move on, if not we wait in the connecting stage 
      if(something) 
       state = 3; 
      else 
       state = 1; 
      break; 
     case 3: 
      // respond to something 

      // next state 
      state = 4; 
      break; 
     case 4: 
      // wait for user interaction 
      navBarStatus.topItem.title = @"Press a button!"; 
      state = 4; 

      globalCommand = userInput; 

      // if user did something 
      if(globalCommand != 0) 
      { 
       // go to state to consume user interaction 
       state = 5; 
      } 

      break; 

     case 5: 
      if(globalCommand == 6) 
      { 
       // respond to command #6 
      } 
      if(globalCommand == 7) 
      { 
       // respond to command #7 
       } 

         // go back and wait for user input 
         state = 4; 
      break; 

     default: 
      state = 0; 
      break; 
    } 

    if(running) 
    { 
     [self performSelector:@selector(tick) withObject:nil afterDelay:0.1]; 
    } 
} 

В этом примере (модифицированный из одного на GitHub) globalCommand является INT, представляющий ввод пользователя. Если globalCommand равно 0, то FSM просто вращается в состоянии 4 до тех пор, пока globalCommand не будет равен нулю.

Для запуска FSM просто установите значение 1 и вызовите [self tick] из viewController. FSM будет «галочкой» каждые 0,1 секунды, пока работа не будет установлена ​​на 0.

В моей первоначальной конструкции FSM мне пришлось отвечать на ввод пользователя и сетевой ввод с компьютера Windows, на котором запущено собственное программное обеспечение. В моем дизайне на ПК с Windows также работал аналогичный, но другой FSM. Для этого проекта я построил два объекта очереди FIFO команд с использованием NSMutuableArray. Взаимодействия с пользователем и сетевой пакет помещают команды в очереди, в то время как FSM будет деактивировать элементы и отвечать на них. Я закончил использование https://github.com/esromneb/ios-queue-object для очередей.

Прошу прокомментировать, если вам нужно какое-либо разъяснение.

+0

Кто-нибудь знает, если это сейчас абсолютно ужасная идея? Никто никогда не прочтет это сообщение, которое даже заботится о том, чтобы ответить. – portforwardpodcast

 Смежные вопросы

  • Нет связанных вопросов^_^