【问题标题】:Declaring a value to int in arrays在数组中将值声明为 int
【发布时间】:2022-01-13 13:27:18
【问题描述】:

我正在尝试只使用数组而不使用类来制作一副卡片。

如何为每张卡声明价值?尝试这样写似乎效率很低,然后尝试为每个索引位置赋值:

int deckOfcards[52]{ 1,2,3,4,5,6,7,8,9,10.......... };

然后我将随机抽取 2 张牌并宣布获胜者。是否可以在数组中使用 rand() 函数?

【问题讨论】:

  • 可能是一个循环?还是std::iota()?或者也许不要让事情变得更困难,然后抱怨困难?每张卡都有独特的价值吗?还是您想模仿一副标准的扑克牌?
  • 另外,不要使用rand()。更喜欢<random> 的东西。
  • @sweenish 它应该模拟一副标准的纸牌
  • 那么接下来,ace的价值是多少?根据游戏的不同,王牌是高牌或低牌。
  • @sweenish 我可能有点不清楚我在这里真正想要什么。王牌是这副牌中最高的牌。我想设置每个索引位置的值。可以说索引号 2 是俱乐部的 2。它在纸牌游戏中的值为 2。现在我想设置这个值,如果我画了 3 个梅花,而电脑画了 2 个梅花。我赢了

标签: c++ arrays random


【解决方案1】:

您可以创建一个循环来为您填充数组..

int deckOfCards[52]{};
for (int i = 0; i < 52; i++)
{
    deckOfCards[i] = i+1;
}

这对于这个特定的实例来说效果很好,但你可能想要使用 std::size(deckOfCards) 在你的循环中,因为数组的大小可能并不总是已知的。

int deckOfCards[52]{};
for (int i = 0; i < std::size(deckOfCards); i++)
{
    deckOfCards[i] = i+1;
}

请记住,数组索引从 0 开始,因此 i 将从 0 变为 51。这就是我们将 deckOfCards[i] 设置为等于 i + 1 的原因

【讨论】:

  • 如果不知道 C 数组的大小,您就有麻烦了。编辑:编辑了关于 C 数组的部分,我现在看到了重载。尽管如果您超出 C 数组的原始范围,它仍然无法工作,因为它可能已经衰减为指针。
  • 我明白这一点。感谢您的回答,我也可以在这个 for 循环中设置值吗?例如将 2 of clubs 设置为数组索引 2,等等?如果这有意义..
  • 你将无法知道这张牌的花色是什么,你只有一个int。我承认你可以创建一个算法来唯一地用一个int(例如,质数乘法)来识别两者,但这似乎有点多。
【解决方案2】:

imo 还有一种更好的方法来为卡片引入随机性, 使用 std::shuffle。通过使用这个函数,你可以得到这样的代码 解释自己。它还将介绍您正在寻找的牌组。

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

//-----------------------------------------------------------------------------

struct card_t
{
    // each new instance gets a number which is then increased
    // ++ at the end is important.
    card_t() :
        number{ g_card_number++ }   
    {
    }

    std::size_t number;
    static std::size_t g_card_number;
};

std::size_t card_t::g_card_number = 1;

//-----------------------------------------------------------------------------

int main()
{
    // setup random generation c++ style
    std::random_device rd;
    std::default_random_engine random_generator{ rd() };

    // create a deck of 52 cards
    // this will call the constructor for each of them so they all get
    // a unique number
    std::array<card_t, 52> cards;

    // shuffle the cards using the random generator
    std::shuffle(cards.begin(), cards.end(), random_generator);

    std::cout << "first card has number : " << cards[0].number << "\n";
    std::cout << "second card has number : " << cards[1].number << "\n";

    return 0;
}

