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

时间:2011-04-14 16:17:22

标签: sql database data-representation

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

该套牌将预先发给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:有理由存放卡片。我们需要分析手牌分布,高卡积分等......

3 个答案:

答案 0 :(得分: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
);

每个HANDHAND_ELEMENT中有13行。我不打算存储关于套装分布的信息,我只是计算一只手的分布,即

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

答案 1 :(得分: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;国王> 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?等

答案 2 :(得分: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);

通过这种方式,您可以循环访问数据库,并在处理卡片时将更改处理为“true”。还可以轻松比较等级。