fork download
  1. #include <iostream>
  2. #include <random>
  3. #include <numeric>
  4. #include <iterator>
  5.  
  6. // seed the generator
  7. std::mt19937 generator((std::random_device())());
  8.  
  9. struct DieInterface
  10. {
  11. virtual ~DieInterface() = default;
  12. virtual unsigned operator()() const = 0 ;
  13. virtual unsigned sides() const = 0;
  14. };
  15.  
  16. struct Die : public DieInterface
  17. {
  18. Die(unsigned nSides) : _dist(1, nSides) {}
  19.  
  20. unsigned operator()() const { return _dist(generator); }
  21. unsigned sides() const { return _dist.b(); }
  22.  
  23. private:
  24. mutable std::uniform_int_distribution<unsigned> _dist;
  25. };
  26.  
  27. struct LoadedDie : public DieInterface
  28. {
  29. using distribution = std::uniform_int_distribution<unsigned>;
  30.  
  31. LoadedDie(unsigned nSides, unsigned loadedFace, unsigned weight_out_of_100)
  32. : _dist(1, nSides - 1), _face(loadedFace), _weight(weight_out_of_100) {}
  33.  
  34. unsigned operator()() const
  35. {
  36. using param_type = distribution::param_type;
  37.  
  38. if (_dist(generator, param_type{ 1, 100 }) >= _weight)
  39. return _face;
  40. else
  41. {
  42. unsigned face = _dist(generator);
  43.  
  44. if (face >= _face)
  45. ++face;
  46.  
  47. return face;
  48. }
  49. }
  50.  
  51. unsigned sides() const { return _dist.b() + 1; }
  52.  
  53. private:
  54. mutable distribution _dist;
  55.  
  56. unsigned _face;
  57. unsigned _weight;
  58. };
  59.  
  60.  
  61. // Take two dice objects, roll them, and return the sum
  62.  
  63. template <typename iter_type>
  64. unsigned roll(iter_type beg, iter_type end)
  65. {
  66. using die_type = const DieInterface&;
  67. return std::accumulate(beg, end, 0u, [](unsigned x, die_type d) { return x + d(); });
  68. }
  69.  
  70. int main()
  71. {
  72. Die dice[] = { Die(6), Die(10) };
  73.  
  74. std::cout << "\nRolling two normal dice:\n";
  75. for (int i = 0; i < 10; ++i)
  76. std::cout << roll(std::begin(dice), std::end(dice)) << '\n';
  77.  
  78. {
  79. const unsigned faces = 6;
  80. const unsigned loaded_face = 6;
  81. const unsigned weight = 50;
  82.  
  83. LoadedDie die(faces, loaded_face, weight);
  84.  
  85. std::cout << "\n\nRolling the loaded die with a 50 percent chance to roll max val:\n";
  86. for (int i = 0; i < 10; ++i)
  87. std::cout << die() << '\n';
  88. }
  89.  
  90. {
  91. const unsigned faces = 20;
  92. const unsigned loaded_face = 5;
  93. const unsigned weight = 50;
  94.  
  95. LoadedDie die(faces, loaded_face, weight);
  96.  
  97. std::cout << "\n\nRolling a 20-sided loaded die: (" << loaded_face << "is loaded)\n";
  98. for (int i = 0; i < 10; ++i)
  99. std::cout << die() << '\n';
  100. }
  101. }
Success #stdin #stdout 0s 3432KB
stdin
Standard input is empty
stdout
Rolling two normal dice:
9
12
11
11
9
9
8
9
13
9


Rolling the loaded die with a 50 percent chance to roll max val:
6
2
6
6
5
4
6
5
1
2


Rolling a 20-sided loaded die: (5is loaded)
5
5
14
3
5
20
10
13
18
5