# 撲克牌遊戲的挑戰

## 52張牌，要如何放在記憶體中

清單，要把所有的牌都放在清單中，之後所有的操作就是利用清單的存取來進行操作。

至於如何去代表每一張牌則有許多種方式，有些人使用1到52這些數字來代表每一張牌，當要使用的時候再利用轉換的方式來算出它的值是多少，花色是什麼。也可能直接使用具備花色和值的內容來儲存在清單的資料項中。

假設我們以0為牌的背面花色，而1到52是由黑桃A排到方塊K，可以使用以下的積木一口氣把所有的牌都放到清單deck中：

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_fcudVbAq5EqRWqecn%2F-L_feS0yA71NnDjWSkEa%2F2019-03-11_15-30-56.png?alt=media\&token=e9c58b4c-22da-4b7f-b9c5-4f2a98688fc5)

執行上述的程式積木之後，就可以得到一個長度為52的deck清單，如下所示：

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_fcudVbAq5EqRWqecn%2F-L_ffOuCR_LSnNRPY0cX%2F2019-03-11_15-35-21.png?alt=media\&token=8134ad08-1c64-42a2-9a7f-c432aaaa02ca)

那麼，我們怎麼會知道任一個數字是哪一個花色，又是什麼編號呢？如果你手上有一幅牌的話，請直接把它們依序排成一列放在桌子上，把最左邊的第一張編上1號，第2張編上2號，依此類推，然後你就會知道如何得知每一個數字是什麼花色和它的值是多少了。

## 算出牌的花色和數值

假設我們有4個花色，從左至右是黑桃、紅心、梅花、以及方塊，那就是52張牌分成4份，如果我們拿到一個數字 N 的話，只要把它減去1，再整除13，得到的數字是0就是在第一組，也就是黑桃，如果得到的數字是1就是第二，那花色就是紅心，依此類推。所以，如果有一個數字是13的話，(13-1)//13 ==> 0，它的花色就是黑桃。

{% hint style="warning" %}
為什麼要減1，同學們可以想出它的道理嗎？
{% endhint %}

公式如下：

$$
fold = floor((n-1)/13)
$$

其中floor是無條件捨去小數點的函數，算出來的fold就是0\~3，可以代表是哪一組牌（要看你的牌放的順序）。

那要如何算出它的值呢？答案是使用取餘數計算就可以了。公式如下：

$$
value = (n-1) %13 + 1
$$

還是以13為例，(13-1)%13+1的結果是13，所以13就是黑桃13，也就是黑桃K。同理，如果是14的話，(14-1)//13==>1，花色是紅心，(14-1)%13+1==>1，結果就是紅心1，也就是紅心A。

## 洗牌的方法

洗牌的目的就是要讓前面的deck清單中的所有內容是隨機的方式放置。一般的想法是，既然有52張牌，就每一張牌要放進deck中時就使用隨機函數，每一次就從1到52的號碼中選一個就好了。但是，這樣的問題是，每一次隨機的數字，有可能會和之前選過的一樣，此種情形會在越後面越容易發生，所以如果要使用此種方式，就要在每次出現隨機數的時候就要再到清單中檢查一次，如果清單中已有這個數字的話，就要重新再找下一個隨機數，重複這些步驟直所有的數字都出現在deck清單中為止。

另外一個方式則是使用另一個方向來思考，就是一開始依序把每一張牌都放到deck清單中，再打亂它們的順序即可。

至於如何打亂順序呢？在這裡用的方法是任選deck清單中的兩位置，把它們的內容交換，只要交換的次數夠多的話，整幅牌的順序就是亂的了。先來看如何交換清單中兩個不同位置的內容，首先要建立兩個變數，在這裡我們使用x和y，接著把x和y分別使用隨機數產生1\~52之間其中一個數值，如下所示：

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_lRTElOgq250AB1cop%2F-L_lS0KywM6hjkKGGeaT%2F%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%202019-03-12%20%E4%B8%8B%E5%8D%886.30.04.png?alt=media\&token=ecbbd4da-150f-4f8b-ab0e-14b90204b3e9)

要交換清單中兩個項目的內容，其程序如下：

$$
temp = deck\[x] \newline
deck\[x]  = deck\[y] \newline
deck\[y] = temp
$$

請留意上述的說明中，temp是一個單純的變數，它只用來存放暫時性的內容，而deck則是一個清單，所以要指定清單內的值，還需要索引變數x和y的幫忙。使用Scratch積木的程式如下：

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_lRTElOgq250AB1cop%2F-L_lTmuV4w6b610k3AVr%2F%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%202019-03-12%20%E4%B8%8B%E5%8D%886.37.59.png?alt=media\&token=37d40235-c3e5-4202-82fb-f346cdeffec7)

