【问题标题】:Inserting unique random numbers into a vector [duplicate]将唯一的随机数插入向量[重复]
【发布时间】:2017-05-24 11:25:36
【问题描述】:

作为某个游戏的代码的一部分,我想在一个向量中生成 4 个唯一的随机数。

此代码适用于一些重复播放,然后应用程序崩溃(不响应窗口)。

虽然我知道 if 条件会阻止 for 循环将相同的数字插入向量中,但这个 for 循环需要多长时间才能通过 rand() 函数生成唯一数字? srand(time(NULL))rand() 如何精确地协同工作以根据系统时间创建随机值?

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>

using namespace std;

//plays bulls and cows


int main() {
srand(time(NULL));
string play="yes";
int nums=4;       // number of values in an answer (must NOT exceed 10)
vector<int> answer;


while (play=="yes" || play=="YES" || play=="Y" || play=="Yes" || play=="y") { //plays the game

answer.push_back(rand()%10+1);
  do {                              //fills vector with unique random numbers
    for (int i=1; i<nums; i++) {
      answer.push_back(rand()%10+1);
      if (answer[i]==answer[i-1]) {
        i=i-1;
        continue;
        }
      }
  } while (answer.size()!=nums);

for (int i=0; i<nums; i++) {
  cout<<answer[i];
}

  cout<<"Do you want to play again?"<<'\n';
  cin>>play;
  answer.clear();
} //game ends


if (play=="no" || play=="n" || play=="No" || play=="NO" || play=="N") { //terminates and checks for exceptions
  cout<<"Thank you for playing!"<<'\n';
  return 0;
} else {
  cerr<<"Error: wrong input. Terminating."<<'\n';
  return 0;
}

    return 0; //safety return
}

【问题讨论】:

  • 另外,我知道有更好的 C++11 方法可以做到这一点,但我需要这样做。
  • 考虑使用std::set 而不是std::vector。一个集合只存储唯一值:std::set&lt;int&gt; answer; while (answer.size() &lt; 5) answer.insert(your_random_number);
  • 这很酷。但是我们现在使用向量,所以不确定它们是否会接受集合。 (运动之类的东西)
  • 然后使用一个集合并将结果复制到您的向量中。无需编写容易出错的循环。
  • @PaulMcKenzie,这是一种方法。谢谢。

标签: c++ vector random


【解决方案1】:

为什么要将新的 try 添加到 answer 而不是临时变量。如果变量有效,则将其添加到答案中。在您的情况下,i 始终保持在1;

while (play=="yes" || play=="YES" || play=="Y" || play=="Yes" || play=="y") { //plays the game

    int last_try=rand()%10+1;
    answer.push_back(last_try);
    do { //fills vector with unique random numbers
            int new_try=rand()%10+1;

            if (last_try!=new_try)
            {
                answer.push_back(new_try);
                last_try=new_try;
            }
    } while (answer.size()!=nums);


    for (int i=0; i<nums; i++)
    {
        cout<<answer[i]<<"\n";
    }

    cout<<"Do you want to play again?"<<'\n';
    cin>>play;
    answer.clear();
} //game ends

【讨论】:

  • 这比我的东西更合理。谢谢。但是核心思想不还是一样吗?我的意思是我突然想到它以某种方式强制执行 for 循环,因为如果我尝试在没有 do-while 循环的情况下执行此操作,则 srand() 和 rand() 总是返回相同的整数。
  • @bruneleski,这是真的。这个想法是蛮力的。您之前的代码非常容易受到攻击。你有一个 for 循环 for (int i=1; i&lt;nums; i++) { 运行 nums 次。你怎么知道nums 迭代后,answer 的大小等于nums?如果循环 while 再次运行,它可能会添加一些其他可能超过 nums 的数字。然后while循环将永远运行并且答案将不断扩大。这是一种未指定的行为。
  • 好吧,我以为我用 answer.clear() 解决了这个问题
  • 如果您将while (answer.size()!=nums); 替换为while (answer.size()&lt;nums);,您会发现错误在哪里。写while size != something的时候,一定要注意size最多增加一个单位,否则会出现跳转!!!
  • 哦,我现在明白了!您与 @MyUsername112358 结合的答案为我点击了它。非常感谢。
【解决方案2】:

问题是您总是在检查向量中的随机值是否有效之前将其推回。假设您的程序按顺序生成这些随机值:

2、6、6、7、9、10

发生的情况是您将插入 2 (i == 2)、6 (i == 3)、6 (i == 4),然后意识到 6 重复了两次,因此您返回一次迭代 (i == 3),但你的两个六点仍然在你的向量中。所以现在您将添加 7 (i == 4),然后您将退出 for 循环,向量中有 5 个值。

然后,当您评估您的 do-while 条件时,您的 answer.size() 将永远不会等于 4,因为它已经等于 5。您现在陷入无限循环,并且您的应用程序在消耗所有内容时崩溃向量中的可用内存无限增长。

另外,您的逻辑似乎有误。为确保您没有重复值(并且您被向量困住),您不仅应该验证最后插入的值,还应该验证整个向量。像这样:

#include <algorithm>

if ( std::find(vector.begin(), vector.end(), item) != vector.end() )
   do_this();
else
   do that();

【讨论】:

    【解决方案3】:

    假设您必须使用std::vector(而不是std::set)。用随机数填充向量的最简单方法是检查该数字是否已经“看到”——如果没有,则将其添加到向量中。

    这可以通过使用bool 的数组作为帮助器来确定是否已看到该号码:

    #include <vector>
    #include <iostream>
    #include <cstdlib>
    
    int main()
    {
        std::vector<int> answer;
        int num = 4;
    
        // 10 numbers
        bool seen[10] = {false};
    
        // keeps track of numbers added
        int numsAdded = 0;
        while (numsAdded < num)
        {
           int numRand = rand()%10;
           if ( !seen[numRand] )
           {
             // not seen, so add it to vector and update bool array and
             // numsAdded
             answer.push_back(numRand + 1);
             seen[num] = true;
             ++numsAdded;
           }
        }
        for (size_t i = 0; i < num; ++i)
           std::cout << answer[i] << " ";
    }
    

    Live Example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2021-02-15
      • 2010-09-16
      • 1970-01-01
      相关资源
      最近更新 更多