將一副撲克牌的每張牌編號為0到51號,第38號的牌是哪一張?這對許多高手來說很不難,但還是有同學詢問過,為了新手朋友寫了這篇教學。順便講解取餘數的好處,以及Magic Number是什麼。
給花色與數字上編號
首先是撲克牌,先不考慮鬼牌,一副牌有52張,分別是四種花色各13張。在此我們將四個花色標上0, 1, 2, 3代表黑桃、紅心、方塊、梅花;數字就標上0, 1, 2… 12,代表從A到K。
根據維基百科的撲克牌型解說,在台灣花色的大小是黑桃、紅心、方塊、梅花,可是很多地方似乎都是黑桃、紅心、梅花、方塊。在這邊還是先使用方塊大於梅花的規則。
花色 | 黑桃♠️ | 紅心♥️ | 方塊♦️ | 梅花♣️ |
編號 | 0 | 1 | 2 | 3 |
數字 | A | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | J | Q | K |
編號 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
再來使用程式語言中常見的整數除法,以及除法取餘數即可計算囉!
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 | 結果 |
---|---|---|---|
0 | 0 % 3 | 0 | say => 早安 |
1 | 1 % 3 | 1 | say => 午安 |
2 | 2 % 3 | 2 | say => 晚安 |
3 | 3 % 3 | 0 | say => 早安 |
4 | 4 % 3 | 1 | say => 午安 |
5 | 5 % 3 | 2 | say => 晚安 |
6 | 6 % 3 | 0 | say => 早安 |
7 | 7 % 3 | 1 | say => 午安 |
8 | 8 % 3 | 2 | say => 晚安 |
避免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的數量改變時依然能夠正常使用這程式。