無痛入手 C++:應用教學 - 猜拳遊戲

閱讀時間約 9 分鐘

須具備知識

  1. 無痛入手 C++:基礎系列5 - 條件判斷
  2. 如何產生亂數


遊戲設計

一開始會先印出遊戲的說明文字: 使用者需要輸入 r 來表示石頭,p 來表示布,以及 s 來表示剪刀:

======================================================
= Wellcome to rock paper scissors. =
= Enter r for rock, p for paper, and s for scissors. =
======================================================

我們讓電腦隨機產生一個介於 0 ~ 2 的整數,用 0 來代表石頭,1 來代表布,2 來代表剪刀。

再來就是比較使用者的輸入以及電腦產生的亂數,看誰獲勝。


方法一

最直觀的方式就是利用 if、else if、else 針對使用者和亂數的各種可能性判斷誰獲勝。完整的程式碼如下:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
cout << "======================================================\n";
cout << "= Wellcome to rock paper scissors. =\n";
cout << "= Enter r for rock, p for paper, and s for scissors. =\n";
cout << "======================================================\n";

// get user move
char userMove;
cin >> userMove;

// get random move
srand(time(0));
int randMove = rand() % 3;
// 0 for rock, 1 for paper, and 2 for scissors
if (randMove == 0)
cout << "r\n";
else if (randMove == 1)
cout << "p\n";
else
cout << "s\n";

// decide win or lose
if(userMove == 'r') {
if (randMove == 0)
cout << "Even.";
else if (randMove == 1)
cout << "You lose.";
else
cout << "You win.";
} else if (userMove == 'p') {
if (randMove == 0)
cout << "You win.";
else if (randMove == 1)
cout << "Even.";
else
cout << "You lose.";
} else {
if (randMove == 0)
cout << "You lose.";
else if (randMove == 1)
cout << "You win.";
else
cout << "You lose.";
}
return 0;
}

可以看到,我們需要處理 3 x 3 = 9種情況,寫起來非常麻煩,也容易看得眼花撩亂。


方法二

我們可以透過找規律的方式,把 9 種情況縮減成 3 種: 勝利、失敗、平手。

首先將使用者出的招從 r、p、s 轉換成 0、1、2。

char userMoveChar;
int userMove;
cin >> userMoveChar;
if (userMoveChar == 'r')
userMove = 0;
else if (userMoveChar == 'p')
userMove = 1;
else
userMove = 2;

如此一來,只要 userMove 和 randMove 相等,就表示平手:

if (userMove == randMove)
cout << "Even";


接著觀察使用者在什麼樣的條件下會輸:
1. 使用者出 0 (石頭),電腦出 1 (布) ->使用者輸
2. 使用者出 1 (布),電腦出 2 (剪刀) ->使用者輸
3. 使用者出 2 (剪刀),電腦出 0 (石頭) ->使用者輸

觀察 1 和 2 可以發現當 randMove = userMove + 1 的時候,代表使用者輸了。3 乍看之下不符合這個規律,這個原因是因為剪刀是"最大"的數字了,下一個招式是石頭,會繞回 0,我們可以利用取餘數來處理這類狀況: (布 + 1) % 3 == 石頭。

也就是說,當滿足以下條件的時候,代表使用者輸了:
(userMove + 1) % 3 == randMove

用相同的邏輯觀察使用者在什麼樣的條件下會贏:
1. 使用者出 0 (石頭),電腦出 2 (剪刀) ->使用者贏
2. 使用者出 1 (布),電腦出 0 (石頭) ->使用者贏
3. 使用者出 2 (剪刀),電腦出 1 (布) ->使用者贏

可以觀察到,當滿足以下條件的時候,代表使用者輸了:
(userMove + 2) % 3 == randMove

總結上述發現的規律:
1. userMove == randMove: 平手
2. (userMove + 1) % 3 == randMove: 使用者輸
3. (userMove + 2) % 3 == randMove: 使用者贏

