首先,我对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'