2013-02-21 52 views
2

我正在開發iOS的BlackJack遊戲。跟蹤目前的狀況和需要做的事情變得越來越困難。例如,我有這使當前遊戲的軌道C++類:在iOS中等待用戶交互的設計模式?

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

目前我使用的事件(方法A)實現它:

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

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

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

會陸續添加更多和更多的選擇在遊戲中,爲每個遊戲創建事件變得單調乏味,難以追蹤。

另一種方式我想實現它是像這樣(方法B):

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和B之間的差值如下:

答:

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

function CompleteA() { 
    finalize(); 
} 

B:

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

通知如何乙保持代碼更有條理。 Objective-C有沒有辦法做到這一點?或者有沒有其他方法可以替代我所提的建議?

我能想到的第三個選擇是使用有限狀態機。我已經聽到了一些關於他們的信息,但我確定這是否能幫助我解決這個問題。

我的問題推薦的設計模式是什麼?

+0

通常,您訂閱的事件會告訴您用戶何時進行了一些輸入。編碼遊戲時,通常會有一個循環,並檢查用戶輸入。在這種情況下,你通常想看看Cocos2D和更新函數。 – Daniel 2013-02-21 09:48:19

+0

這些塊可以幫助你輕鬆解決這個問題。 – holex 2013-02-21 13:45:47

回答

1

我明白你遇到的困境。當我第一次開始使用iOS時,我非常困難地放棄了對操作系統的控制權。

一般來說iOS會鼓勵你使用方法A.通常你的ViewController中有變量在方法A()中設置,然後在CompleteA()中檢查它們以驗證A()是否首先運行

關於你關於有限狀態機的問題,我認爲它可以幫助你解決你的問題。我在寫的iOS的第一件事是FSM(在那裏,這是非常糟糕的代碼),但是你可以看看這裏(近FlipsideViewController.m的底部:

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

總的想法是,你把這個放在你的.h文件裏面的一個@interface塊裏面

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

然後在你的。M你有這樣的:

- (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並從viewController調用[self tick]即可。 FSM將每隔0.1秒「打勾」,直到運行設置爲0.

在我原有的FSM設計中,我必須響應用戶輸入和來自運行它自己的軟件的Windows計算機的網絡輸入。在我的設計中,Windows PC也運行類似但不同的FSM。對於這種設計,我使用NSMutuableArray構建了兩個FIFO隊列對象。用戶交互和網絡數據包會將命令排入隊列,而FSM會使條目出隊並響應它們。我最終使用https://github.com/esromneb/ios-queue-object作爲隊列。

如果您需要任何澄清請發表評論。

+0

有人知道現在這是一個完全可怕的想法嗎?沒有人會閱讀這篇文章,他們甚至都非常關心回覆。 – portforwardpodcast 2016-01-15 01:53:31