2011-04-14 94 views
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) 
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

回答

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名的文本,我怎麼排除2的那是 '12'的一部分?等

+0

很棒的答案。謝謝。但我覺得我需要澄清一些觀點。首先我不需要選擇像你的例子那樣的東西。 (雖然現在我可以看到新的潛力)我需要選擇的只是整個手牌或只是一個牌手。我這麼說是因爲它可能會改變數據庫的設計。比較等級不應該是一個問題(至少大部分時間)。 – Sinan 2011-04-14 17:12:06

+0

「選擇......整隻手」是什麼意思?你想對數據做什麼?如果簡短的回答是你想要做的就是顯示玩家手中的內容,那麼你甚至不需要數據庫:只需一個平面文件,每手一行,每一行都包含手的內容顯示格式,如「黑桃王牌,3鑽石和幾張面牌」。但是如果你真的想要以某種方式操縱它,那當然答案會改變。 – Jay 2011-04-18 16:52:19

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將在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 
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); 

這種方式可以遍歷數據庫和變更處理爲「真」作爲卡正在處理中。還可以輕鬆比較排名。

相關問題