2013-07-15 24 views
0

我正在使用C++編寫基於文本的遊戲。我想知道如果不嵌套如此多的if語句,你將如何進入不同的事件。我所說的一個例子是...基於文本的遊戲非分支if語句

if (userChoice == 1) 
{ 
    //do something 
    cout << "Pick 1 , 2, or 3" << endl; 
    if (userChoice == 1) 
    { 
      cout << "pick 1, 2, 3/ some storry line" << endl; 
      if (userChoice == 3) 
      { 
       cout << " storyline...123...." << endl; 
       if (userChoice == 2) 
       { 
         //etc 
       } 
      } 
    } 
} 

我該如何做這個概念,而不分支if語句?

+0

那麼爲什麼你可能需要'(userChoice == 1)'兩次,第二次查看switch語句 – aaronman

+0

將邏輯上分離的邏輯和動作組織成不同的功能。當然,你需要內部的條件,但一旦你嘗試過,你會立即看到這樣做的優勢。 –

回答

3

您可以通過使用數據驅動設計擺脫分支if語句。

在基地你有一個循環檢查輸入,並使用當前上下文評估輸入,然後更改上下文。

這些if語句中的每一個都變成了「場景」(或房間或狀態,選擇對您正在編寫的程序有意義的名稱)。每個場景都有一個ID,一個描述以及一組有效的輸入和場景編號。

你有一個場景代表結束。

你有一個循環,雲:

評估輸入覈對當前場景的有效輸入的輸入,如果有效集當前場景中指定的場景。

該程序將當前場景初始化爲第一個場景,然後啓動循環。

因此,對於你的例子(顯然是不全面的,但應該給你你需要的數據的想法),你將有一個場景:

id: 1 
description: "Pick 1 , 2, or 3" 
inputs: "1" => 2, "2" =>, "3" => 

id: 2 
description: "pick 1, 2, 3/ some storry line" 
inputs: "1" =>, "2" =>, "3" => 3 

id: 3 
description: " storyline...123...." 
inputs: "1" =>, "2" =>, "3" => 

通常情況下,數據將來自文件。

下面是一個例子(這並沒有被編譯或調試):

struct Scene 
{ 
    Scene(int id_, int description_) 
     : id(id_) 
     , description(description_) 
    { 
    } 

    int id; 
    std::string description; 
    std::map<std::string, int> inputToNextScene; 
}; 

void main(int, char **) 
{ 
    std::map<int, Scene> scenes; 

    int ids = [1,2,3]; 
    std::string descriptions = ["first", "second", "third"]; 
    int nextScenes [3][3] = [ [1, 2, 3], [1, 3, 2], [1, 2, 0]]; 
    std::string input[3] = ["1", "2", "3"]; 

     for (int i = 0; i != 3; ++i) 
     { 
      scenes[ ids[i] ] = Scene(ids[i], descriptions); 

      Scene& scene = scenes.at(ids[i]); 

      for (int j = 0; j != 3; ++j) 
      { 
       scene.inputToNextScene[ input[j] ] = nextScenes[i][j]; 
      } 
    } 

    int currentScene = 1; 

    std::string input; 

    while (currentScene != 0) 
    { 
     Scene& scene = scenes.at(currentScene); 

     std::cout << scene.description; 
     //Maybe put in a prompt and check currentscene against previous before  printing description 
     std::cin >> input; 
     if (scene.inputToNextScene.find(input) != scene.inputToNextScene.end()) 
     { 
      currentScene = scene.inputToNextScene.at(input); 
     } 
    } 

    cout << "The end!"; 
} 
+0

我有點困惑。你可以編輯並給我一個代碼示例。 – freemann098

+0

@ freemann098,看看我包括的例子。 –

+0

感謝您的幫助! – freemann098

0

我會成爲一個單獨的函數爲每個選項:

void doStoryLine1() { 
    cout << "Options: ..." << endl; 
    if(userChoice == 1) 
     fightDragon(); 
    else if(userChoice == 2) 
     fightOrcs(); 
    else if(userChoice == 3) 
     marryPrincess(); 
    else 
     /* invalid option? */ 
} 

void doStoryLine2() { 
    ... 
} 

void selectStoryLine() { 
    cout << "Options: ..." << endl; 
    if(userChoice == 1) 
     doStoryLine1(); 
    else if(userChoice == 2) 
     doStoryLine2(); 
    else if(userChoice == 3) 
     doStoryLine3(); 
    else 
     /* invalid option? */ 
} 
+0

我可以但這會做同樣的事情,但功能,因爲使用的功能,它將分支再次if語句或我將不得不做許多功能。 – freemann098

+0

你最好做很多功能。你更有可能使你的代碼更好,更模塊化,並使維護更容易。 – nneonneo

-2

你描述的問題,似乎是在異步編程(例如節點JS)的常見問題。

可以通過使用控制流編程擺脫這些環的,如序列/瀑布承諾

注:我以前沒有使用過這個頭,但它應該工作類似於一個如何做期貨JS:Futures vs. Promises

代碼在JS(你的想法在C++)

/** Sequence **/ 
new Sequence() 


.then(function(next, arg1, arg2) { 
    // stage 1... 
    next(arg1, arg2); 
}) 


.then(function(next) { 
    // stage 2... 
    next(); 
}); 



/** Promise **/ 
var a = Promise(); 

function stage1() { 
    // capture input 1... 

    a.fulfill(input1); 

}(); 

a.when(function(err, data) { 
    console.log(data); 

}); 
+0

-1期貨是解決C++中這個問題的可怕選擇。另外,C++期貨還沒有'.then'(還),這使得底層的想法基本無法使用。 – ComicSansMS

+0

也許你可以進一步闡述?國際海事組織,這不應該得到一個downvote! – jhtong

+0

C++中的期貨不允許派送。相反,您可以將它們視爲將一個線程的值傳遞給另一個線程的一次性通道。在沒有多個線程的情況下,甚至可以用'T'類型的變量替換所有'將來的'/'承諾'對(只要你不關心唯一一個允許寫入的屬性) 。建議的'.then'風格分派可以在C++中實現,但未來在這裏是工作的錯誤工具 - 特別是因爲未來的主要設計目標是充當多線程原語。 – ComicSansMS

0

參見this questionmy answer

短版:

使用單獨的函數或對象的每個「分支」。 而不是「if/else」,請使用std::map。將用戶輸入ID映射到處理它們的函數。