利用這樣的規律,我們就可以把原本的 9 種狀況縮減成 3 種。完整的程式碼如下:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
cout << "======================================================\n";
cout << "= Wellcome to rock paper scissors. =\n";
cout << "= Enter r for rock, p for paper, and s for scissors. =\n";
cout << "======================================================\n";

// get user move
char userMoveChar;
int userMove;
cin >> userMoveChar;
if (userMoveChar == 'r')
userMove = 0;
else if (userMoveChar == 'p')
userMove = 1;
else
userMove = 2;

// get random move
srand(time(0));
int randMove = rand() % 3;
// 0 for rock, 1 for paper, and 2 for scissors
if (randMove == 0)
cout << "r\n";
else if (randMove == 1)
cout << "p\n";
else
cout << "s\n";

// decide win or lose
if (userMove == randMove)
cout << "Even.";
else if ((userMove + 2) % 3 == randMove)
cout << "You win";
else
cout << "You lose";

return 0;
}


程式技巧

  1. 有時候可以找出規律,縮減需要做的條件判斷數量。
  2. 可以用 % 來表示"從最後一個數字繞回第一個數字"。




2會員
14Content count
程式設計 & 電腦系統 & 系統軟體
留言0
查看全部
發表第一個留言支持創作者!
鏟薯員的窩 的其他內容
C 語言的函式庫定義了許多好用的函式,在寫 C++ 的時候可以拿來用。這是因為 C++ 當初在設計的時候,就有刻意把 C 涵蓋進來。 基本用法 首先要導入 C 語言的標準函式庫: #include <cstdlib> 以 c 作為開頭表示它是 C 語言的函式庫,只是被我們拿來 C++ 的程式
<iostream> ​在之前的文章有提到過,<iostream> 是專門處理程式的輸入 (input) 以及輸出 (output) 的函式庫。輸入輸出的對象是以電腦作為主角: 輸入指的是「把資料給電腦」,輸出指的是「從電腦那邊取得資料」。 在這個系列的文章中,程式輸入指的都是從鍵盤輸入資料給電
C 語言的函式庫定義了許多好用的函式,在寫 C++ 的時候可以拿來用。這是因為 C++ 當初在設計的時候,就有刻意把 C 涵蓋進來。 基本用法 首先要導入 C 語言的標準函式庫: #include <cstdlib> 以 c 作為開頭表示它是 C 語言的函式庫,只是被我們拿來 C++ 的程式
<iostream> ​在之前的文章有提到過,<iostream> 是專門處理程式的輸入 (input) 以及輸出 (output) 的函式庫。輸入輸出的對象是以電腦作為主角: 輸入指的是「把資料給電腦」,輸出指的是「從電腦那邊取得資料」。 在這個系列的文章中,程式輸入指的都是從鍵盤輸入資料給電
你可能也想看
Thumbnail
1.加權指數與櫃買指數 週五的加權指數在非農就業數據開出來後,雖稍微低於預期,但指數仍向上噴出,在美股開盤後於21500形成一個爆量假突破後急轉直下,就一路收至最低。 台股方面走勢需觀察週一在斷頭潮出現後,週二或週三開始有無買單進場支撐,在沒有明確的反轉訊號形成前,小夥伴盡量不要貿然抄底,或是追空
Thumbnail
重點摘要: 1.9 月降息 2 碼、進一步暗示年內還有 50 bp 降息 2.SEP 上修失業率預期,但快速的降息速率將有助失業率觸頂 3.未來幾個月經濟數據將繼續轉弱,經濟復甦的時點或是 1Q25 季底附近
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Grass 是由一家去中心化人工智慧領域的初創公司Wynd Network,在2023年6月所推出的去中心化網路資源共享平台。
Thumbnail
從去年就開始火的CCD相機,美女、網紅現在幾乎人手一台,拍出來的照片張張都有氛圍感!CCD相機不僅記錄下每一個瞬間,更賦予與手機影像不同且難以言喻的深度和質感。今天就來推薦幾款CCD相機。【此篇文章內容引用自新識界】
期許未來的自己能幫助更多對英文恐懼或排斥的孩子看到更多這個世界裡頭的有趣與價值。為了達到這個目標,用心準備每一堂課,在課堂中好好陪伴每一位學生學習是現在的我能努力做好的事。
Thumbnail
論語裡孔子曾說過:「未知生,焉知死?」過了五十歲之後,我反而有一種「先知死,而後生」的體悟。 最近因為一些因素,對於「死亡」的歷程必須先行預習,所以連續看了兩部日本電影:「無痛離世」跟「山中靜夫的最後尊嚴」。同樣聚焦在癌症末期的主題,同樣超級寫實的演繹了病人在世間最後辛苦的時光,讓我可以先預習癌末
Thumbnail
透過Google Authenticator轉移帳戶的功能,可以一次性提取所有TOTP密鑰,加快整合TOTP到Bitwarden的過程。整合完成後,不論是輸入帳號密碼或是輸入TOTP認證碼,都只需要Bitwarden即可搞定,在安全性和方便性取得平衡。在方便性和安全性之間取得平衡,是資安永遠的課題。
Thumbnail
在另一次快速的截肢手術中,李斯頓雖然饒過病人的睪丸,卻意外切斷助理的兩根手指。後來病人與助理雙雙死於壞疽,而一名在旁觀看這場手術的人,看見李斯頓匆忙揮舞手術刀,刀子戳破了外套,還以為李斯頓被戳死,因此嚇得休克,一命嗚呼。在麻醉劑出現之前的年代,手術就是這麼危險。
Thumbnail
  為了未來就業穩定,目前打算以成為公股銀行行員的目標邁進!打算花半年至一年的時間考取Fit(金融基測),再慢慢考一些有的沒的法定考試(好痛苦...)   先說我報名證基會2023/7/7的紙筆考試,大概從2023/6/27開始準備,準備時長10天左右。但我不能說自己是非常認真準備的學生,主要原因是
