【问题标题】:How to randomize a switch?如何随机化一个开关?
【发布时间】:2017-11-08 01:59:02
【问题描述】:

这是我目前所拥有的。这个程序的重点是如果有人输入数字1..3,他们将获得其中一个奖品,但我不希望奖品每次都在同一扇门后面。我如何使它们随机化,所以也许百万美元在 2 号门而不是 1 号门后面?

#include <iostream>
#include <cstdlib>
using namespace std;

int main() {
    int doorNumber;
    //int door1, door2, door3;

    cout << "Pick a door, 1, 2, or 3" << endl;
    cin >> doorNumber;

    switch (doorNumber) {
    case 1:
        cout << "you win a million dollars" << endl;
        break;
    case 2:
        cout << "you win detergent" << endl;
        break;
    case 3:
        cout << "you win a dishwasher" << endl;
        break;
    }

    return 0;
}

【问题讨论】:

  • 我想不出这样做的好方法,但是 +1 因为我认为这是一个好问题。在我的脑海中,您可以忽略他们的输入并简单地打印一个随机语句。因此,与其使用switch(doorNumber),不如获取一个随机数和switch,而不是
  • 您的程序可能“作弊”。 IE。忽略输入,随机确定用户收到的奖品。

标签: c++ function switch-statement


【解决方案1】:

case 语句需要在编译时必须知道的整数值,因此不幸的是,您不能在 switch 语句中随机移动门编号。 但是,您可以在用户的​​输入中添加一个随机数,并以 3 为模,然后添加一个以将总和投影回 1,2 或 3。

