2017-01-10 3 views
-1

特定のゲームのコードの一部として、ベクトルに4つの一意の乱数を生成したいとします。ベクトルに一意の乱数を挿入する

このコードは、繰り返し再生された後、アプリケーションがクラッシュする(応答しない)場合に機能します。

if-conditionはfor-loopが同じ数字をベクトルに挿入するのを防ぐが、rand()経由で一意の数字を生成するまで、for-loopにかかる時間はどのくらいかかりますか? どのように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 
} 
+0

をまた、私はより良い、C++ 11の方法が存在しているはずこれを行うには、私はこのようにする必要があります。 – bruneleski

+0

'std :: vector'の代わりに' std :: set'を使うことを検討してください。セットはユニークな値だけを格納します: 'std :: set answer; while(answer.size()<5)answer.insert(your_random_number); ' – PaulMcKenzie

+0

これはクールです。しかし、今はベクターで作業しています。セットを受け入れるかどうかは不明です。 (物の運動種) – bruneleski

答えて

0

問題は、有効であるかどうかを確認する前に、常にベクトルのランダム値をプッシュバックすることです。のは、あなたのプログラムがためにこれらのランダムな値を生成しましょう:

2、6、6、7、9、10

何が起こることはありますが、2(I == 2)、6(Iを挿入します== 3 )、6(i == 4)、次に6が2回繰り返されるので、1回の繰り返し(i == 3)に戻りますが、6つはどちらもベクトルに残ります。これで7(i == 4)を追加し、ベクトルの5つの値を使ってforループを終了します。

do-while条件を評価すると、answer.size()はすでに5に等しいため、4になることはありません。これで、無限ループに陥り、消費時にアプリケーションがクラッシュしますあなたのベクトルから利用可能なすべてのメモリが無限に成長します。

また、ロジックにエラーがあるようです。繰り返し値を持たないようにするためには、最後に挿入された値だけでなくベクトル全体を検証する必要があります。このように:

#include <algorithm> 

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

なぜ新しいテイクを一時変数の代わりに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 
+0

私のものよりも合理的です。ありがとう。 しかし、コアのアイデアは変わっていませんか? 私はdo-whileループを使わずにしようとすると、srand()とrand()が常に同じ整数を返すので、何らかの形でforループを実行することが起こります。 – bruneleski

+0

@ bruneleski、それは本当です。アイデアはブルートフォースにある。以前のコードは非常に脆弱です。 'for(int i = 1; i jeremine

+0

これは、私がanswer.clear()で世話したと思ったものです。 – bruneleski

0

あなたは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

関連する問題