存储BlackJack手的最佳方式?

时间:2013-06-06 06:42:30

标签: c playing-cards blackjack

首先,我还是C新手,所以请告诉我你可以提出的任何建议(特别是关于处理数组)。

我想在C中存储BlackJack牌。我得出的结论是牌或牌必须是一个字符串,因为牌可以是两个字符:A, J, Q, K或数字:{{1}其中10实际上应该是一个包含两个字符的字符串。

现在,我尝试将手牌组成一个像这样的阵列:

1, 2.. 10

问题是char* hand; hand[1] = "A"; hand[2] = "2"; ,它占用了数组的两个索引而不是一个。我可以解决这个问题的方法就是创建一个包含5个字符串的结构(BlackJack手中的最大卡数),每张卡一个。但是,如果我出于某种原因希望拥有成千上万张牌,那该怎么办呢?那么存放手的最佳方式是什么?

5 个答案:

答案 0 :(得分:2)

您可能会发现此网站很有趣。

http://www.computerpokercompetition.org/

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

基本上,他们将卡片存储为整数。这是处理卡片的最有效方式。甲板上只有52种卡片。更多如果有笑话在场。因此,您可以将其映射为0到51之间的整数值。它们使用以下函数打印出卡片的内容,因为整数卡号不会告诉您太多。请注意,他们根据排名和套件构建字符串。

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;
}

答案 1 :(得分:1)

不要将卡片存储为字符串(例如"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');

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

答案 2 :(得分:1)

我写了一篇关于这个主题的文章here。使用字符串是一个非常糟糕的主意。整数更好,最好使用的顺序是将套装放在低位,即使用2c,2d,2h,2s,3c,3d,... Ks,Ac,Ad,Ah,As的顺序。这样,你甚至不需要将等级和套装分开来进行数学运算。那么,手只是整数数组。通过这种表示,我可以在几分钟内运行数十亿次的手。 my library中计算二十一点手总数的函数如下所示(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;
}

这是来自通用卡片模拟库并且速度非常快,但是如果我真的想要通过二十一点模拟而不做其他任何事情的球到墙速度,我根本不会代表卡片,而只是拥有{1,2,3,4,5,6,7,8,9,10,10,10,10}的多份副本的“套牌”,并从中处理。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

将卡存储为整数:

  • 1 = Ace
  • 2 = 2
  • 3 = 3
  • ...
  • 9 = 9
  • 10 = 10
  • 11 =杰克
  • 12 =女王
  • 13 =国王

出于显示目的,使用translate函数将整数转换为其名称:

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();
    }
}