【问题标题】:Picking random chars from char array?从字符数组中选择随机字符?
【发布时间】:2020-02-04 07:27:46
【问题描述】:

我是 C++ 新手,本周要完成一项非常艰巨的任务。我不会详细介绍它,因为我不想为我完成工作,但是谁能指出我将如何从多维字符串数组中选择随机字符的正确方向?

char gameZero[16][6] = { {'A','A','C','I','O','T'}, {'A','H','M','O','R','S'}, {'E','G','K','L','U','Y'}, {'A','B','I','L','T','Y'}, {'A','C','D','E','M','P'}, {'E','G','I','N','T','V'}, {'G','I','L','R','U','W'}, {'E','L','P','S','T','U'}, {'D','E','N','O','S','W'}, {'A','C','E','L','R','S'}, {'A','B','J','M','O','Q'}, {'E','E','F','H','I','Y'}, {'E','H','I','N','P','S'}, {'D','K','N','O','T','U'}, {'A','D','E','N','V','Z'}, {'B','I','F','O','R','X'} };

目标是打印出这些字符的 4x4 棋盘,在每场游戏开始时从每个数组中随机选择一个字符,这样棋盘就不会是相同的。

任何有关如何执行此操作的建议/提示将不胜感激 - 谢谢!

编辑:

我已经到了可以从两个数组生成随机索引的地步,但是我目前的做法只输出一个字符,而我需要从数组中的 16 个分类中的每个分类中获取一个字符。关于如何从每个输出一个的任何想法?我想我必须将索引生成器放在某种循环中。

mt19937 gen(time(nullptr)); // random number generator

// used to generate random number in specific range 
uniform_int_distribution<int> random_outer(0, outer_size - 1);
uniform_int_distribution<int> random_inner(0, inner_size - 1);

int index_outer = random_outer(gen); // used to generate random outer index
int index_inner = random_inner(gen); // used to generate random inner index

cout << gameZero[index_outer][index_inner] << endl;

【问题讨论】:

  • 只是为了更好地理解您的问题,例如,如果我们在 4x4 中为第一个元素随机选择“A”,那么其余 15 个元素中的任何一个都不能是“A”?
  • @Abdulkareem 嗨!棋盘上可以出现多少个重复字母没有限制,本质上是对棋盘进行洗牌,以显示 16 个数组中的每一个中的一个字符的随机集合。因此,从技术上讲,如果每个阵列中有一个 A,那么有一个 4x4 的 A 板就可以了。 (那不会是一个非常有趣的游戏,但目前没有什么可以告诉我的)
  • 如果是二维数组,维度为16和6,则生成两个随机整数值。一个在0 和15 之间,另一个在0 和5 之间。然后使用该对值作为索引来访问数组的元素。有大量关于在 C++ 中生成随机整数值的信息。
  • @Peter 在做了更多的挖掘之后,我认为这将是最好的方法,现在正在尝试。谢谢!
  • 所以一个策略可以从初始化一个指针开始,以指向 16 个数组中的第一个数组,然后在第一次迭代中 pic 一个介于 0 和 5 之间的随机数(您可以使用rand())和提前指针通过那么多位置,将该指针值分配给新数组的当前元素。在下一次迭代中,使用您从 rand()i.e. 获得的结果推进 ponter,通过 ('rand( )' - 5 +1)

标签: c++ arrays random boggle


【解决方案1】:

您可以使用以下算法:

  • 在区间[0, std::size(gameZero )[中生成随机数x
  • 在区间[0, std::size(gameZero[0])[中生成随机数y
  • 访问gameZero[x][y] 获取二维数组的随机字符。

【讨论】:

  • 关闭一个错误。范围需要分别为 [0, std::size(gameZero) - 1] 和 [0, std::size(gameZero[0]) - 1]。
  • @Peter [0, std::size(gameZero) - 1] 和 [0, std::size(gameZero)[ 是一回事。反括号表示半开区间。
  • 区间开闭端的现代数学符号是)。 [ 整数范围的开放端是过时的,即使在数学文献中也是如此,并且在过去 100 年左右的时间里被大多数活跃的数学出版物积极劝阻。
  • @Peter 我以前没听说过。您的索赔有参考资料吗?这两种符号都在 ISO 80000-2:2009 标准中。我在这里使用括号符号来提高可读性,使其易于与以右括号结尾的值表达式区分开来。
【解决方案2】:
  • 提供一个包含 6 项的 int 列表。
  • 使用 0 - 5 的索引值对其进行初始化。
  • 对于板上的每个单元格://from 0 - 15.
    • 洗牌 int 列表。
    • 对于您拥有的每个 4x4 板://假设最多 6 个。
      • 在索引 iBoard 处使用 int 列表中的项目设置当前板的当前单元格。
        • //example: board[iBoard][iCell] = listInt[iBoard]

【讨论】:

    【解决方案3】:

    鉴于您的gameZero 类型为char[16][6],您只需要生成一个随机数,该随机数表示在(0, sizeof gameZero) 范围内与gameZero 开头的偏移量。任何基本类型 (char, int, double, etc...) 的数组都保证在内存中是连续的。此外,在您的类型为char 的情况下,每个char 都是1 字节。因此,您可以通过计算距数组开头的偏移量来访问gameZero 中的任何字符。

    如您所见,C++ 提供了自己的Pseudo-random number generation。您可以选择任何一种分发引擎来创建随机分发。当您需要一个随机数时,使用您的发行版进行调用,传递您创建的实例作为其参数的引擎。例如,要使用std::mersenne_twister_engine 创建随机分布,您可以这样做:

    #include <random>
    ...
        char gameZero[16][6] = {{'A','A','C','I','O','T'}, 
        ...
        std::random_device rd;              /* random device/seed */
        std::mt19937 gen(rd());             /* standard mersenne_twister_engine */
        std::uniform_int_distribution<> dist(0, sizeof gameZero);    /* dist */
    

    然后,为了选择代表gameZero 内偏移量的随机元素,您只需使用以下命令请求一个随机数:

            int off = dist(gen);        /* get random offset in gameZero */
    

    从偏移量,gameZero 中的 [x][y] 元素可以简单地通过使用数组中的列数(在您的情况下为 6)来计算,例如

            int x = off / 6,            /* compute row from offset */
                y = off - 6 * x;        /* compute col from offset */
    

    (注意:整数除法是有意计算上面的x(行)值)

    然后您可以简单地使用gameZero[x][y] 访问随机元素。

    例如,如果在循环中请求随机偏移量并按照上述说明计算 [x][y] 索引,则可以输出偏移量、计算的索引和该索引处的字符,类似于以下内容:

    $ ./bin/randarr2d
    92 - gameZero[15][2] = F
     9 - gameZero[ 1][3] = O
    14 - gameZero[ 2][2] = K
    91 - gameZero[15][1] = I
    86 - gameZero[14][2] = E
    46 - gameZero[ 7][4] = T
    92 - gameZero[15][2] = F
    33 - gameZero[ 5][3] = N
    87 - gameZero[14][3] = N
    57 - gameZero[ 9][3] = L
    87 - gameZero[14][3] = N
    50 - gameZero[ 8][2] = N
    10 - gameZero[ 1][4] = R
    23 - gameZero[ 3][5] = Y
    ...
    

    请理解,您也可以仅使用偏移量直接访问元素,但这会导致技术上违反数组边界。 (例如*(*gameZero + off))短篇小说是一个二维数组实际上是一个一维数组的数组。当您访问一个数组时,它会转换为指向其第一个元素的指针。在二维数组的情况下,它是指向第一个 数组 的指针。 (在您的情况下是第一个 6 字符数组),因此如果您应用超过 5 的偏移量,即使您仍在 2D 数组的范围内,您在技术上也正在处理第一个 1D 数组范围之外的元素.从单个偏移量计算 x, y 索引可以消除该问题。

    查看一下,如果您有任何其他问题,请告诉我。

    【讨论】:

    • 非常感谢您提供令人难以置信的详细回复!我的问题现在解决了。我是这个论坛的新手,所以看到这样一个乐于助人的社区让我感到非常振奋。
    【解决方案4】:

    感谢所有在此线程中回复的人的帮助,我相信我已经为我的问题找到了一个合理的答案。如果有人碰巧遇到这个线程,这里就是我想出的:

    void shuffleDice() { // shuffles Game #0 dice. 
    
    mt19937 gen(time(nullptr));
    uniform_int_distribution<int> random_inner(0, inner_size - 1);
    
    int n = random_inner(gen); // generates random number for inner array 
    for (int i = 0; i < 16; i++) // loops through outer array
    {
        cout << gameZero[i][n] << '\n';
    }
    

    请记住,我是编程/C++ 新手,所以它可能不是最漂亮的,但它仍然有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-12
      • 1970-01-01
      • 1970-01-01
      • 2020-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      相关资源
      最近更新 更多