【讨论】:

    【解决方案2】:

    将奖品放入一个数组中,然后对该数组进行洗牌,例如:

    #include <iostream>
    #include <algorithm>
    #include <limits>
    
    int main() {
        string prizes[3] = {"a million dollars", "detergent", "a dishwasher"};
        int doorNumber;
    
        std::random_shuffle(prizes, prizes+2);
    
        do {
            std::cout << "Pick a door: 1, 2, or 3" << std::endl;
            std::cin >> doorNumber;
    
            if ((doorNumber >= 1) && (doorNumber <= 3))
                break;
    
            std::cout << "Invalid door! Try again" << std::endl;
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cin.clear();
        }
        while (true);
    
        std::cout << "you win " << prizes[doorNumber-1] << std::endl;
    
        return 0;
    }
    

    请注意,std::random_shuffle() 在 C++14 中已弃用并在 C++17 中删除。您可以改用std::shuffle()

    #include <iostream>
    #include <algorithm>
    #include <random>
    #include <limits>
    #include <iterator>
    
    int main() {
        string prizes[3] = {"a million dollars", "detergent", "a dishwasher"};
        int doorNumber;
    
        std::random_device rd;
        std::mt19937 g(rd());
        std::shuffle(std::begin(prizes), std::end(prizes), g);    
    
        do {
            std::cout << "Pick a door: 1, 2, or 3" << std::endl;
            std::cin >> doorNumber;
    
            if ((doorNumber >= 1) && (doorNumber <= 3))
                break;
    
            std::cout << "Invalid door! Try again" << std::endl;
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cin.clear();
        }
        while (true);
    
        std::cout << "you win " << prizes[doorNumber-1] << std::endl;
    
        return 0;
    }
    

    【讨论】:

    • 我只是删除了已弃用的示例,它不会在此答案中添加任何内容
    • @thecoshman:很多人还没有使用 C++14/17,所以std::random_shuffle() 在 C++11 及更早版本中是一个可行的解决方案。
    • 这个问题被简单地标记为“C++”,显然是一个菜鸟。我们应该避免教授旧的糟糕的做事方式。
    • @RemyLebeau 这可能是真的,但考虑到这些人中的大多数人应该更有经验(即:他们没有转换,因为他们开始时不存在),有问题的人(以及大多数在这里寻找答案的人)应该使用最新的代码标准,因为他们没有理由不这样做。
    • 这是您的意见。除非另有说明,否则我宁愿不做假设并为多个版本提供解决方案。
    【解决方案3】:

    您可以为玩家的选择添加随机修饰符。如果您事先这样做,则与为每个奖品设置不同的预定门号完全相同。切换后,只需将它们相加并确保结果在 1 和 3 之间。

    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    int main() {
        int doorNumber;
        //int door1, door2, door3;
    
        srand(time(NULL));
        int randomNumber = rand() % 3;
        // generate a number between 1 and 3
    
        cout << "Pick a door, 1, 2, or 3" << endl;
        cin >> doorNumber;
    
        switch ((doorNumber + randomNumber) % 3 + 1) { 
        case 1:
            cout << "you win a million dollars" << endl;
            break;
        case 2:
            cout << "you win detergent" << endl;
            break;
        case 3:
            cout << "you win a dishwasher" << endl;
            break;
        }
    
        return 0;
    }
    

    你不能在 switch 中有不同的门号,因为 case 值是在编译期间设置的,所以它们必须是常量值。

    【讨论】:

      【解决方案4】:

      可以通过声明一个数组并打乱数组的内容。

      #include <iostream>
      #include <cstdlib>
      #include <algorithm>
      using namespace std;
      
      int main() {
          int doorNumber;
          int a[2] = {1,2,3};
          //int door1, door2, door3;
      
          random_shuffle(&a[0], &a[2]);
      
          cout << "Pick a door, 1, 2, or 3" << endl;
          cin >> doorNumber;
      
          switch (doorNumber) {
          case a[0]:
              cout << "you win a million dollars" << endl;
              break;
          case a[1]:
              cout << "you win detergent" << endl;
              break;
          case a[2]:
              cout << "you win a dishwasher" << endl;
              break;
          }
      
          return 0;
      }
      

      【讨论】:

      • 您不能对case 语句使用运行时值,它们必须是编译时常量。您将不得不改用 if 语句:if (doorNumber == a[0]) { ... } else if (doorNumber == a[1]) { ... } else if (doorNumber == a[2]) { ... }
      • switch(a[doorNumber - 1]) { case 1: ... } 确保数字在 1 和 3 之间(含)。
      • 随机随机播放最近不是被移除或弃用了吗?
      • @pTz 顺便说一句,编辑以添加对代码的评论并不真正“合适”,只需对答案发表评论即可。
      • @Isaiah:是的,在 C++14 中已弃用,在 C++17 中已删除。不过,在 C++11 及更高版本中有 std::shuffle()
      【解决方案5】:

      您不能像您要求的那样“随机切换”。此外,在您提出的问题中,每次运行程序时,用户输入一个数字并显示随机结果;您甚至可以不记录他们的输入内容,而是将switch 记录在随机值上。

      但是,我怀疑你想要做的是让玩家有多次机会选择门。在这种情况下,您需要创建门结果的集合(在您的示例中为std::vector&lt;std::string&gt;),然后将其随机化。 C++ 和许多其他语言提供标准函数来打乱集合。现在你有了随机排列的门集合,你可以让玩家一一选择它们,你可以显示他们选择的结果。

      最终,我认为您不需要切换或担心如何随机化它。

      ps,我没有为此编写代码示例,因为我认为这是一个足够理论上的概念,尽管我可能没有很好地解释它,所以请随时要求澄清。

      C++ 类似于

      std::vector<std::string> doors = {
          "door a", "door b", "door c"};
      auto random_doors = std::shuffle_sort(doors); // or something like this
      cout << "Enter a door: "
      cin >> players_input
      cout << "You entered a door and : " << random_doors[players_input];
      

      【讨论】:

      • 我将如何应用 std::vector<:string>。我还是 C++ 的新手,需要进一步的指导..
      • 我添加了一个粗略的例子,但是你真的需要自己去了解这些东西是什么。有很多东西要学,是的,我知道,但现在就开始阅读吧。
      • 你也可以使用 std::array<:string> 它与 C 风格的数组非常相似。
      • AFAIK,STL 中没有std::shuffle_sort()
      • @RemyLebeau 是的,不要太在意,它应该被更多地视为看起来接近 C++ 的伪代码。这个问题的重要部分是逻辑而不是实际的实现。如果它对您很重要,请随意将其设为“真正的”C++。
      猜你喜欢
      • 2012-11-25
      • 2023-03-26
      • 2011-03-25
      • 1970-01-01
      • 2011-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多