2017-10-11 60 views
0

我正在写一个应该作为彩票的代码。可用的彩票号码是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; 
} 

(也别问我为什么数组的名称为“赢”,这是我的教授要我叫什么)

+0

这就是为什么大括号很重要。好的缩进也会给你一个线索,是不对的。 –

+0

你应该看这个:[兰特()是有害的(https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful) –

+1

什么是'检查()'应该被检查? –

回答

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)?

0

你只当i是10的值赋给fillFunc[i] ,这是一个超出界限的访问。将分配移至循环内部。

您还有其他问题。如果你做continue,你只需要在数组中未设置一个条目。

您应该尝试向程序中添加大量输出语句,以便您更轻松地理解它正在执行的操作。如果您愿意,可以使用调试器来逐步完成。

+0

通过'int win [arraySize] = {};'将条目初始化为'0';他们不是未设置 –

+0

我已经调整了我的循环,现在又产生了随机数,这很好,但正如你所说的那样,继续什么都不做。我想我的问题是我如何使用我的检查功能来检测数字已经在数组中使用,并在其位置产生一个不同的数字? – Breinz

+0

哦,我现在明白了。更新了我的答案。 –

1

要回答你的问题,你在你需要考虑一个洗牌的算法评论更新。

我会告诉你如何做到这一点O(n),所以你不必“循环”通过你当前的数字列表,并继续检查,看看是否已经选择了新的数字。 ..

您的彩票最大数量是50,从而使尺寸50的阵列如下:

  • lotteryNumber [0] = 1
  • lotteryNumber [1] = 2
  • .. 。
  • lotteryNumber [4 9] = 50

挑选一个数字放入您的“选定”数字数组...

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

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

numbersPickedSoFar++; 

理论

  1. 的随机数索引,而不是实际值
  2. 通过交换,你与外构件采摘的数量,您不,如果你的随机数发生器采关心相同的索引,因为它下一次会有所不同。

看一个小例子说,你有1 2 3 4

  • rand()产生 “2”
  • 所以你的第一#为2(这里假设为基础1索引)现在你交换的(第二)元素(4)元素,现在你有1 4 3 | 2
  • (这里| 2意味着你不能再挑选号码,因为它是 随机#发电机范围之外),但是你减少随机#代码从 1-4到1到3
  • rand()产生 “1”,所以你的电话号码是 “1” 和你交换,与 “外” 松绑号码3 4 | 1 2
  • rand()产生
  • “2” 了!这次你的彩票号码是4 ...等等。

我希望这是有道理的。

+0

看看[Fisher-Yates_shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle)。 – Jarod42

1

因为check()总是返回true。一开始,该数组被零填充,从而check回报truewin[0]==0而作为没有什么变化该值仍然是正确的,直到永远。所以在draw你总是分支到continue并且永远不会修改任何东西。

为了解决这个问题的一种方式可能是洗牌1-50的序列,并提取所述混洗阵列的第一10个值。您可以使用非常简单的Fisher-Yates algorithm

相关问题