非重复序列的非重复数字

时间:2014-12-14 14:21:54

标签: c++ random

我会尽力描述我的问题,因为这是我第一次来这里:)

所以,我必须在C ++中编写一个程序,因为你可能或者可能没有从标题中猜到,打印出一系列随机数字,这些随机数字不会在数字本身和系列中重复。

我有4个“插槽”来填充数字系列。数字可以从0到4随机化(不能重复)。

我的意思是:

SLOT 1:1 3 2 4

SLOT 2:3 1 4 2< -----如您所见,它们不会水平重复,也不会垂直重复

SLOT 3:2 4 3 1

SLOT 4:4 2 1 3

这是我提出的代码,直到我被卡住(这是一个可怕的丑陋代码,我知道)

    void MC_Slot_Rand()
{
    text.setDefaultColor("white");//don't mind this
    srand((unsigned)time(NULL));
    int n1;
    int n2;
    int n3;
    int n4;
    int number;
    int slotN = 0;
    int slotN_2 = 1;
        while (slotN < dim)
        {
            color.red();//don't mind this
            cout << "SLOT " << slotN_2 << ":  ";
            color.white();//don't mind this either
            n1 = 1;//RESET 
                   //for some reason, if i don't put 1
                   // the program repeats the numbers
            n2, n3, n4 = 10;//RESET
            do
            {
                number = rand() % 4;
            } while (number == n1);
            n1 = number;

            do
            {
                number = rand() % 4;
            } while (number == n1);
            n2 = number;

            do
            {
                number = rand() % 4;
            } while (number == n1 || number == n2);
            n3 = number;

            do
            {
                number = rand() % 4;
            } while (number == n1 || number == n2 || number == n3);
            n4 = number;

            //cout << n1 << n2 << n3 << n4;//debug
            MC_ENUM(n1);
            MC_ENUM(n2);//this function simply takes the number and
                        //transforms it into a letter using a switch statement
                        // example: 0 = A, 1 = B, etcetera...

            MC_ENUM(n3);
            MC_ENUM(n4);
            ut.spacer(3);//this function does cout<<endl; as many times
                         //as the number specifies
            slotN++;
            slotN_2++;

        }

}//END OF FUNCTION

这段代码的作用是简单地打印4系列非重复数字,但数字是垂直重复的!当然,我不希望这种情况发生。

我希望那里比我更有经验的人可以帮助我:)。

非常重要:如果您想尝试使用此代码,请取消使用don't mind thisMC_ENUM();函数以及ut.spacer();评论的行,因为它们是我的库的一部分并赢得了'与你合作:P

感谢您的时间。

4 个答案:

答案 0 :(得分:0)

在这里你能做什么: 当您需要数字是唯一的,而不是生成随机数时,您所做的是生成所需的所有唯一数字的数组。在这种情况下,它是一个长度为4的数组,其值为[1,2,3,4]。 现在,使用已知良好的混洗算法随机地对阵列进行随机排列,该算法保证所有排列的机会几乎相等。如果您想阻止某个数字出现在同一个索引中,您可以轻松地在随机数中添加一个规则,该规则需要为每个随机数字添加唯一的位置。

这是另一种方法:这种方法特别适合小长度。生成所有可能的排列,然后随机选择一个排列。为了维护您的额外要求,您只需忽略不合适的排列。这种方法的一个明显优势是它完全是确定性的。

答案 1 :(得分:0)

据我所知,你正在做的是产生1-4号数字的所有排列的随机向量。

幸运的是答案在标准库中:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool column_match(const vector<int>& v1, const vector<int>& v2)
{
    auto N = std::min(v1.size(), v2.size());
    for (size_t i = 0 ; i < N ; ++i) {
        if (v1[i] == v2[i])
            return true;
    }
    return false;
}

int main()
{
    vector<int> nums = { 1, 2, 3, 4 };

    vector<vector<int>> series;
    do {
        series.push_back(nums);
    } while (next_permutation(begin(nums), end(nums)));

    random_shuffle(begin(series), end(series));

    vector<vector<int>> result;
    copy_if(begin(series), end(series), back_inserter(result), [&](const auto& candidate){
        return !any_of(begin(result), end(result), [&](const auto& check){
            return column_match(candidate, check);
        });
    });

    for (const auto& s : result) {
        copy(begin(s), end(s), ostream_iterator<int>(cout, ","));
        cout << endl;
    }

    return 0;
}

示例输出:

4,3,1,2,
3,2,4,1,
1,4,2,3,
2,1,3,4,
Program ended with exit code: 0

答案 2 :(得分:0)

我认为你应该这样做,这是我的想法

首先,你应该像a [4] [4]那样定义arry,当它产生一个数字你将数字存储在arry中,然后产生下一个numbet,将它与水平中的其他数据进行水平比较,如果它重复并且然后生成下一个,如果没有并存储它

当第一行完成时,在产生数字的第二行中,你不仅要水平地将它与此行进行比较,还要垂直地与其他行进行比较

就像这一行在线,你会成功。

答案 3 :(得分:0)

你可以作弊。您的问题中已经有一个解决方案:

1 3 2 4
3 1 4 2
2 4 3 1
4 2 1 3

您可以使用该解决方案生成其他人。首先,将该解决方案转换为字母:

A C B D
C A D B
B D C A
D B A C

其次,选择从四个字母A,B,C,D到四个数字1,2,3,4的随机映射。用您的映射中的相应数字替换网格中的字母。这将给出一个解决方案。

对于更多可能的解决方案,您可以在网格中交换列或交换网格中的行,但可能不允许某些生成的网格。如果你这样做,你需要更仔细地检查。