【问题标题】:Generating a random number for players in a dice game在骰子游戏中为玩家生成随机数
【发布时间】:2022-01-30 02:25:04
【问题描述】:

我正在编写一个简单的骰子游戏,两个玩家互相对战。获胜者是掷骰子时获得最大数字的人。但是,当我按 Enter 为第一个玩家生成一个随机数时,我只会得到新的空行。代码如下:

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

using namespace std;

int main()
{
    srand(time(0));
    
    int p1 = (rand() % 6) + 1;
    cout << "Player 1: Press enter to roll your dice" << endl;
    cin >> p1;

    
    int p2 = (rand() % 6) + 1;
    cout<<"Player 2: Press enter to roll your dice" << endl;
    cin >> p2; 
    

     if(p1 == p2) 
      {
          cout<<"You tied! \n";
      }
      
      else if(p1 > p2)
      {
          cout<<"You won! \n";
      }
      
      else
      {
          cout<<"You lost! \n";
      }
}

【问题讨论】:

  • 您意识到您正在用控制台中的每个用户条目覆盖您的“随机”数字,对吧?你认为cin &gt;&gt; p1p1 的前任住户从前两行有什么影响?而且由于格式化整数提取将过滤空白,因此您继续输入的换行符将被忽略,直到流满足请求(并覆盖 p1)或尝试出错。
  • cin&gt;&gt;p 用用户在终端中输入的内容覆盖 p 的值。
  • 对不起,先生,如果我没有明白您的意思,但我的程序的目标是,一旦我为每个玩家单击输入,将为两个玩家中的每一个生成一个新的随机数。
  • p1 = randcin &gt;&gt; p1,不能同时使用。与p2 相同。
  • 非常感谢!感谢大家的帮助!

标签: c++ random


【解决方案1】:

您试图提示用户放弃操作,但实际上要求他们向控制台提供整数输入(不方便,这会覆盖您刚刚拉出的随机抽奖)。

当流处于良好状态时:

cin >> p1;

将尝试从流中读取格式化整数。在此尝试期间,空格(包括换行符)将被忽略。因此,直到您 (a) 输入一个有效整数,(b) 输入任何将 fail 解析为整数的非空格,或 (c) 流已经在 EOF 中状态所以任何进一步的拉动而不清除都会失败,所以你只是盯着输入提示。

您似乎真正想要的是忽略输入流上的数据,直到输入换行符(或遇到 EOF)。一种方法是使用流ignore 成员。例如:

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

将从std::cin 提取所有输入并丢弃它,直到输入换行符或流到达错误或eof 状态。使用它,您可能真正想要的是:

#include <iostream>
#include <limits>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    srand(static_cast<unsigned>(time(0)));

    int p1, p2;

    cout << "Player 1: Press enter to roll your dice" << endl;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    p1 = (rand() % 6) + 1;

    cout << "Player 2: Press enter to roll your dice" << endl;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    p2 = (rand() % 6) + 1;

    cout << "Player 1: " << p1 << '\n';
    cout << "Player 2: " << p2 << '\n';

    if (p1 == p2)
    {
        cout << "You tied! \n";
    }

    else if (p1 > p2)
    {
        cout << "Player 1 won! \n";
    }

    else
    {
        cout << "Player 2 won! \n";
    }
}

我会使用&lt;random&gt; 进行实际抽奖,但这与您发布的代码中的根本问题无关。

【讨论】:

    【解决方案2】:

    要获得Enter 按键,您需要阅读换行符。在 C++ 中,这是相当冗长的:

    #include <iostream>
    #include <limits>
    
    std::cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
    

    请注意,您的程序在编写时确实不需要用户输入——发生的一切都与用户的操作无关。

    RNG 和鸽巢原理

    无论您的系统上的RAND_MAX 是什么,如果不是 32767,它可能是 2n-1 形式的数字。这不能很好地除以 6。例如,相比 2 或 5,您更有可能得到 0 的随机数。

    解决这个问题的方法是忽略超过 6 的倍数的数字。

    int multiples = RAND_MAX / 6;
    int new_rand_max = multiples * 6;
    

    如果来自rand() 的值不严格小于new_rand_max,那么你可以把它扔掉。

    while ((x = rand()) >= new_rand_max) ;
    

    现在你可以得到余数并返回:

    return x % 6;
    

    将所有这些都放在一个函数中,将 6 设为参数值,然后就可以开始了!

    int random( int n )
    {
      int max = (RAND_MAX / n) * n;
      int result;
      while ((result = rand()) >= max) ;
      return result % n;
    }
    

    并使用它:

    int p1 = random( 6 ) + 1;
    

    【讨论】:

      猜你喜欢
      • 2014-02-28
      • 1970-01-01
      • 1970-01-01
      • 2016-05-07
      • 2011-07-18
      • 2022-08-07
      • 2023-03-15
      • 1970-01-01
      • 2016-11-19
      相关资源
      最近更新 更多