繁体   English   中英

存放二十一点手牌的最佳方法?

[英]Best way to store a BlackJack hand?

首先,我还是C语言的新手,所以请让我知道您可以提出的任何建议(尤其是关于处理数组的建议)。

我想将BlackJack手存储在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之间的整数值。它们使用以下函数来打印出一张卡,因为整数卡号不会告诉您太多。 注意,他们基于等级和套件来构建字符串。

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');

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

我在这里写了一篇关于这个问题的文章。 使用字符串是一个非常糟糕的主意。 整数更好,最好的使用顺序是将低序位放在一起,即使用2c,2d,2h,2s,3c,3d,...,Ks,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;
}

这是来自通用卡片模拟库的,而且速度非常快,但是如果我真的想要二十一点模拟的弹球到墙壁的速度,却什么也没做,我根本就不会代表卡片,只需要一个“ {1,2,3,4,5,6,7,8,9,10,10,10,10}的多个副本”,然后从中进行处理。

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

将卡存储为整数:

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM