###### tags: `APCS`
# **b519-撲克牌遊戲**
### **題目連結:** [**b519**](https://zerojudge.tw/ShowProblem?problemid=b519)
### **題目解析**
此題目是撲克牌遊戲的一部分,我們需要判斷玩家手上的五張牌屬於哪種牌型,並根據牌型給予對應的分數。牌型包括同花順、四條、葫蘆、順子、三條、兩對、一對和雜牌。每種牌型都有不同的得分。
### **解題方向**
* 將每張牌轉換為花色和點數:根據給定的數字,我們需要將其轉換為相應的花色和點數。
* 判斷牌型:依次檢查是否為同花順、四條、葫蘆、順子、三條、兩對和一對。如果不屬於任何一種牌型,則為雜牌。
* 計算分數:根據判斷出的牌型,給予對應的分數。
### **程式解析**
讀取輸入
```python
# Start
N = int(input())
```
逐行處理測試資料
```python
for s in sys.stdin:
data = list(map(int, s.split()))
```
轉換牌號為花色和點數
```python
# Set input card, separate flower and number
handcard = []
for i in data:
card = []
flower = math.ceil(i / 13) # 1, 2, 3, 4
number = i % 13 # 0~12, 0=K
card.append(flower)
card.append(number)
handcard.append(card)
```
* 將每張牌的數字轉換為對應的花色和點數,並存入handcard列表中。
* flower:根據數字計算牌的花色。
* number:根據數字計算牌的點數。
初始化分數
```python
score = 0
```
檢查順子
```python
card_num = []
for i in range(5):
card_num.append(handcard[i][1])
card_num.sort() # 把數字丟入此arr並由小到大排序
```
* 提取所有牌的點數,並將其排序。
```python
diff = 0
for i in range(4):
if card_num[i + 1] - card_num[i] == 1:
diff += 1
if diff == 3 and sum(card_num) == 34:
diff += 1 # 10 J Q K A 特例
if diff == 4: # 至少是順子
score = 4
```
* 檢查是否為順子:
* diff:記錄相鄰牌的點數差是否為1。
* 若連續4次相鄰牌的點數差為1,則為順子。
* 特別處理10, J, Q, K, A的情況。
檢查同花
```python
now_flower = handcard[0][0]
isFlush = True # 起始預設True
for i in range(1, 5):
if handcard[i][0] != now_flower: # 檢查花色是否相同
isFlush = False
if isFlush == True: # 判斷是不是同花順
score += 3
```
* 若為順子,則進一步檢查是否為同花順:
* isFlush:標記是否為同花。
* 若所有牌的花色相同,則為同花順,分數加3。
檢查對子
```python
else:
# Check pairs
num_type = []
for i in range(5):
now_point = handcard[i][1]
for j in range(i + 1, 5):
if handcard[j][1] == now_point:
score += 1 # 有一個與先前相同就+1
if now_point not in num_type: # 丟入num_type
num_type.append(now_point)
```
* 若不是順子,則檢查對子:
* num_type:記錄出現過的點數。
* 檢查是否有相同點數的牌,並計算出現次數。
檢查葫蘆
```python
# Check fullhouse
if len(num_type) == 2 and score == 4: # 檢查葫蘆
score += 1
```
* 若有兩種點數,且分數為4(代表至少有一個三條和一個對子),則為葫蘆,分數加1。
輸出結果
```python
print(score)
```
### **完整程式碼**
```python=
import sys, math
# Start
N = int(input())
for s in sys.stdin:
data = list(map(int, s.split()))
# Set input card, separate flower and number
handcard = []
for i in data:
card = []
flower = math.ceil(i/13) # 1, 2, 3, 4
number = i % 13 # 0~12, 0=K
card.append(flower)
card.append(number)
handcard.append(card)
score = 0
# Check straight
card_num = []
for i in range(5):
card_num.append(handcard[i][1])
card_num.sort() # 把數字丟入此arr並由小到大排序
diff = 0
for i in range(4):
if card_num[i+1] - card_num[i] == 1:
diff += 1
if diff==3 and sum(card_num)==34:
diff+=1 # 10 J Q K A 特例
if diff == 4: # 至少是順子
score = 4
# Check flower
now_flower = handcard[0][0]
isFlush = True # 起始預設True
for i in range(1, 5):
if handcard[i][0] != now_flower: # 檢查花色是否相同
isFlush = False
if isFlush == True: # 判斷是不是同花順
score += 3
else:
# Check pairs
# 檢查對子
num_type = []
for i in range(5):
now_point = handcard[i][1]
for j in range(i+1, 5):
if handcard[j][1] == now_point:
# 判斷目前點數與先前的(now_point)是否相同
score += 1 # 有一個與先前相同就+1
if now_point not in num_type: # 丟入num_type
num_type.append(now_point)
# Check fullhouse
if len(num_type) == 2 and score == 4: # 檢查葫蘆
# 「葫蘆」為三張同數字,另兩張同數字的牌;一個「一對」和「三條」所組成的五張牌;
# 得分5分;
score += 1
print(score)
```