如何防止c++中随机生成选项的重复

How to prevent repetition of randomly generated options in C++?

本文关键字:选项 何防止 c++ 随机      更新时间:2023-10-16

这是我到目前为止所做的,我尽了最大的努力标记代码的每个位。值得注意的是,这是用XCode编写的,所以它是在Mac上运行的。

/*
Ayush Sharma
4 November 2016
*/
#include <iostream>
#include <ctime>
using namespace std;
int main (){
//clearing the screen
system("clear");
//seeding the random
srand((unsigned int)time(NULL));
//variables & arrays
char answer;
int r, m, correct = 0;
string capitals[50] =
    {"Montgomery", "Juneau", "Phoenix", "Little Rock", "Sacramento", "Denver", "Hartford", "Dover", "Tallahassee", "Atlanta", "Honolulu", "Boise", "Springfield", "Indianapolis", "Des Moines", "Topeka", "Frankfort", "Baton Rouge", "Augusta", "Annapolis", "Boston", "Lansing", "St. Paul", "Jackson", "Jefferson City", "Helena", "Lincoln", "Carson City", "Concord", "Trenton", "Santa Fe", "Albany", "Raleigh", "Bismarck", "Columbus", "Oklahoma City", "Salem", "Harrisburg", "Providence", "Columbia", "Pierre", "Nashville", "Austin", "Salt Lake City", "Montpelier", "Richmond", "Olympia", "Charleston", "Madison", "Cheyenne"};
string states[50] = {"Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Carolina","North Dakota","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"};
//title
cout << "***************************************************************n";
cout << "*                                                             *n";
cout << "*                 United States Capitals Quiz                 *n";
cout << "*                                                             *n";
cout << "***************************************************************nn";

for (int i = 0; i < 15; i++){
    //Picking A Random State
    r = rand() % 50;
    //Checking if State is a Repeat
    if (states[r] != "-1") {
        cout << "What is the capital of " << states[r] << "? ";
        //Picking Correct Answer Choice and Respective Layout
        m = rand() % 4;
        if (m == 0) {
            cout << "nA: " << capitals[r] << endl;
            cout << "B: " << capitals[rand()%50] << endl;
            cout << "C: " << capitals[rand()%50] << endl;
            cout << "D: " << capitals[rand()%50] << endl;
        }
        if (m == 1) {
            cout << "nA: " << capitals[rand()%50] << endl;
            cout << "B: " << capitals[r] << endl;
            cout << "C: " << capitals[rand()%50] << endl;
            cout << "D: " << capitals[rand()%50] << endl;
        }
        if (m == 2) {
            cout << "nA: " << capitals[rand()%50] << endl;
            cout << "B: " << capitals[rand()%50] << endl;
            cout << "C: " << capitals[r] << endl;
            cout << "D: " << capitals[rand()%50] << endl;
        }
        if (m == 3) {
            cout << "nA: " << capitals[rand()%50] << endl;
            cout << "B: " << capitals[rand()%50] << endl;
            cout << "C: " << capitals[rand()%50] << endl;
            cout << "D: " << capitals[r] << endl;
        }
        //Recieving Answer
        cout << "Answer: ";
        cin >> answer;
        //Converting Letter to Number
        if (answer == 'A' || answer == 'a') answer = 0; if (answer == 'B' || answer == 'b') answer = 1;
        if (answer == 'C' || answer == 'c') answer = 2; if (answer == 'D' || answer == 'd') answer = 3;
        //Comparing Answer to Correct Answer
        if (m == answer) {
            cout << "Correct!" << endl << endl;
            correct++;
        }else{
            cout << "Incorrect! The correct answer was " << capitals[r] << "! nn";
        }
        //Removing State from Array
        states[r] = "-1";
    }else{
        //If State was a Repeat, generate another State
        i--;
    }
}
//Printing Results
cout << "Number Correct: " << correct << "/15 or " << ((correct/15.00)*100) << "%!n";
return 0;
}

代码几乎可以工作。问题是答案有时会被重复,比如下面这个场景:威斯康辛州的首府是哪里?答:麦迪逊b .法兰克福c·杰克逊d·麦迪逊只有A或D是"正确"的答案,尽管它们有相同的文本(尽管我宁愿让答案不可能重复)。我也想知道是否有一种更有效的方法来创建选择题的布局。提前感谢!

-Ayush

假设您希望随机绘制50值,而不需要重复,只需创建包含这些值的数组或向量,对其进行洗牌,然后按顺序访问洗牌数组中的元素。

在c++ 11中,这很容易使用<algorithm>中的std::iota()std::random_shuffle()算法。

  int value[50];
  std::iota(std::begin(value), std::end(value), 0);   //  populate array with values 0 to 49
  std::random_shuffle(std::begin(value), std::end(value));

然后在你的外循环中,用r=value[i]代替r = rand()%50

std::begin()std::end()在标准标头<iterator>中。

同样的想法可以在c++ 11之前使用,但方法有点不同(c++ 11不支持std::begin(), std::end()std::iota(),但等效的很容易实现)。

而不是value是一个数组,我将它创建为std::vector<int>,也有50个元素。我在上面使用数组来说明,因为您似乎默认使用数组。

这是很明显会发生的事情。一个简单的解决方案是创建一个数组来保存已经显示的选项。使用while循环向数组中添加唯一选项。您可以使用另一个函数检查数组中是否有任何重复。然后,显示capitals[r]以及数组中的其他三个选项。

bool noRepeat(int arr[], int o){
    for(int i=0; i<3; i++){
        if(arr[i] == o)
            return false;
    }
    return true;
}

int main(){
    ...
    //picking correct answer and determining layout
    int m = rand()%4, n=0, y, options[3];
    if (m == 0) {
        while(n<3){
            y = rand()%50;
            if(noRepeat(options, y) && capitals[y]!=capitals[r])
                options[n++] = y;                
        }
        //display according to layout
        cout << "nA: " << capitals[r] << endl;
        cout << "B: " << capitals[options[0]] << endl;
        cout << "C: " << capitals[options[1]] << endl;
        cout << "D: " << capitals[options[2]] << endl;
    }
    //do the same for the rest
    ...
}

就像@Isaiah说的,你可以使用while循环来测试生成的索引是否与你的正确答案不相同。

例如:

int index = rand() % 50;
while(index == r)
{
    index = rand() % 50;
}
cout << "B: " << capitals[index] << endl;

注意:这仍然可以产生重复的"不正确的答案",但我猜你得到的点,以避免由rand产生的重复。很明显,这个代码只是为了纠正正确答案的重复,你应该使用rand,正如其他人在评论中提到的。

你的问题是随机选择三个没有重复的大写字母。下面是一些伪代码

  1. 将除正确答案外的所有答案都大写成矢量
  2. 生成一个随机索引到这个向量
  3. 在该索引处使用大写字母,并从矢量
  4. 中删除大写字母。
  5. 对第二个和第三个随机大写字母重复步骤2和3。注意随机索引应该允许在每次迭代中减少向量大小。