C语言 最好的方式来存储二十一点手



首先,我对C还是个新手,所以请让我知道你能给我的任何建议(特别是关于处理数组的建议)。

我想在c中存储一张二十一点的手牌,我得出的结论是手牌或牌必须是一个字符串,因为牌可以是字符:A, J, Q, K或数字:1, 2.. 10,其中10实际上应该是两个字符的字符串。

现在,我尝试将组成手牌的卡片存储到一个数组中,像这样:

char* hand;
hand[1] = "A";
hand[2] = "2";

问题在于10,它占用了数组的两个索引而不是一个。我可以绕过这个问题的一种方法是创建一个包含5个字符串的结构体(游戏邦注:即《BlackJack》手牌中的最大牌数),每个字符串对应一张牌。然而,如果出于某种原因,我想要拥有数千张牌呢?那储存手的最好方法是什么呢?

您可能会对这个网站感兴趣。

http://www.computerpokercompetition.org/

他们举办一年一度的AI扑克比赛。他们的服务器是用C语言编写的,您可以从上面的站点下载代码。

基本上,它们将卡片存储为整数。这是处理牌的最有效的方法。牌组中只有52种牌。如果有小丑在场,更多。所以你可以把它映射成0到51之间的整数值。他们使用下面的函数打印出卡片是什么,因为一个整数卡号并不能告诉你太多。注意,它们是基于rank和suite来构建字符串的。

int printCard( const uint8_t card, const int maxLen, char *string  )
{
  if( 3 > maxLen ) {
    return -1;
  }
  string[ 0 ] = rankChars[ rankOfCard( card ) ];
  string[ 1 ] = suitChars[ suitOfCard( card ) ];
  string[ 2 ] = 0;
  return 2;
}

不要将卡片存储为字符串(例如"9"),而应存储为字符(例如'9')。对于值10,您可以使用像'T'这样的替换字符。示例代码:

char hand[MAX_HAND_LEN];
int hand_len;
get_hand(hand, hand_len);
for (int i = 0; i < hand_len; i++) { 
    if (hand[i] == 'T') {
        putchar('1');
        putchar('0');
    } else {
        putchar(hand[i]);
    }
    putchar(' ');
}
putchar('n');

这样既不会浪费不必要的内存(因为一张卡现在只需要一个字节的存储空间),也不会牺牲代码的简单性或可读性。

我在这里写了一篇关于这个主题的文章。使用字符串是一个非常糟糕的主意。整数更好,最好的使用顺序是将suit放在低阶位,即使用顺序2c, 2d, 2h, 2s, 3c, 3d,…k, Ac, Ad, Ah, As。这样,你甚至不需要把等级和花色分开来计算。那么,手就是整数数组。我可以用这个表示在几分钟内运行数以亿计的手。在我的库中,计算二十一点手牌总数的函数如下所示(OJ_CARD宏扩展为一个整数常量,以便快速比较):

int ojb_total(const oj_cardlist_t *sp) {
    int i, c, t = 0, ace = 0, soft = 0;
    for (i = 0; i < sp->length; ++i) {
        c = sp->cards[i];
        if (c >= OJ_CARD(OJR_ACE, OJS_CLUB)) {
            ace = 1;
            ++t;
        } else if (c >= OJ_CARD(OJR_TEN, OJS_CLUB)) {
            t += 10;
        } else {
            t += OJ_RANK(c) + 2;
        }
    }
    if (ace && t < 12) {
        t += 10;
        soft = 1;
    }
    return soft ? -t : t;
}

这是一个通用的纸牌模拟库,它非常快,但如果我真的想从一个没有其他功能的21点模拟中获得球到墙的速度,我就不会表示任何纸牌,而只是拥有一个包含{1,2,3,4,5,6,7,8,9,10,10,10,10}多个副本的"牌组",并从中发牌。

将卡片存储为整数:

  • 1 = Ace
  • 2 = 2
  • 3 = 3
  • 9 = 9
  • 10 = 10
  • 12 =皇后号

出于显示目的,使用翻译函数将整数转换为它们的名称:

string GetCardNameFromNumber(int cardNumber)
{
    switch(cardNumber)
    {
        case 1:
            return "A";
        case 11:
            return "J";
        case 12:
            return "Q";
        case 13:
            return "K";
        default:
            return cardNumber.ToString();
    }
}

我想说没有唯一最好的方法。但是,char *hand;没有定义字符串数组;你可以使用char *hand[5],这个10不会有两个索引;或者您可以使用char hand[5],并将10存储为单个字符,例如:'0'或'T'

最新更新