2012年1月15日星期日

KAG教學(應用篇)---剪刀、石頭、布

(建議在閱讀本篇教學之前,請先閱讀KAG教學---分歧,選項(1)KAG教學---如果......否則,if 條件判斷(2)KAG教學---也許只是為了寫少點字,變數(3)KAG教學---隨機數,random&intrandom


(k ゚∀゚)<今次是以剪刀、石頭、布這遊戲作為範例,從而簡單介紹隨機數的應用。

剪刀、石頭、布這類規則簡單的遊戲有什麼東西值得介紹?>( ゚ω゚ s)

(k ゚∀゚)<正因為是規則十分簡單,我們更容易理解當中的邏輯和關係。

(k ゚∀゚)<雖然是家喻戶曉的遊戲,不過還是解釋一下遊戲規則,兩個玩家同時出剪刀、石頭、布等手勢,在剪刀和布裡剪刀會勝利,在剪刀和石頭裡石頭會勝利,在布和石頭裡布會勝利,如果雙方一樣的話,就是平局。

(k ゚∀゚)<而這次範例是玩家和電腦玩剪刀、石頭、布這遊戲,每一局玩家都選擇剪刀、石頭或布,電腦則會隨機選一個,之後判斷哪一方勝利。

聽起來好像很簡單,不過想寫出來的話又有點複雜。>( ゚ω゚ s)

(k ゚∀゚)<不如我循序漸進地解說吧,當我們不太清楚流程的話,其實可以先畫流程圖,方便自己或別人理解。看看以下的流程圖。





















(k ゚∀゚)<在上述的流程圖裡,首先我們要玩家選擇,電腦隨機選一個,之後兩者進行比較,判斷哪一方勝利並且顯示出來。

(k ゚∀゚)<不如我們先製作玩家選擇的部分,看看以下的範例。

*start|剪刀、石頭、布
[cm]
剪刀、石頭、布[r]

請選擇以下你想出的手勢:[r]
[link target=*scissors]剪刀[endlink][r]
[link target=*rock]石頭[endlink][r]
[link target=*paper]布[endlink][r]
[s]
*scissors

[jump target=*start]
*rock

[jump target=*start]
*paper

[jump target=*start]

(k ゚∀゚)<吉里吉里根據玩家的選擇,分別跳到*scissors、*rock或*paper,然後用[jump]返回一開始的地方。

那麼我們只要把哪一方勝利的內容寫在它們之間就可以嗎?>( ゚ω゚ s)

(k ゚∀゚)<是的,不過在這之前先寫電腦一方的部分,為了用到電腦會隨機選一個,我們會使用到intrandom來製造一個隨機數,這個數值將會代表電腦的選擇。

(k ゚∀゚)<用intrandom(0,2)可能出現的結果只有三種,分別是0、1或2,每個數值對應每一個手勢,例如0代表剪刀,1代表石頭,2代表布,看看以下的範例。

*start|剪刀、石頭、布
[cm]
[eval exp="tf.comp=intrandom(0,2)"]
剪刀、石頭、布[r]

請選擇以下你想出的手勢:[r]
[link target=*scissors]剪刀[endlink][r]
[link target=*rock]石頭[endlink][r]
[link target=*paper]布[endlink][r]
[s]
*scissors

[jump target=*start]
*rock

[jump target=*start]
*paper

[jump target=*start]

(k ゚∀゚)<之後我們可以比較雙方所出的手勢來決定哪一方勝利,由於label本身已經確定了玩家一方,所以只要考慮電腦一方就可以,看看以下的範例。

*start|剪刀、石頭、布
[cm]
[eval exp="tf.comp=intrandom(0,2)"]
剪刀、石頭、布[r]

請選擇以下你想出的手勢:[r]
[link target=*scissors]剪刀[endlink][r]
[link target=*rock]石頭[endlink][r]
[link target=*paper]布[endlink][r]
[s]

*scissors
[cm]
玩家是剪刀,[r]
[if exp="tf.comp==1"]
電腦是石頭,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==2"]
電腦是布,[r]
玩家獲得勝利。[p][cm]
[else]
電腦是剪刀,[r]
雙方相同,平局。[p][cm]
[endif]
[jump target=*start]

*rock
[cm]
玩家是石頭,[r]
[if exp="tf.comp==2"]
電腦是布,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==0"]
電腦是剪刀,[r]
玩家獲得勝利。[p][cm]
[else]
電腦是石頭,[r]
雙方相同,平局。[p][cm]
[endif]
[jump target=*start]

*paper
[cm]
玩家是布,[r]
[if exp="tf.comp==0"]
電腦是剪刀,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==1"]
電腦是石頭,[r]
玩家獲得勝利。[p][cm]
[else]
電腦是布,[r]
雙方相同,平局。[p][cm]
[endif]
[jump target=*start]

哦!終於完成了,那麼簡單的遊戲居然要寫這麼多。>( ゚ω゚ s)

(k ゚∀゚)<雖然十分簡陋,不過基本上已經可以玩了。

(k ゚∀゚)<然而,這次的範例還有後續的,若果我們想計算一下玩家的勝利率,我們該怎麼辦?

玩家的勝利率是不是玩家的勝利次數除以總遊玩次數?>( ゚ω゚ s)

(k ゚∀゚)<是的,由於計算勝利率時,必須知道玩家的勝利次數和總遊玩次數,所以需要用到變數來儲存著它們,這兩個變數一開始都是0,而玩家每玩一次,總遊玩次數的變數就會加1,當玩家勝利的話,勝利次數的變數就會加1,看看以下的範例。

[eval exp="f.gameCount=0"]
[eval exp="f.win=0"]
*start|剪刀、石頭、布
[cm]
[eval exp="tf.comp=intrandom(0,2)"]
剪刀、石頭、布[r]
現在的勝利率:
[emb exp="Math.round(f.win/f.gameCount*100)"]
%[r]

請選擇以下你想出的手勢:[r]
[link target=*scissors]剪刀[endlink][r]
[link target=*rock]石頭[endlink][r]
[link target=*paper]布[endlink][r]
[s]

*scissors
[cm]
玩家是剪刀,[r]
[if exp="tf.comp==1"]
電腦是石頭,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==2"]
電腦是布,[r]
玩家獲得勝利。[p][cm]
[eval exp="f.win++"]
[else]
電腦是剪刀,[r]
雙方相同,平局。[p][cm]
[endif]
[eval exp="f.gameCount++"]
[jump target=*start]

*rock
[cm]
玩家是石頭,[r]
[if exp="tf.comp==2"]
電腦是布,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==0"]
電腦是剪刀,[r]
玩家獲得勝利。[p][cm]
[eval exp="f.win++"]
[else]
電腦是石頭,[r]
雙方相同,平局。[p][cm]
[endif]
[eval exp="f.gameCount++"]
[jump target=*start]

*paper
[cm]
玩家是布,[r]
[if exp="tf.comp==0"]
電腦是剪刀,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==1"]
電腦是石頭,[r]
玩家獲得勝利。[p][cm]
[eval exp="f.win++"]
[else]
電腦是布,[r]
雙方相同,平局。[p][cm]
[endif]
[eval exp="f.gameCount++"]
[jump target=*start]

唔……好像有點問題,為什麼一開始的時候勝利率會出現NaN?這是什麼東西來的?>( ゚ω゚ s)

(k ゚∀゚)<NaN是Not a Number的簡稱,由於一開始f.win和f.gameCount的數值都是0,而數學上0除以0是沒有意義的,我們在設計程式時經常需要留意並處理這些例外事件。

那麼現在我們該怎麼辦?>( ゚ω゚ s)

(k ゚∀゚)<其中一個辦法是利用[if]來判斷f.gameCount是否等於0,若果等於0,就不用顯示勝利率,看看以下的範例。

[eval exp="f.gameCount=0"]
[eval exp="f.win=0"]
*start|剪刀、石頭、布
[cm]
[eval exp="tf.comp=intrandom(0,2)"]
剪刀、石頭、布[r]
[if exp="f.gameCount!=0"]
現在的勝利率:
[emb exp="Math.round(f.win/f.gameCount*100)"]
%[r]
[endif]

請選擇以下你想出的手勢:[r]
[link target=*scissors]剪刀[endlink][r]
[link target=*rock]石頭[endlink][r]
[link target=*paper]布[endlink][r]
[s]

*scissors
[cm]
玩家是剪刀,[r]
[if exp="tf.comp==1"]
電腦是石頭,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==2"]
電腦是布,[r]
玩家獲得勝利。[p][cm]
[eval exp="f.win++"]
[else]
電腦是剪刀,[r]
雙方相同,平局。[p][cm]
[endif]
[eval exp="f.gameCount++"]
[jump target=*start]

*rock
[cm]
玩家是石頭,[r]
[if exp="tf.comp==2"]
電腦是布,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==0"]
電腦是剪刀,[r]
玩家獲得勝利。[p][cm]
[eval exp="f.win++"]
[else]
電腦是石頭,[r]
雙方相同,平局。[p][cm]
[endif]
[eval exp="f.gameCount++"]
[jump target=*start]

*paper
[cm]
玩家是布,[r]
[if exp="tf.comp==0"]
電腦是剪刀,[r]
電腦獲得勝利。[p][cm]
[elsif exp="tf.comp==1"]
電腦是石頭,[r]
玩家獲得勝利。[p][cm]
[eval exp="f.win++"]
[else]
電腦是布,[r]
雙方相同,平局。[p][cm]
[endif]
[eval exp="f.gameCount++"]
[jump target=*start]

(k ゚∀゚)<今次的範例就到這裡,下次再見。

沒有留言:

發佈留言