【问题标题】:Rolling dice for an array掷骰子阵列
【发布时间】:2014-03-05 19:10:34
【问题描述】:

我需要这个程序做的是滚动 36000 2d6,以表格格式输出每个值的结果以及它出现的频率。不幸的是,我不熟悉数组的工作方式。这是我目前所拥有的:

int DiceArray()
{
    int rollOne = 0;
    int rollTwo = 0;
    int countrolls = 0;
    int sum = 0;
    for (countrolls=1; countrolls<=36000; countrolls++)
    {
        rollOne = (rand() % 6) + 1;
        rollTwo = (rand() % 6) + 1;
        sum = rollOne+rollTwo;
    }
}

所以,我需要一个骰子结果数组,我猜它看起来像 result[11],因为它列出了骰子总和的 2 到 12。然后我将不得不使数组多维;我需要第二列来显示结果。

因此,例如,两个的结果会发生 700 次。所以我需要像结果[2]这样的东西。那正确吗?无论如何,我将如何为我的数组获得正确的值?

我想对于结果数组,我只是这样列出它们,因为它们总是相同的:{2, 3, 4,... 12}

但是如何将总和输出到数组?

【问题讨论】:

标签: c++ arrays


【解决方案1】:

不确定,您在问什么,但您似乎需要一个简单的histogram。像这样:

void DiceArray()
{
  int rollOne = 0;
  int rollTwo = 0;
  int sum = 0;

  // This array holds histogram. hist[0] and hist[1] are always zero.
  int hist[13] = { 0 }; 

  for (int countrolls = 0; countrolls < 36000; ++countrolls)
  {
    rollOne = (rand() % 6) + 1;
    rollTwo = (rand() % 6) + 1;
    sum = rollOne+rollTwo;
    hist[sum]++;
  }

  for (int i = 2; i <= 12; ++i)
  {
    std::cout << i << ": " << hist[i] << std::endl;
  }
}

此函数打印以下内容:

2: 949
3: 1974
4: 2898
5: 3987
6: 5133
7: 6088
8: 4944
9: 3976
10: 3075
11: 1991
12: 985

【讨论】:

  • @Vincent 如果RAND_MAX2^31-1,则在26 的情况下,1 有 20 亿分之一的过度选择。可靠地检测到将采用10^18 试验的顺序(双重顺序不是错字——10^18 是基于统计经验法则的餐巾估计)。 rand() 成为一个糟糕的 RNG 的趋势将更多导致不均匀性(你如何拼写这个词?)——rand() 通常是一个非常糟糕的 RNG。
【解决方案2】:

这样的事情应该可以工作:

#include <iostream>
#include <random>
#include <array>

std::array<std::size_t, 13> DiceArray(const std::size_t count)
{
    std::random_device device;
    std::mt19937 engine(device());
    std::uniform_int_distribution<std::size_t> distribution(1, 6);
    std::array<std::size_t, 13> result = {};
    for (std::size_t i = 0; i < count; ++i) {
        ++result[distribution(engine)+distribution(engine)];
    }
    return result;
}

int main(int argc, char* argv[])
{
   auto result = DiceArray(36000);
   for (std::size_t i = 0; i < result.size(); ++i) {
       std::cout<<i<<" "<<result[i]<<std::endl;
   }
   return 0;
}

【讨论】:

    【解决方案3】:

    您对result[11]; 的想法会奏效。您也必须对其进行零初始化。

    int result[11] = {0};
    

    请记住,数组是从零开始的。所以这个数组将覆盖 0-10 的范围。您可以通过减去最小掷骰子来解决这个问题。为循环中的每个滚动增加相应的数组位置:

    ++result[sum-2];
    

    再次访问该值需要减去最小掷骰数:

    int numTwos = result[2-2];
    int numTens = result[10-2];
    

    【讨论】:

      【解决方案4】:

      这是一个 C++11 答案。基于this stack overflow answer

       typedef std::mt19937 MyRNG;  // the Mersenne Twister with a popular choice of parameters
      
       std::vector< unsigned > DiceArray(
         unsigned how_many_rolls, unsigned dice_count,
         MyRNG& rng
       )
       {
         // d6!
         std::uniform_int_distribution<uint32_t> d6(1,6);
         std::vector< unsigned > retval;
         retval.resize( dice_count * 6+1 );
         for (unsigned count = 0; count < how_many_rolls; ++count)
         {
           unsigned sum = 0;
           for(unsigned i = 0; i < dice_count; ++i) {
             sum += d6(rng);
           }
           retval[sum] += 1;
         }
         return retval;
       }
      

      接下来我们使用它:

      int main(int argc, char* argv[])
      {
        MyRNG rng;
        uint32_t seed_val = 0;       // populate somehow -- as `0` it will replicate the same sequence each time.  A common trick is to grab the current time or some other source of entropy
        rng.seed(seed_val); // avoid calling this more than once per experiment.  It resets the RNG, if you call it again it will repeat the same sequence of numbers as the first time.
        std::vector<unsigned> result = DiceArray(36000, 2, rng);
        for (unsigned i = 0; i < result.size(); ++i) {
           std::cout << i <<": " << result[i] << "\n";
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-08
        • 2021-04-06
        • 2012-02-29
        • 2015-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多