我正在开发一个openGL项目,而我的rand函数并没有给我足够大的随机范围。 我的任务是编写一个钻石程序,一个钻石在屏幕上居中,5个随机放在屏幕的其他地方。发生的事情是我的中心钻石应该是它的位置,而其他五颗钻石则聚集在一起,中心左侧有一小部分随机。我已经包含了绘制钻石的功能。
void myDisplay(void)
{
srand(time(0));
GLintPoint CenterPoint;
int const size = 20;
CenterPoint.x = screenWidth / 2;
CenterPoint.y = screenHeight / 2;
glClear(GL_COLOR_BUFFER_BIT);
drawDiamond(CenterPoint, size);
for (int i = 0; i < 5; i++)
{
GLfloat x = rand() % 50 + 10;
GLfloat y = rand() % 200 + 100;
GLfloat size = rand() % 100;
GLintPoint diam = {x,y};
drawDiamond(diam, size);
}
如果需要更多代码,请告诉我,我会进行编辑。有没有人对我如何纠正这个有任何想法?我已经“玩弄”了rand()函数的数量,但实际上并没有做太多。他们似乎仍然只是在屏幕上的不同点聚集。我很感激帮助。万一有人需要知道,我在VS2012中创建了这个。
答案 0 :(得分:10)
此功能没有业务:
srand(time(0));
这应该在你的程序开始时被称为一次(一个好地方就在main()
里面);而且大多数 - 肯定不在您的显示例程中。一旦种子被设置,你就不应该再为你的过程再做一次,除非你想重复一个先前的序列(从它的外观来看,你没有)。
也就是说,我强烈建议您使用C ++ 11标准库附带的<random>
中的功能。有了它,您可以建立分配(例如:uniform_int_distribution<>
),它将为您完成大部分模数工作,并正确解释这些事情可能遇到的问题(Andon指出一个关于某些数字基于模数的可能性)。
花一些时间与<random>
。这很值得。使用您正在使用的三个范围的示例:
#include <iostream>
#include <random>
using namespace std;
int main()
{
std::random_device rd;
std::default_random_engine rng(rd());
// our distributions.
std::uniform_int_distribution<> dist1(50,60);
std::uniform_int_distribution<> dist2(200,300);
std::uniform_int_distribution<> dist3(0,100);
for (int i=0;i<10;++i)
std::cout << dist1(rng) << ',' << dist2(rng) << ',' << dist3(rng) << std::endl;
return EXIT_SUCCESS;
}
输出(显然会有所不同)。
58,292,70
56,233,41
57,273,98
52,204,8
50,284,43
51,292,48
53,220,42
54,281,64
50,290,51
53,220,7
是的,真的就是这么简单。就像我说的那样,那个图书馆是这只猫的睡衣。它提供了许多更多的东西,包括随机正态分布,不同的引擎后端等。我强烈建议您检查它。
答案 1 :(得分:2)
正如WhozCraig所提到的那样,每次拨打myDisplay (...)
时,随机播放随机数生成器都是一个坏主意。这是因为time (NULL)
的粒度为1秒,而在实时图形中,您通常每秒绘制一次以上的场景。因此,每当您在不到1秒的时间内调用myDisplay (...)
时,您就会重复相同的随机数序列。
此外,对rand (...)
的调用使用模运算会对返回值的质量产生负面影响。这是因为它改变了发生数字的概率分布。首选技术应该是将rand (...)
转换为float,然后除以RAND_MAX,然后将此结果乘以所需的范围。
GLfloat x = rand() % 50 + 10; /* <-- Bad! */
/* Consider this instead */
GLfloat x = (GLfloat)rand () / RAND_MAX * 50.0f + 10.0f;
虽然,想一想。如果要在2行之后将它们存储在整数数据结构中,为什么要将GLfloat
用于x和y?