随机生成一个没有重复元素的枚举数组(C ++)

时间:2018-01-20 10:41:33

标签: c++ arrays enums

我正在尝试生成一个没有相同元素的枚举数组,但我所做的仍然会给我重复元素

const int MAXNO = 6;
enum Fruit {Durian, Papaya, Apple, Orange, Mango, Jackfruit, Strawberry};

int main ()
{
    srand (time (NULL));

    int size = rand () % 6 + 1;

    Fruit f [size];
    cout << "Size: " << size << endl;

    for (int i = 0; i < size; i++)
    {
        f[i] = static_cast <Fruit>(rand() % MAXNO);

        for (int j = 0; j < i; j++)
        {
            do 
            {
                f[i] = static_cast <Fruit>(rand() % MAXNO);

            }while(f[i] == f[j]);
        }       
        cout << f[i] << endl;

    }
}

我做错了什么?

5 个答案:

答案 0 :(得分:1)

获取数组whit enum length并使用0初始化,并且对于每个随机枚举产生检查,该数组中的索引为0,如果为true,则在该数组上生成enum的索引。

获取枚举大小的数组whit长度 最初用0

int produced_value[MAXNO] = {0}; //be new array
-------------------------
| 0 | 0 | 0 | 0 | 0 | 0 |
-------------------------

此数组显示之前生成的枚举。 每次生成随机枚举并希望在检查之前不生成该数组。如果该数组中的索引为零,而不是之前生成的,则不会重复使用它并更新数组。

例如

int a;
while(produced_value[(a = rand() % MAXNO)]); //this loop find a that value in produced_value is 0
/* if a == 2 then should update array
    -------------------------
    | 0 | 0 | 1 | 0 | 0 | 0 |
    ---------~~~-------------
*/
produced_value[a] = 1; // mark 'a' as produced 

//Then use Unique int in the enum range
f[i] = static_cast <Fruit>(a);

答案 1 :(得分:1)

您的内部循环用于检查其他数组元素是否有重复项,但只要一个元素不重复,就会提前终止检查。换句话说,您不会搜索重复项,搜索非重复项

我们说i为2,f[0]Applef[1]Orange

内循环开始,j为0。

f[i] = static_cast <Fruit>(rand() % MAXNO);创建Orange。它应该被检测为重复,但它不是。

怎么来的?

这是因为在do...while条件下,您将f[2]f[0]进行比较。它们不相等,所以循环终止。

根据您的原始方法,快速解决此问题的方法是比较所有元素是否相等,理想情况是在单独的函数中:

bool exists(Fruit* begin, Fruit* end, Fruit fruit)
{
    for (Fruit* iter = begin; iter != end; ++iter)
    {
        if (*iter == fruit)
        {
            return true;
        } 
    }
    return false;
}

然后将你的循环改为:

for (int i = 0; i < size; i++)
{
    bool duplicate = false;
    do
    {
        f[i] = static_cast <Fruit>(rand() % MAXNO);
        duplicate = exists(f, f + i, f[i]);
    } while (duplicate);
}

但是这个解决方案仍有一些问题,最严重的(在我看来)是循环终止条件取决于随机运气。从理论上讲,该程序可能会循环很长时间甚至是永远。

更好的设计是使用您的老师显然不允许使用的所有标准C ++功能(安全容器和预定义算法),并重新考虑整个程序逻辑。其他答案和评论已经充分涵盖了这一点。

答案 2 :(得分:0)

如果你从一个集合中随机选择一个元素然后你就可以让那个元素再次被拾取,那么你得到重复是非常合理的。

我会建议另一种方法。为什么不首先对枚举数组进行随机排序,然后选择第一个size元素?通过这种方式,您不会获得重复项,并始终以随机顺序拥有第一个size元素。 另请注意,您有7个枚举,这意味着MAXNO应为7,否则int size = rand () % MAXNO;之类的表达将永远不会返回6,这是您的有效枚举列出Strawberry

如下所示,应该有效:

#include <iostream>
#include <chrono>
using namespace std;
const int MAXNO = MAXNO*2;
enum Fruit {Durian, Papaya, Apple, Orange, Mango, Jackfruit, Strawberry};
int main ()
{
    srand (time (NULL));

    Fruit ff [Strawberry+1] = {Durian, Papaya, Apple, Orange, Mango, Jackfruit, Strawberry};
    const int NIT = 7;
    for(int i=0 ; i < NIT ; i++ ){
        const int ii = (rand() % MAXNO);
        const int jj = (rand() % MAXNO);
        swap(ff[ii],ff[jj]);
    }

    //simply output the firse `size` element
    //from the randomly ordered array.
    const int size = rand () % MAXNO;
    for (int i=0;i<size;i++)
        cout<<ff[i]<<endl;

}

答案 3 :(得分:0)

首先,不要创建一个可变长度数组,只需使用vector:

  

果实f [大小];

枚举类型与此无关,因此要解决您的问题,您只需创建一个包含所有可能的int值的向量,然后随机播放向量(live example):

#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>


const int MAXNO = 6;

int main ()
{
     std::vector<int> v;
     v.reserve(MAXNO);

     for (int i = 0; i < MAXNO; ++i)
     {
        v.push_back(i);   
     }

    std::random_device rd;
    std::mt19937 g(rd());

    std::shuffle(v.begin(), v.end(), g);

    for (auto& e: v)
    {
        std::cout << e << " ";
    }
}
  

3 4 0 1 2 5

答案 4 :(得分:-1)

您可以使用此代码: 如果你有任何问题,请告诉我

enum Fruit {Durian, Papaya, Apple, Orange, Mango, Jackfruit, Strawberry};

private std :: vector :: RanomFruit() {     auto baseList = new List {Fruit :: Durian,Fruit :: Papaya,Fruit :: Apple,Fruit :: Orange,Fruit :: Mango,Fruit :: Jackfruit,Fruit :: Strawberry};

auto fruitArray = std::vector<Fruit>(7);
Random *random = new Random();

for (int i = 0; i <= 6; i++)
{
    int randNumber = random->Next(6 - i);
    fruitArray[i] = baseList[randNumber];
    baseList->RemoveAt(randNumber);

}

return fruitArray;

}