0

「Choose Your Own Adventure」ゲームで if ステートメントと switch ステートメントをいつどのように使用するかを説明するにはどうすればよいですか?

ゲームは基本的に、ある答えを入れるとゲームの流れや方向性が変わるという仕組みになっています。私は通常、if 文を関数で使用してきましたが、それが最も効率的で簡単な教育方法ですか?

ありがとう!

編集:うわー、たくさんの素晴らしい回答をありがとうございます!! 最後に 1 つだけ注意してください。もしあなたがプログラミングの予備知識なしでこの概念を理解しようとしている 13 歳だったとしたら、どのように理解しようとしますか? 真剣に、助けてくれてありがとう!!

4

6 に答える 6

3

「私はこの情報を受け取りました。今何をすべきか」には、5 つの異なる解決策 (ギブ オア テイク) があります。

  1. If/else if/else ... チェーン。true利点は、 orにできる任意の式を使用できることfalseです。欠点は、それらのチェーンが長い場合、かなり面倒になる可能性があることです.
  2. Switch - 「ほとんど同じようなことがたくさんある」場合に最適です。欠点は、caseラベルが整数値 (またはchar値、文字列、浮動小数点値などではない) でなければならないことです。
  3. 長い if/else をよりシンプルにするテーブルif(table[index].something) ...
  4. 関数ポインタ - テーブル ポインタ バリアントの一種 - は、その方向に移動した場合に実行したいことを実行する関数へのポインタを格納します。
  5. 仮想関数を使用するオブジェクト。繰り返しますが、ソリューションの変形ですが、table関数ポインターを格納する代わりに、「必要なことは何でも行う」ために使用できるメンバー関数を使用してオブジェクトを格納します。

この場合の正しい解決策は、おそらく後者の 3 つのいずれかの組み合わせ/バリエーションです。少なくとも私の意見では。

于 2013-06-14T00:20:21.683 に答える
1

switchステートメントはスピードのためです。そのため、それらは数値のみです。コンパイラは、コードが常に実行されている場合にパフォーマンスを大幅に向上させることができる非スパース (連続) 値範囲のルックアップ テーブルを作成しようとします。これは、どのコードを実行するかを決定するために、連続した範囲に対して 1 回の比較のみを行う必要があるためです。

switchcaseステートメントは、それぞれの最後にa を指定する必要があるため、見つけにくいバグを引き起こす可能性があります。そうしbreakないと、実行が次の に失敗しcaseます。

if//ステートメントは、より一般的に使用するためのものですelse ifelse一般に、同じ値に対して多くの比較がある場合switch、同等のステートメントよりも遅くなります。ただし、ステートメントのチェーンがあまり実行されずチェーンがそれほど長くない場合、パフォーマンスの向上はごくわずかです。if

より一般的な使用法についてifは、行く方法です。CYOAGでは、スピードは必要ありません。ゲームの最も遅い部分はユーザーです。

これを13歳に説明するには:

単一の整数 (整数) 値に対して 1,000,000 回以上の比較を一度に実行する予定で、できるだけ迅速に実行する必要がある場合は、switchステートメントを使用します。そうでなければ、問題ではありません。を使用するときは注意してください。それぞれの最後に がswitchない場合、何が起こったのかを理解しようとして頭を悩ませることになるからです。2 つ以上の が実行されたとき。breakcasecase

于 2013-06-14T02:43:23.377 に答える
0

switchまあ、実際には文字列を/に入れることはできませんcase。それはあなたを残しますif。または、文字列を読み取り、それらを何らかの型にマップしてから、 /内でenumsaid を使用するパーサーを実装する必要があります。enumswitchcase

ただし、より良い (より拡張可能な) 方法は、関数コールバックのマップを使用することです。

このようなもの:

#include <map>
#include <string>
#include <iostream>

typedef void(*ActionCallback)();
typedef std::map<std::string, ActionCallback> ActionMap;
static bool running = true;

void leftAction(){
    std::cout << "\"left\" entered" << std::endl;
}

void rightAction(){
    std::cout << "\"right\" entered" << std::endl;
}

void quitAction(){
    std::cout << "game terminated" << std::endl;
    running = false;
}

int main(int argc, char** argv){
    ActionMap actionMap;
    actionMap["left"] = leftAction;
    actionMap["right"] = leftAction;
    actionMap["quit"] = quitAction;

    while(running){
        std::string command;
        std::cout << "enter command. Enter \"quit\" to close" << std::endl;
        std::cin >> command;

        ActionMap::iterator found = actionMap.find(command);
        if (found == actionMap.end())
            std::cout << "unknown command " << command << std::endl;
        else
            (*found->second)();
    }
    return 0;
}

このアプローチの大きな利点は、実行時にコマンドを変更できることです。新しいコマンドを追加したり、それらを削除したりします。もう少し進んで、lisp/python/lua バインディングを追加して、さらに拡張可能にすることもできます。

于 2013-06-14T01:00:39.590 に答える