vocus logo

方格子 vocus

無痛入手 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. 可以用 % 來表示"從最後一個數字繞回第一個數字"。




留言
avatar-img
鏟薯員的窩
9會員
14內容數
程式設計 & 電腦系統 & 系統軟體
鏟薯員的窩的其他內容
2024/05/05
C 語言的函式庫定義了許多好用的函式,在寫 C++ 的時候可以拿來用。這是因為 C++ 當初在設計的時候,就有刻意把 C 涵蓋進來。 基本用法 首先要導入 C 語言的標準函式庫: #include <cstdlib> 以 c 作為開頭表示它是 C 語言的函式庫,只是被我們拿來 C++ 的程式
Thumbnail
2024/05/05
C 語言的函式庫定義了許多好用的函式,在寫 C++ 的時候可以拿來用。這是因為 C++ 當初在設計的時候,就有刻意把 C 涵蓋進來。 基本用法 首先要導入 C 語言的標準函式庫: #include <cstdlib> 以 c 作為開頭表示它是 C 語言的函式庫,只是被我們拿來 C++ 的程式
Thumbnail
看更多
你可能也想看
Thumbnail
賽勒布倫尼科夫以流亡處境回望蘇聯電影導演帕拉贊諾夫的舞台作品,以十段寓言式殘篇,重新拼貼記憶、暴力與美學,並將審查、政治犯、戰爭陰影與「形式即政治」的劇場傳統推到台前。本文聚焦於《傳奇:帕拉贊諾夫的十段殘篇》的舞台美術、音樂與多重扮演策略,嘗試解析極權底下不可言說之事,將如何成為可被觀看的公共發聲。
Thumbnail
賽勒布倫尼科夫以流亡處境回望蘇聯電影導演帕拉贊諾夫的舞台作品,以十段寓言式殘篇,重新拼貼記憶、暴力與美學,並將審查、政治犯、戰爭陰影與「形式即政治」的劇場傳統推到台前。本文聚焦於《傳奇:帕拉贊諾夫的十段殘篇》的舞台美術、音樂與多重扮演策略,嘗試解析極權底下不可言說之事,將如何成為可被觀看的公共發聲。
Thumbnail
柏林劇團在 2026 北藝嚴選,再次帶來由布萊希特改編的經典劇目《三便士歌劇》(The Threepenny Opera),導演巴里・柯斯基以舞台結構與舞台調度,重新向「疏離」進行提問。本文將從觀眾慾望作為戲劇內核,藉由沉浸與疏離的辯證,解析此作如何再次照見觀眾自身的位置。
Thumbnail
柏林劇團在 2026 北藝嚴選,再次帶來由布萊希特改編的經典劇目《三便士歌劇》(The Threepenny Opera),導演巴里・柯斯基以舞台結構與舞台調度,重新向「疏離」進行提問。本文將從觀眾慾望作為戲劇內核,藉由沉浸與疏離的辯證,解析此作如何再次照見觀眾自身的位置。
Thumbnail
本文深入解析臺灣劇團「晃晃跨幅町」對易卜生經典劇作《海妲.蓋柏樂》的詮釋,從劇本歷史、聲響與舞臺設計,到演員的主體創作方法,探討此版本如何讓經典劇作在當代劇場語境下煥發新生,滿足現代觀眾的觀看慾望。
Thumbnail
本文深入解析臺灣劇團「晃晃跨幅町」對易卜生經典劇作《海妲.蓋柏樂》的詮釋,從劇本歷史、聲響與舞臺設計,到演員的主體創作方法,探討此版本如何讓經典劇作在當代劇場語境下煥發新生,滿足現代觀眾的觀看慾望。
Thumbnail
《轉轉生》為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,融合舞蹈、音樂、時尚和視覺藝術,透過身體、服裝與群舞結構,回應殖民歷史、城市經驗與祖靈記憶的交錯。本文將從服裝設計、身體語彙與「輪迴」的「誕生—死亡—重生」結構出發,分析《轉轉生》如何以當代目光,形塑去殖民視角的奈及利亞歷史。
Thumbnail
《轉轉生》為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,融合舞蹈、音樂、時尚和視覺藝術,透過身體、服裝與群舞結構,回應殖民歷史、城市經驗與祖靈記憶的交錯。本文將從服裝設計、身體語彙與「輪迴」的「誕生—死亡—重生」結構出發,分析《轉轉生》如何以當代目光,形塑去殖民視角的奈及利亞歷史。
Thumbnail
這篇內容,將會講解什麼是運算子,以及與運算子相關的知識。包括運算子的簡介、賦值運算子、算術運算子、遞增/遞減、比較運算子、邏輯運算子。
Thumbnail
這篇內容,將會講解什麼是運算子,以及與運算子相關的知識。包括運算子的簡介、賦值運算子、算術運算子、遞增/遞減、比較運算子、邏輯運算子。
Thumbnail
這篇內容,將會講解什麼是變數,以及與變數相關的知識。包括變數、資料型態、變數賦值、變數的命名規則、變數的作用區域、變數的可重複性、內建變數。
Thumbnail
這篇內容,將會講解什麼是變數,以及與變數相關的知識。包括變數、資料型態、變數賦值、變數的命名規則、變數的作用區域、變數的可重複性、內建變數。
Thumbnail
這篇內容,將透過實戰教學,來講解「滑鼠點方塊」的程式碼。包括如何測試遊戲、座標系統、自訂參數和內建參數、if else、and、遊戲的邏輯設計、程式碼解析。
Thumbnail
這篇內容,將透過實戰教學,來講解「滑鼠點方塊」的程式碼。包括如何測試遊戲、座標系統、自訂參數和內建參數、if else、and、遊戲的邏輯設計、程式碼解析。
Thumbnail
高中數學主題練習—對數方程式
Thumbnail
高中數學主題練習—對數方程式
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News