Thumbnail
大綱: 1.股利的三大迷思 2.投資中第1~3級思考 3.大部分的人虧損的原因 4.兩個最有效率的投資策略 5.單筆投資與定期定額的差別。 6.長期投資成功的關鍵是什麼? 7.已實現和未實現報酬的差異。 8.股票賣出的三大理由。 9.投資必勝九大金律。 讀書心得分成兩篇,上篇的連結 本文PODCAS
Thumbnail
大綱: 1.適合誰閱讀 2.股市秤重機 3.風險管理的兩大誤區 4.長期投資的七大優勢 5.股利是雙面刃 【無痛致富】,去年10/26號上市。作者是佛里曼投資顧問團隊(Freeman Publications),總部位於英國倫敦,提供個人專業的投資理財顧問服務,將最複雜的投資策略以易於理解的語言傳達
Thumbnail
水晶洞功效: 水晶洞又稱作是風水石,裡面充滿漂亮的晶牙、水晶花,彼此能量互相震動凝聚磁場!能夠聚財納福、避邪擋煞、吉祥平安。且晶洞本身就是源源不絕的發電廠,可以幫其他水晶淨化、消磁。 迷你晶洞擺放在辦公桌: 在工作上有貴人幫助、專注辦公、防止小人陷害、被老闆讚許、加薪升官的機會! 迷你晶洞擺放在正財
Thumbnail
1.加權指數與櫃買指數 週五的加權指數在非農就業數據開出來後,雖稍微低於預期,但指數仍向上噴出,在美股開盤後於21500形成一個爆量假突破後急轉直下,就一路收至最低。 台股方面走勢需觀察週一在斷頭潮出現後,週二或週三開始有無買單進場支撐,在沒有明確的反轉訊號形成前,小夥伴盡量不要貿然抄底,或是追空
Thumbnail
重點摘要: 1.9 月降息 2 碼、進一步暗示年內還有 50 bp 降息 2.SEP 上修失業率預期,但快速的降息速率將有助失業率觸頂 3.未來幾個月經濟數據將繼續轉弱,經濟復甦的時點或是 1Q25 季底附近
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Grass 是由一家去中心化人工智慧領域的初創公司Wynd Network,在2023年6月所推出的去中心化網路資源共享平台。
Thumbnail
從去年就開始火的CCD相機,美女、網紅現在幾乎人手一台,拍出來的照片張張都有氛圍感!CCD相機不僅記錄下每一個瞬間,更賦予與手機影像不同且難以言喻的深度和質感。今天就來推薦幾款CCD相機。【此篇文章內容引用自新識界】
期許未來的自己能幫助更多對英文恐懼或排斥的孩子看到更多這個世界裡頭的有趣與價值。為了達到這個目標,用心準備每一堂課,在課堂中好好陪伴每一位學生學習是現在的我能努力做好的事。
Thumbnail
論語裡孔子曾說過:「未知生,焉知死?」過了五十歲之後,我反而有一種「先知死,而後生」的體悟。 最近因為一些因素,對於「死亡」的歷程必須先行預習,所以連續看了兩部日本電影:「無痛離世」跟「山中靜夫的最後尊嚴」。同樣聚焦在癌症末期的主題,同樣超級寫實的演繹了病人在世間最後辛苦的時光,讓我可以先預習癌末
Thumbnail
透過Google Authenticator轉移帳戶的功能,可以一次性提取所有TOTP密鑰,加快整合TOTP到Bitwarden的過程。整合完成後,不論是輸入帳號密碼或是輸入TOTP認證碼,都只需要Bitwarden即可搞定,在安全性和方便性取得平衡。在方便性和安全性之間取得平衡,是資安永遠的課題。
Thumbnail
在另一次快速的截肢手術中,李斯頓雖然饒過病人的睪丸,卻意外切斷助理的兩根手指。後來病人與助理雙雙死於壞疽,而一名在旁觀看這場手術的人,看見李斯頓匆忙揮舞手術刀,刀子戳破了外套,還以為李斯頓被戳死,因此嚇得休克,一命嗚呼。在麻醉劑出現之前的年代,手術就是這麼危險。
Thumbnail
  為了未來就業穩定,目前打算以成為公股銀行行員的目標邁進!打算花半年至一年的時間考取Fit(金融基測),再慢慢考一些有的沒的法定考試(好痛苦...)   先說我報名證基會2023/7/7的紙筆考試,大概從2023/6/27開始準備,準備時長10天左右。但我不能說自己是非常認真準備的學生,主要原因是
