我尝试着创造一款带有骰子的游戏,我需要在其中添加一些随机数字(游戏邦注:即模拟骰子的边缘)。我知道如何在1到6之间

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

using namespace std;

int main() 
{ 
    srand((unsigned)time(0)); 
    int i;
    i = (rand()%6)+1; 
    cout << i << "\n"; 
}

并不是很好地工作,因为当我运行程序几次,这是我得到的输出:

6
1
1
1
1
1
2
2
2
2
5
2

所以我想要一个每次生成不同随机数的命令,而不是连续5次生成相同的随机数。是否有这样的命令?


当前回答

这里有一个解决方案。创建一个返回随机数的函数并放置它 在main函数之外,使其具有全局性。希望这能有所帮助

#include <iostream>
#include <cstdlib>
#include <ctime>
int rollDie();
using std::cout;
int main (){
    srand((unsigned)time(0));
    int die1;
    int die2;
    for (int n=10; n>0; n--){
    die1 = rollDie();
    die2 = rollDie();
    cout << die1 << " + " << die2 << " = " << die1 + die2 << "\n";
}
system("pause");
return 0;
}
int rollDie(){
    return (rand()%6)+1;
}

其他回答

我知道如何在c++中生成随机数,而不使用任何标头,编译器intrinsic或任何东西。

#include <cstdio> // Just for printf
int main() {
    auto val = new char[0x10000];
    auto num = reinterpret_cast<unsigned long long>(val);
    delete[] val;
    num = num / 0x1000 % 10;
    printf("%llu\n", num);
}

在运行一段时间后,我得到了以下数据:

0: 5268
1: 5284
2: 5279
3: 5242
4: 5191
5: 5135
6: 5183
7: 5236
8: 5372
9: 5343

看起来是随机的。

工作原理:

现代编译器使用ASLR(地址空间布局随机化)防止缓冲区溢出。 你可以不使用任何库生成一些随机数,这只是为了好玩。不要那样使用ASLR。

这段代码产生从n到m的随机数。

int random(int from, int to){
    return rand() % (to - from + 1) + from;
}

例子:

int main(){
    srand(time(0));
    cout << random(0, 99) << "\n";
}

每次生成不同的随机数,而不是连续六次生成相同的随机数。

用例场景

我把“可预测性”的问题比作一袋六块纸,每个纸上写着一个从0到5的值。每当需要一个新的数值时,就会从袋子里抽出一张纸。如果袋子是空的,那么数字被放回袋子。

根据这个,我可以创建一个算法。

算法

一个包通常是一个集合。我选择了bool[](也称为布尔数组,位平面或位图)来扮演袋子的角色。

我选择bool[]的原因是,每一项的索引已经是每张纸的值。如果论文需要在它们上面写任何东西,那么我将使用Dictionary<string, bool>代替它。布尔值用于跟踪数字是否已经绘制。

一个名为RemainingNumberCount的计数器被初始化为5,当选择一个随机数时,计数器会向下计数。这样,我们就不必在每次想要画一个新数字时,都要计算还剩下多少张纸了。

为了选择下一个随机值,我使用for..循环来扫描索引包,并使用一个计数器来计数,当索引为false时,称为NumberOfMoves。

NumberOfMoves用于选择下一个可用号码。NumberOfMoves首先被设置为0到5之间的随机值,因为有0..我们可以通过袋子的5个可行步骤。在下一次迭代中,NumberOfMoves被设置为0到4之间的随机值,因为现在有0..我们可以用4步穿过袋子。在使用这些数字时,可用的数字会减少,因此我们使用rand() % (RemainingNumberCount + 1)来计算NumberOfMoves的下一个值。

当NumberOfMoves计数器为零时,for..循环应该如下所示:

将当前值设置为与..循环的索引。 将包中的所有数字设置为false。 停止for..循环。

Code

上述解决方案的代码如下:

(将以下三个块依次放入主.cpp文件中)

#include "stdafx.h"
#include <ctime> 
#include <iostream>
#include <string>

class RandomBag {
public:
    int Value = -1;

    RandomBag() {
        ResetBag();

    }

    void NextValue() {
        int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);

        int NumberOfMoves = rand() % (RemainingNumberCount + 1);

        for (int i = 0; i < BagOfNumbersLength; i++)            
            if (BagOfNumbers[i] == 0) {
                NumberOfMoves--;

                if (NumberOfMoves == -1)
                {
                    Value = i;

                    BagOfNumbers[i] = 1;

                    break;

                }

            }



        if (RemainingNumberCount == 0) {
            RemainingNumberCount = 5;

            ResetBag();

        }
        else            
            RemainingNumberCount--; 

    }

    std::string ToString() {
        return std::to_string(Value);

    }

private:
    bool BagOfNumbers[6]; 

    int RemainingNumberCount;

    int NumberOfMoves;

    void ResetBag() {
        RemainingNumberCount = 5;

        NumberOfMoves = rand() % 6;

        int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);

        for (int i = 0; i < BagOfNumbersLength; i++)            
            BagOfNumbers[i] = 0;

    }

};

控制台类

我创建这个Console类是因为它可以很容易地重定向输出。

下面的代码中…

Console::WriteLine("The next value is " + randomBag.ToString());

...可以用……

std::cout << "The next value is " + randomBag.ToString() << std::endl; 

...然后这个Console类可以根据需要删除。

class Console {
public:
    static void WriteLine(std::string s) {
        std::cout << s << std::endl;

    }

};

主要方法

用法示例如下:

int main() {
    srand((unsigned)time(0)); // Initialise random seed based on current time

    RandomBag randomBag;

    Console::WriteLine("First set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nSecond set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nThird set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nProcess complete.\n");

    system("pause");

}

示例输出

当我运行程序时,我得到以下输出:

First set of six...

The next value is 2
The next value is 3
The next value is 4
The next value is 5
The next value is 0
The next value is 1

Second set of six...

The next value is 3
The next value is 4
The next value is 2
The next value is 0
The next value is 1
The next value is 5

Third set of six...

The next value is 4
The next value is 5
The next value is 2
The next value is 0
The next value is 3
The next value is 1

Process complete.

Press any key to continue . . .

关闭声明

该程序是使用Visual Studio 2017编写的,我选择使用. net 4.6.1使其成为Visual c++ Windows控制台应用程序项目。

我在这里没有做任何特别的事情,所以代码应该也适用于早期版本的Visual Studio。

使用模数可能会在随机数中引入偏置,这取决于随机数生成器。更多信息请看这个问题。当然,在随机序列中得到重复的数字是完全可能的。

尝试一些c++ 11特性以获得更好的分发:

#include <random>
#include <iostream>

int main()
{
    std::random_device dev;
    std::mt19937 rng(dev());
    std::uniform_int_distribution<std::mt19937::result_type> dist6(1,6); // distribution in range [1, 6]

    std::cout << dist6(rng) << std::endl;
}

有关c++ 11随机数的更多信息,请参阅此问题/答案。上面的方法并不是唯一的方法,但它是一种方法。

这里有一个解决方案。创建一个返回随机数的函数并放置它 在main函数之外,使其具有全局性。希望这能有所帮助

#include <iostream>
#include <cstdlib>
#include <ctime>
int rollDie();
using std::cout;
int main (){
    srand((unsigned)time(0));
    int die1;
    int die2;
    for (int n=10; n>0; n--){
    die1 = rollDie();
    die2 = rollDie();
    cout << die1 << " + " << die2 << " = " << die1 + die2 << "\n";
}
system("pause");
return 0;
}
int rollDie(){
    return (rand()%6)+1;
}