將一副撲克牌的每張牌編號為0到51號,第38號的牌是哪一張?這對許多高手來說很不難,但還是有同學詢問過,為了新手朋友寫了這篇教學。順便講解取餘數的好處,以及Magic Number是什麼。

來源:維基百科

給花色與數字上編號

首先是撲克牌,先不考慮鬼牌,一副牌有52張,分別是四種花色各13張。在此我們將四個花色標上0, 1, 2, 3代表黑桃、紅心、方塊、梅花;數字就標上0, 1, 2… 12,代表從A到K。

根據維基百科的撲克牌型解說,在台灣花色的大小是黑桃紅心方塊梅花,可是很多地方似乎都是黑桃紅心梅花方塊。在這邊還是先使用方塊大於梅花的規則。

花色黑桃♠️紅心♥️方塊♦️梅花♣️
編號0123
花色與編號的對應
數字A2345678910JQK
編號0123456789101112
數字與編號的對應

再來使用程式語言中常見的整數除法,以及除法取餘數即可計算囉!

JavaScript範例

const suits = ['黑桃', '紅心', '方塊', '梅花']
const numbers = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']

function getCard(id) {
    const n = id % 13
    const s = (id - n) / 13
    return suits[s] + numbers[n]
}

getCard(38)  // 方塊K

一般情況下JavaScript的數字都是浮點數,因此無法整除的數字就會出現小數點,可以使用parseInt(id /13)來解決。也可以像上面範例中那樣,先算出餘數,然後進行除法前先把被除數的餘數減掉,進行除法後就不會有小數點了。

Java範例

public class PokerCard {
    static String[] suits = {"黑桃", "紅心", "方塊", "梅花"};
    static String[] numbers = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};

    static String getCard(int id) {
        int n = id % 13;
        int s = id / 13;
        return suits[s] + numbers[n];
    }

    public static void main(String[] args) {
        System.out.println(getCard(38));  // 方塊K
    }
}

補充說明

取餘數的妙用

操作陣列的時候取餘數是一種常見的手法,例如我們有一個陣列為say = ['早安', '午安', '晚安'],透過索引0, 1, 2即可讀取上面三個值,要是數值超過的話,就會溢位出錯(Index out of range)。理想情況下我們應該確保帶入的索引只該在陣列範圍內,但有些情況難免不好處理,因此可以用索引取餘數的方式來避免溢位。

自變數 X運算應變數 Y結果
00 % 30say => 早安
11 % 31say => 午安
22 % 32say => 晚安
33 % 30say => 早安
44 % 31say => 午安
55 % 32say => 晚安
66 % 30say => 早安
77 % 31say => 午安
88 % 32say => 晚安

避免Magic Number

const say = ['早安', '午安', '晚安']

function getSay(id) {
    // const n = id % 3 <= 避免此寫法
    const n = id % say.length
    return say[n]
}

延續上一則補充說明,我們可以將程式碼以JavaScript方式寫出來,這邊要注意的是要避免Magic Number。所謂的Magic Number就是一個數字,像是上面程式碼第4行那樣,寫上去可以讓程式正常運作,但沒有說明3是什麼,而且隨著say的內容改變就會出錯。

以這篇為例,應該要使用say.length來進行計算,這樣看程式碼可以很清楚知道這個數字來自哪裡,而且當say的數量改變時依然能夠正常使用這程式。