Thumbnail
大綱: 1.股利的三大迷思 2.投資中第1~3級思考 3.大部分的人虧損的原因 4.兩個最有效率的投資策略 5.單筆投資與定期定額的差別。 6.長期投資成功的關鍵是什麼? 7.已實現和未實現報酬的差異。 8.股票賣出的三大理由。 9.投資必勝九大金律。 讀書心得分成兩篇,上篇的連結 本文PODCAS
Thumbnail
大綱: 1.適合誰閱讀 2.股市秤重機 3.風險管理的兩大誤區 4.長期投資的七大優勢 5.股利是雙面刃 【無痛致富】,去年10/26號上市。作者是佛里曼投資顧問團隊(Freeman Publications),總部位於英國倫敦,提供個人專業的投資理財顧問服務,將最複雜的投資策略以易於理解的語言傳達
Thumbnail
水晶洞功效: 水晶洞又稱作是風水石,裡面充滿漂亮的晶牙、水晶花,彼此能量互相震動凝聚磁場!能夠聚財納福、避邪擋煞、吉祥平安。且晶洞本身就是源源不絕的發電廠,可以幫其他水晶淨化、消磁。 迷你晶洞擺放在辦公桌: 在工作上有貴人幫助、專注辦公、防止小人陷害、被老闆讚許、加薪升官的機會! 迷你晶洞擺放在正財