以上的程式片段我們要讓它執行足夠的次數，所以接下來是洗牌的程式積木，也就是加上一個重複迴圈：

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_lRTElOgq250AB1cop%2F-L_lU7mM4AE_Pudp57SY%2F%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%202019-03-12%20%E4%B8%8B%E5%8D%886.39.26.png?alt=media\&token=d2a93d46-4a1d-4156-929f-314b96e58b00)

把上述這段程式碼串接上建立清單程式積木後面就可以了。以下是執行完畢之後的舞台畫面：

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_lRTElOgq250AB1cop%2F-L_lURXusg5ryX5REYwC%2F%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%202019-03-12%20%E4%B8%8B%E5%8D%886.40.35.png?alt=media\&token=4768d4b5-5c3e-423b-b319-0c9568952b6d)

## 莊家和玩家的牌，要放在哪裡

當deck中的牌是隨機擺置的情況之後，如果要發5張牌，那麼只要拿deck清單中的前面5張牌就可以了。當然為了要可以玩之後的遊戲，這5張牌最好是放在另外一個清單中，如果需比較莊家和玩家不同的牌，那麼就需要另外準備兩個清單，前10張中的單數，也就是1, 3, 5, 7, 9是給玩家，而偶數，也就是2, 4, 6, 8, 10是莊家的牌。

## 如何發牌給玩家&#x20;

在這個例子中，我們把玩家的牌放在player，而莊家則是建立一個叫做banker的清單來放置。這表示我們還需要再定義2個清單變數，分別就叫做player和banker，之後利用迴圈把deck中的資料項目複製到這兩個清單中。為了簡化說明，在這裡只複製player這個清單，複製完成之後，player中的5個項目，就是玩家所得到的5張牌。

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_lo06aiqQ015CLNLFb%2F-L_lp0A-qkbIYdb7dwMZ%2F%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%202019-03-12%20%E4%B8%8B%E5%8D%888.15.05.png?alt=media\&token=dd6d7fe9-0f38-4ce7-897d-60a0d54f17fe)

在這個例子中，我們使用角色被點擊事件來啟動發牌，也就是程式開始執行的時候是進行洗的操作，而按下貓咪之後才會發牌。發牌之後的結果，如下圖所示：

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_lo06aiqQ015CLNLFb%2F-L_lpkvQ-TvoYcooQfxD%2F%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%202019-03-12%20%E4%B8%8B%E5%8D%888.18.19.png?alt=media\&token=476266d0-96f0-4aed-8d1d-4f4e8ab40257)

從上圖中可以看出，其實player中的內容就是deck中第1到第5個資料項目的內容。再來，就是讓貓咪說明這些牌的內容，運用之前的程式碼，說出如下：

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_p0_OPggMea9hRlyc3%2F-L_p1pWB3JPbyEN-tY8q%2F2019-03-13_11-14-06.png?alt=media\&token=032e406a-0904-472b-baa3-f6f3d7688d55)

## 使用字串組合讓貓咪一次說出牌面的花色和內容值

在前面的程式例子中，貓咪對於每一張牌都分別說出花色和內容值，如何讓牠可以把花色和內容值放在一起呢？答案就是字串組合積木。為了避免積木堆疊太長，在這裡先建立一個叫做message的變數，先組合出我們要的訊息，再由貓咪說出來。

![](https://1789170130-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LZJEK4Zm0THA0vYxBYQ%2F-L_p0_OPggMea9hRlyc3%2F-L_p6sQUHVFMU36Kkb9j%2F2019-03-13_11-36-14.png?alt=media\&token=98be1e59-8b46-4629-bb63-c6b4f5da42f0)

如果還覺得太長的話，同學們別忘了，變數是個好東西，同學們想想看，如果把message分成2個獨立的變數，那要如何做呢？

## 如何補牌

發牌很簡單，就是把deck的前5張複製到player清單中，那補牌呢？首先要知道要補的是哪幾張牌，這些要有一個清單把它記錄下來，之後再補牌的時候，就利用一個迴圈去這個清單中找一通，如果有要補牌的地方，就從第6張開始，依此類推，直到所有的牌都看過一遍為止。

為了維持最新的補牌順序，需要再一個變數（例如top），一開始指向deck中的第6張牌（也就是一開始top的內容要設為6），當把牌補出去之後，再把它的內容加1，以切換到下一張牌的位置。

## 如何判斷輸贏

這個部份就要看你玩的是哪一種遊戲而有所不同，留待給同學們當作是討論的內容囉。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nkust.gitbook.io/scratch-3/ke-pai-de-tiao.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
