为什么我随机生成的数组只输出零?

时间:2017-10-11 04:07:02

标签: c++ arrays c++11 random

我正在编写一个应该作为彩票的代码。可用的彩票号码是1-50,其中有10个。用户应输入一个号码,如果用户的号码与10个随机抽奖号码中的一个匹配,则程序返回。我已经把所有这些部件都搞定了,但是有一个问题;所有10个彩票号码必须是唯一的。我有10个独特的数字1-50,但它们并非随机。我写到这一点的代码对我来说似乎是正确的,除了我知道有些东西丢失了(以及我可以清理我的代码的事实,但我现在正专注于目标)。现在,如果我运行该程序,它将返回十个零。我需要彩票阵列中的每个元素都是1-50的唯一数字,并且每次运行程序时都会生成不同的数字集。任何帮助将不胜感激。

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

using std::cout; using std::cin; using std::endl;

void printOut(int[]);
void draw(int[]);
bool check();
int fillFunc[10];

int main()
{
    const int arraySize = 10;
    int win[arraySize] = {};

    srand((unsigned)time(NULL));

    draw(win);
    cout << "Your lottery numbers are: ";
    printOut(win);
}

void draw(int fillFunc[])
{
    int i;
    for (i = 0; i < 10; i++)
    {
        if (check() == true)
            continue;
        fillFunc[i] = 1 + rand() % 50;
    }
}

void printOut(int fillFunc[])
{
    for (int i = 0; i < 10; i++)
    {
        cout << " " << fillFunc[i];
    }
    cout << "\n";
}

bool check()
{
    for (int i = 0; i < 10; ++i)
    {
        if (fillFunc[i] == i)
            return true;
    }
    return false;
}

(也不要问我为什么数组有名称&#34; win&#34;,这是我的教授要我称之为的)

4 个答案:

答案 0 :(得分:1)

要回答您在评论中更新的问题,您需要考虑改组算法。

我会告诉你如何做到这一点,这是O(n)所以你不必循环&#34;循环&#34;通过您当前的数字列表,并继续检查新号码是否已被选中......

你的彩票最大数量是50,所以制作一个大小为50的数组,如下所示:

  • lotteryNumber [0] = 1
  • lotteryNumber [1] = 2
  • ...
  • lotteryNumber [49] = 50

选择一个号码放入&#34;选择&#34;数字数组...

indexToLotteryNumbers = rand() % 50 - numbersPickedSoFar;
randomLotteryNumber[i++] = lotteryNumber[ indexToLotteryNumbers ];

// this is the key "trick"
swap(&lotteryNumber[ indexToLotteryNumbers ], &lotteryNumber[49-numbersPickedSoFar]); 

numbersPickedSoFar++;

理论

  1. 随机数是索引而不是实际值
  2. 通过交换您使用外部元素选择的数字,您不必关心您的随机数生成器是否选择相同的索引,因为下次将会有所不同。
  3. 看一个小例子......说你有1 2 3 4

    • rand()生成&#34; 2&#34;
    • 所以你的第一个#是2(假设在这里基于1的索引)现在你交换了(第二个)元素的(第4个)元素,现在你有1 4 3 | 2
    • (这里| 2表示你不能再次选择那个号码,因为它在...之外 随机#generator范围)但你减少随机#生成 1-4至1至3
    • rand()生成&#34; 1&#34;所以你的号码是&#34; 1&#34;然后你用&#34;外部&#34;交换它未命中的数字3 4 | 1 2
    • rand()生成
    • &#34; 2&#34;再次!这次你的彩票号码是4 ......等等。

    我希望这是有道理的。

答案 1 :(得分:1)

因为check()始终返回true。在开始时,数组用零填充,因此checktrue作为win[0]==0返回,并且永远保持为真,因为没有任何更改该值。因此,在draw中,您始终会转移到continue并且永远不会修改任何内容。

要解决这个问题,可以采用一种方法来改变1-50的序列,并提取混洗数组的前10个值。您可以使用非常简单的Fisher-Yates algorithm

答案 2 :(得分:0)

fillFunc[i]为10时,您只为i分配一个值,这是一个超出范围的访问权限。将作业移动到循环内部。

你也有其他问题。如果执行continue,则只需在数组中保留一个条目。

您应该尝试在程序中添加大量输出语句,以便更轻松地了解它正在做什么。如果您愿意,可以使用调试器逐步完成它。

答案 3 :(得分:0)

考虑到你的限制,这就是我要做的。在填充数组时,不要检查数字是否唯一,只需将数组传递给选择数字的函数,以便它可以返回唯一值。

我还删除了冗余的全局数组。如果您忘记将正在使用的本地数组传递给任何函数,它可能是错误的来源。

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

using std::cin;
using std::cout;
using std::endl;

int getUniqueNumber(int fillFunc[])
{
    while(true)
    {
        //pick number
        int val = 1 + rand() % 50;
        //assume it's unique
        bool unique = true;
        for (int i = 0; i < 10; ++i)
        {
            //if another number matches, it isn't unique, choose again
            if (fillFunc[i] == val)
            {
                unique = false;
                break;
            }
        }
        //if it is unique, return it.
        if (unique)
        {
            return val;
        }
    }
    //never reached, but avoids an all control paths must return a value warning.
    return -1;
}

void draw(int fillFunc[])
{
    for (int i = 0; i < 10; i++)
    {
        fillFunc[i] = getUniqueNumber(fillFunc);
    }
}

void printOut(int fillFunc[])
{
    for (int i = 0; i < 10; i++)
    {
        cout << " " << fillFunc[i];
    }
    cout << "\n";
}

int main()
{
    srand((unsigned)time(NULL));
    const int arraySize = 10;
    int win[arraySize] = {};
    draw(win);
    cout << "Your lottery numbers are: ";
    printOut(win);
    return 0;
}

还有其他一些可能更好的方法来选择范围内的唯一数字,但我只是简单地实现和解释。您可以在这些问题中阅读其他一些方法:

Unique random numbers in an integer array in the C programming language

Unique (non-repeating) random numbers in O(1)?