無痛入手 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
3會員
14內容數
程式設計 & 電腦系統 & 系統軟體
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
鏟薯員的窩 的其他內容
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) 的函式庫。輸入輸出的對象是以電腦作為主角: 輸入指的是「把資料給電腦」,輸出指的是「從電腦那邊取得資料」。 在這個系列的文章中,程式輸入指的都是從鍵盤輸入資料給電
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這篇內容,將會講解什麼是表達式(Expression),什麼是陳述式(Statement)。有了這些概念,各位會更容易理解,要如何設計程式碼。
Thumbnail
這篇內容,將會講解什麼是函式,以及與函式相關的知識。包括函式的簡介、Runtime Function、自訂函式、Script Function 腳本函式、Method 方法。
Thumbnail
分享一個猜數字的遊戲題目,給予提示讓玩家找出正確的四位數密碼。
Thumbnail
一、了解思維 二、大量體驗 三、拆解架構 四、找出樂趣
Thumbnail
探討正義想關主題的桌上解謎遊戲, 好玩卻也能引人省思
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這篇內容,將會講解什麼是表達式(Expression),什麼是陳述式(Statement)。有了這些概念,各位會更容易理解,要如何設計程式碼。
Thumbnail
這篇內容,將會講解什麼是函式,以及與函式相關的知識。包括函式的簡介、Runtime Function、自訂函式、Script Function 腳本函式、Method 方法。
Thumbnail
分享一個猜數字的遊戲題目,給予提示讓玩家找出正確的四位數密碼。
Thumbnail
一、了解思維 二、大量體驗 三、拆解架構 四、找出樂趣
Thumbnail
探討正義想關主題的桌上解謎遊戲, 好玩卻也能引人省思