在数据库中存储一副扑克牌的最佳方式是什么?

问题描述:

我正在研究一个需要在数据库中存储一副牌的应用程序。我不确定什么是在数据库中表示这个最好的方法。在数据库中存储一副扑克牌的最佳方式是什么?

该套牌将被预先分配到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) 
405251282717161514

任何想法?

PS:有一个理由来存储卡。我们需要分析手牌分布,高卡点等......

+2

定义 “最好的”。您的意思是“存储最少字节数的手的最佳方式”,还是“存储手的最佳方式,使其易于人类阅读”? – Davidann 2011-04-14 16:21:15

+0

最后,手将被转换为应用程序可读的人类,但更重要的是,我需要能够根据其属性进行分类和检索。我不认为字节数量应该是一个问题。 – Sinan 2011-04-14 16:30:29

+1

为什么有必要在数据库中存储所有枚举?为什么不根据需要生成它们? – Davidann 2011-04-14 16:31:32

我觉得最自然不过的事情。将创建卡表,这将每张卡片有一张记录,然后是手牌记录,手中每张卡片都有一张记录。如果有整个牌的数据 - 球员的名字?他坐在桌旁?他有多少筹码?无论如何 - 那么你需要一个单独的桌子,而不是手中的牌。我也会创建一个西装的查找表。

(我们可以辩论使用人工键与这里的自然键,但这是另一个主题。)

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是否容易用于数据库;国王> 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名的文本,我怎么排除2的那是 '12'的一部分?等

+0

很棒的答案。谢谢。但我觉得我需要澄清一些观点。首先我不需要选择像你的例子那样的东西。 (虽然现在我可以看到新的潜力)我需要选择的只是整个手牌或只是一个牌手。我这么说是因为它可能会改变数据库的设计。比较等级不应该是一个问题(至少大部分时间)。 – Sinan 2011-04-14 17:12:06

+0

“选择......整只手”是什么意思?你想对数据做什么?如果简短的回答是你想要做的就是显示玩家手中的内容,那么你甚至不需要数据库:只需一个平面文件,每手一行,每一行都包含手的内容显示格式,如“黑桃王牌,3钻石和几张面牌”。但是如果你真的想要以某种方式操纵它,那当然答案会改变。 – Jay 2011-04-18 16:52:19

这取决于你想要做的分析类型。要不是我,我可能会默认为类似(忽略非主约束)

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将在HAND_ELEMENT 13行。我不会理会存储有关的诉讼分布的信息,我只是计算手的分布,即

SELECT suit, count(*) 
    FROM hand JOIN hand_element USING (hand_id) 
      JOIN card   USING (card_id) 
WHERE hand_id = :some_hand_id 

我也正在为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); 

这种方式可以遍历数据库和变更处理为“真”作为卡正在处理中。还可以轻松比较排名。