1

我正在开发一个需要在数据库中存储一副手牌的应用程序。我不确定在数据库中表示它的最佳方式是什么。

该套牌将被应用程序预先分配给 4 手,每手持有 13 张牌。之后我需要存储手和其他数据,如西装分布等......

最好为每手牌创建一个单独的行并将其与一副牌相关联吗?或者将它们排成一排会更好吗?

另外我不确定是否应该将它们保留为文本或数字。这是一个例子:

Sorted by suit and separated by dot
AK.32.6543.AKQ98

或者

(52 = Largest rank or largest suit or 02 = 2 of smallest suit)
405251282717161514012322200908

有任何想法吗?

PS:存卡是有原因的。我们需要分析手牌分布、高牌点等...

4

3 回答 3

4

这取决于您要进行的分析类型。如果是我,我可能会默认为(忽略非主要约束)

CREATE TABLE card (
  card_id NUMBER PRIMARY KEY,
  suit    VARCHAR2(10) NOT NULL,
  value   VARCHAR2(1)  NOT NULL
);

CREATE TABLE hand (
  hand_id   NUMBER PRIMARY KEY,
  player_id NUMBER NOT NULL
);

CREATE TABLE hand_element (
  hand_element_id NUMBER PRIMARY KEY,
  hand_id         NUMBER NOT NULL,
  card_id         NUMBER NOT NULL
);

每个HAND将有 13 行HAND_ELEMENT。我不会费心存储有关花色分布的信息,我只计算一手牌的分布,即

SELECT suit, count(*)
  FROM hand JOIN hand_element USING (hand_id)
            JOIN card         USING (card_id)
 WHERE hand_id = :some_hand_id
于 2011-04-14T16:31:43.943 回答
4

我认为最自然的事情是为卡片创建一个表格,为一副牌中的每张卡片创建一个记录,然后为手牌创建一个记录,为手中的每张卡片创建一个记录。如果有关于整手牌的数据——玩家的名字?他坐在桌边的哪个位置?他有多少筹码?不管怎样——那么你需要一张单独的桌子来存放手牌,而不是手中的牌。我还会为西装创建一个查找表。

(我们可以在这里讨论合成键与自然键的使用,但这是另一个主题。)

card (cardid, suitid, rank)
suit (suitid, suitname)
hand (handid, playername, whatever)
handcard (handcardid, handid, cardid)

我的第一个冲动是让“排名”一个从 1 到 13 的数字,并在输出时将 1 转换为“Ace”,将 11 转换为 13 为“Jack”、“Queen”和“King”。您可以将它们存储为文本,但是如果有需要的话,很难比较排名。即确定13>10 对数据库来说是否容易;King>10,没那么多。

我绝对不会尝试将多个卡片的标识塞进一个字段中,无论是用句点分隔还是固定长度的 ID 或其他什么分隔。这样做需要你的程序有代码来分离这个字段以获得你想要的数据,而不是让数据库检索你想要的数据,这就是数据库的用途。

我不知道你想用这些牌手做什么,但是你可能想做的大多数事情都非常容易,就像我描述的那样场地。比如,“谁有黑桃王?” 简单的:

select playername
from hand
join handcard using (handid)
join card using (cardid)
join suit using (suitid)
where suit.name='Spades' and card.rank=13

或者,“每个玩家有多少张面孔卡?”

select playername, count(*)
from hand
join handcard using (handid)
join card using (cardid)
where card.rank between 11 and 13

当然是“玩家#3 有什么牌?” 也很容易:

select rank, suitname
from handcard
join card using (cardid)
join suit using (suitid)
where handid=3

使用打包格式执行这些查询将需要棘手的字符串提取调用。字符串操作总是很痛苦。就像您总是遇到问题一样,如果我在文本中搜索 2,我如何排除属于 '12' 的 2?等等

于 2011-04-14T16:57:49.650 回答
0

我也在为 3 张牌扑克做一个类似的项目。我这样设置我的 SQL:

CREATE TABLE cards 
(

    id int AUTO_INCREMENT,
    suite varchar(30) NOT NULL,
    rank int NOT NULL,
    dealt BOOLEAN DEFAULT false,
    PRIMARY KEY (id)

);

然后运行命令以这种方式填充数据库:

INSERT INTO cards (suite,rank) VALUES ('spades',1);

This way you can loop through the database and change dealt to 'true' as cards are being dealt. Also makes it easy to compare ranks.

于 2016-05-14T14:22:58.453 回答