【讨论】:

    【解决方案3】:

    要求是您要模拟一副标准的扑克牌,而 cmets 表示您要跟踪花色和价值。您还声称您只想使用一个整数数组来执行此操作。

    这是可能的,但可能不是你真正想要的。更简单的解决方案已作为答案发布,但我将尝试提供满足所述要求的答案。

    我只是先说这可能是一个 XY 问题,这意味着您所说的问题并不是您遇到的真正问题。您将在代码中看到同样多的内容。

    要将两条信息唯一地编码为单个int,您需要一种编码和解码方法。最简单的方法是使用素数乘法。这是因为只有两个被除数可以是素数。只是为了好玩,这也是许多现代密码学的基础。

    您需要 17 个质数(4 个花色和 13 个值)。我选择“第一个”17,从 3 开始。它们是:3、5、7、11、13、17、19、23、29、31、37、41、43、47、53、59 和61.

    我会随意用最后4个来代表花色。所以对我来说,梅花是 47,黑桃是 53,然后是红桃,然后是方块。

    因此,例如,3 个梅花的值为 235 (5 * 47)。红心 3 的值为 295 (5 * 59)。每张牌都是唯一可识别的,你可以知道它的价值和花色。

    你可能只用素数作为花色,但我知道如果我们使用两个素数,唯一性是有保证的。

    要随机选择两张牌,您实际上将洗牌整个牌组,然后只查看数组的前两个元素。这是因为如果您尝试仅在 [0, 51] 范围内选择两个随机数,([] 表示包含),您可能会选择两次相同的数字,这在真实牌组中是不可能的。

    这是代码,我尽量保持简单(即,尽量减少标准库的使用,但出现健全的异常情况)

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <random>
    
    void create_deck(int deck[], int deckSize) {
      //          cl  sp  he  di
      int suits[]{47, 53, 59, 61};
    
      //           2  3  4   5   6   7   8   9  10   J   Q   K   A
      int values[]{3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
    
      int idx = 0;
      for (std::size_t s = 0; s < sizeof(suits) / sizeof(suits[0]); ++s) {
        for (std::size_t v = 0;
             v < sizeof(values) / sizeof(values[0]) && idx < deckSize; ++v) {
          deck[idx] = suits[s] * values[v];
          ++idx;
        }
      }
    }
    
    // Prints the name of the card and returns the value
    int decode_card(int val) {
      //          cl  sp  he  di
      int suits[]{47, 53, 59, 61};
      std::string suitNames[]{"clubs", "spades", "hearts", "diamonds"};
    
      //           2  3  4   5   6   7   8   9  10   J   Q   K   A
      int values[]{3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
      std::string valueNames[]{"two",   "three", "four", "five", "six",
                               "seven", "eight", "nine", "ten",  "jack",
                               "queen", "king",  "ace"};
      int realValues[]{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
    
      std::string suit;
      std::string value;
      for (std::size_t i = 0; i < sizeof(suits) / sizeof(suits[0]); ++i) {
        if (val % suits[i] == 0) {
          suit = suitNames[i];
          val /= suits[i];
          for (std::size_t v = 0; v < sizeof(values) / sizeof(values[0]); ++v) {
            if (values[v] == val) {
              value = valueNames[v];
    
              std::cout << value << " of " << suit << ".\n";
              return realValues[v];
            }
          }
        }
      }
    
      return -1;
    }
    
    int main() {
      const int deckSize = 52;
      int deck[deckSize];
    
      create_deck(deck, deckSize);
      std::shuffle(std::begin(deck), std::end(deck),
                   std::mt19937(std::random_device{}()));
    
      int playerOneDraw = deck[0];
      int playerTwoDraw = deck[1];
    
      std::cout << "Player 1: ";
      int playerOneValue = decode_card(playerOneDraw);
      std::cout << "Player 2: ";
      int playerTwoValue = decode_card(playerTwoDraw);
    
      if (playerOneValue > playerTwoValue) {
        std::cout << "Player 1 wins.\n";
      } else if (playerOneValue == playerTwoValue) {
        std::cout << "It's a draw.\n";
      } else {
        std::cout << "Player Two wins.\n";
      }
    }
    

    一次运行的输出:

    Player 1: ace of spades.
    Player 2: three of diamonds.
    Player 1 wins.
    

    马上,我希望您看到与使用类的其他解决方案相比,它的代码更长、更复杂。从长远来看,这使得这段代码更难维护。

    这正是因为您给出的要求使任务变得比实际需要的更难。我选择不使用全局变量,因为你真的不应该,但我也选择不使用namespace,因为我假设如果你不想要类,你可能不想要namespace

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-19
      • 1970-01-01
      • 2010-10-30
      • 2016-05-15
      • 1970-01-01
      相关资源
      最近更新 更多