撲克牌遊戲的挑戰

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

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

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

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

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

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

算出牌的花色和數值

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

為什麼要減1,同學們可以想出它的道理嗎?

公式如下:

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

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

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

value=(n1)%13+1value = (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之間其中一個數值,如下所示:

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

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

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

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

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

莊家和玩家的牌,要放在哪裡

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

如何發牌給玩家

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

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

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

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

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

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

如何補牌

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

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

如何判斷輸贏

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