掷骰子程序在每次运行时都会生成相同的随机数序列
我编写了一个程序,可以掷出具有用户指定面数的骰子。问题是,它太可预测了。
我使用的是CodeBlocks IDE,编译器是GCC。该程序在调试和发布版本中都可以很好地编译,但无论我选择什么构建选项,可执行文件每次运行时都会返回相同的值。我不能接受这个,因为它的预期用途是作为桌面 RPG 工具,如果聪明的玩家知道骰子滚动的模式,那么他们会相对容易作弊。
解决这个问题最简单的方法是什么?
这是来源:
#include <iostream> /* for input and output */
#include <cstdlib> /* for random numbers */
using namespace std;
void rolldie() {
cout << "How many sides to the die?" << endl << "D";
int die;
cin >> die;
int roll = rand() % die +1;
cout << endl << "The die rolled " << roll << endl << endl << "Roll another? (Y for yes, anything else for no; Capitalization counts) ";
}
int main() {
rolldie();
char again;
cin >> again;
while (again == 89) {
rolldie();
cin >> again;
}
return 0;
}
I wrote a program that rolls a die with a user-specified number of sides. The problem is, it's too predictable.
I'm using the CodeBlocks IDE, and the compiler is GCC. The program compiles nicely as both debug and release builds, but no matter what build option I choose, the executable will return the same values every time it's run. I can't have this, because its intended use is as a tabletop RPG tool, and it would be relatively easy for a smart player to cheat if they knew the pattern by which the dice would roll.
What is the easiest way to fix this problem?
Here's the source:
#include <iostream> /* for input and output */
#include <cstdlib> /* for random numbers */
using namespace std;
void rolldie() {
cout << "How many sides to the die?" << endl << "D";
int die;
cin >> die;
int roll = rand() % die +1;
cout << endl << "The die rolled " << roll << endl << endl << "Roll another? (Y for yes, anything else for no; Capitalization counts) ";
}
int main() {
rolldie();
char again;
cin >> again;
while (again == 89) {
rolldie();
cin >> again;
}
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您没有为随机数生成器播种。我不会下载您的 zip 文件,但由于您使用的是 MinGW,我想您可能想查看
srandom(3)
或srand(3)
。You didn't seed your random number generator. I'm not going to download your zip file, but since you're using MinGW, I guess you probably want to look into
srandom(3)
orsrand(3)
.访问 http://www.boost.org 并获取他们的随机数生成器库。这是我见过的最好的随机生成器,特别是对于 C++ 来说,在任何地方都很难找到像样的随机生成器。
他们有大量非常棒的库,可用于 C++ 中的各种内容,因此我强烈建议浏览它们,但这应该可以解决您所遇到的输出过于可预测的问题。只需确保您阅读了有关如何使用它的说明,并首先正确地为生成器播种。
至于随机生成器的种子使用什么,c++ 中常用的是 time(NULL)(在 time.h 或 ctime 中找到)。这只是返回一个数字,表示自 1970 年 1 月 1 日以来的当前时间(以秒为单位)。由于每次运行程序时都会返回不同的值,因此它对于更简单的随机数很有用,如果您将其与 boost 的随机生成器结合起来,您的输出应该看起来不错。
Go to http://www.boost.org and get their random number generator library. It's the best random generator I've seen, particularly for c++ where it's really hard to find a decent one anywhere.
They have a TON of really awesome libraries for all sorts of things in c++, so I highly recommend browsing through them, but this should solve the problems you're having of the output being too predictable. Just make sure you read the instructions for how to use it and properly seed the generator first.
As far as what to use for the seed to a random generator, a common one to use in c++ is time(NULL) (found in time.h or ctime). This just returns a number representing the current time in seconds since Jan 1, 1970. Since it will return a different value every time the program is run, it's useful for simpler random numbers, and if you combine that with boost's random generator your output should look good.
首先,CStdLib.Rand 并不是一个很好的 PRNG。然而,我对 C++ 的了解还不够深入,无法知道 C++ 世界中什么是更好的;我会看看推荐用于密码学的 PRNG。对于大多数非安全目的来说,这个应该足够好。
更重要的是,您还没有“播种”PRNG。这不会像 .NET 等某些其他语言的内置 PRNG 那样自动发生。如果没有播种,那么种子始终是恒定的(可能为零),因此 PRNG 算法生成的数字流将始终相同。最常见的种子将基于当前时间(最好是“滴答”分辨率,因此很难准确猜测调用检索到了毫秒的几分之一);种子数据的其他良好来源包括鼠标光标的位置、RAM 或 HDD 的上次访问地址或来自连接设备的真正随机数据(在线赌场的服务器通常具有真正的 RNG 设备,可提供实际随机环境数据可用于播种 PRNG)。
Well, first, CStdLib.Rand is not a great PRNG. However I don't know C++ well enough to know what's better in the C++ world; I would look at PRNGs recommended for cryptography. This one should work well enough for most non-security purposes.
More importantly, you haven't "seeded" the PRNG. This does not happen automatically as it is with certain other languages' built-in PRNGs like .NET's. If it's not seeded, then the seed is always constant (probably zero) and so the stream of numbers produced by the PRNG algorithm will always be the same. The most common seed would be based on the current time (preferably at "ticks" resolution so it's hard to guess exactly what fraction of a millisecond was retrieved by the call); other good sources of seed data include the position of the mouse cursor, the last-accessed address of RAM or the HDD, or truly random data available from an attached device (servers for online casinos often have true RNG devices that provide actually random environmental data that can be used to seed a PRNG).
简单的答案:
您希望每次都使用来自某个源的输入来为随机数生成器播种,无论是系统(如时间)、用户、文件等。
详细答案:
默认的随机数生成器 rand() 对于大多数情况来说都非常平庸,但有关 rand 的更详细答案请参阅此:在 C++ 中使用 rand() 函数的正确方法是什么?
我的建议:
我的公司使用随机数,这些随机数需要不可预测他们每天都会使用 Mersenne Twister 算法的变体,至于在游戏中使用,您会发现其性能绰绰有余。
作为额外的好处,它已经以各种形式用 C 和 C++ 实现,因此将其集成到任何项目中都非常简单。
例如: http://www-personal.umich.edu/~wagnerr/MersenneTwister .html
或:http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/
Simple answer:
You want to seed your random number generator each time with input from some source, be it the system (like the time), user, a file, or so on.
Detailed answer:
The default random number generator rand() is very mediocre for most things, but see this for a more detailed answer about rand: What's the Right Way to use the rand() Function in C++?
My recommendation:
My company works with random numbers that are required to be unpredictable on a daily basis and they use a variation of the Mersenne Twister algorithm and as for use in a game you'll find its performance more than adequate.
As an added bonus, it has been implemented in C and C++ in various forms and so integrating it into any project is very simple.
For example: http://www-personal.umich.edu/~wagnerr/MersenneTwister.html
or: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/