C 語言初學教材 - 第三章 簡化巢狀的 if-else

巢狀的 if-else 陳述雖然很好用,但是太多層容易讓程式變得不好理解。雖然在我們的猜數字遊戲中巢狀的 if-else 陳述不致於有閱讀理解的困擾,我們在這裡仍是另一個以狀態控制的版本,說明如何簡化巢狀的 if-else 陳述。



目前我們把結果只用一種狀態記錄,其實可以依三層的巢狀 if-else 陳述詳細解析成三種狀態,分別是記錄答對或對錯的狀態、大於答案或小於答案的狀態、差值超過 5 或小於 5 的狀態。


因此,我們宣告三個列舉型態來分別記入這些狀態,全部的程式碼如下
#include <stdio.h>
#include <time.h>
#include <math.h>

enum RW {RIGHT = 1, WRONG};
enum BS {BIG = 1, SMALL};
enum DI {FOUR = 1, FIVE}; 

int main(void)
{
    int answer = time(NULL);
    int guess;
    int diff;
    int STATE_RW = 0;
    int STATE_BS = 0;
    int STATE_DI = 0;
    
    answer %= 25;
    if (answer == 0) {
        answer = 25;
    }
    
    printf("請猜一個數字 1 到 25: ");
    scanf("%d", &guess);
    diff = guess - answer;
    diff = (int) fabs(diff);
    
    if (guess == answer) {
        STATE_RW = RIGHT;
    }
    else {
        STATE_RW = WRONG;
    }
    
    if (answer > guess) {
        STATE_BS = SMALL;
    }
    else {
        STATE_BS = BIG;
    }
    
    if (diff > 5) {
        STATE_DI = FIVE;
    }
    else {
        STATE_DI = FOUR;
    }
    
    if (STATE_RW == RIGHT) {
        printf("猜對囉!\n");
    }
    else if (STATE_BS == BIG && STATE_DI == FIVE) {
        printf("猜的數字比答案大....還很遠,再加把勁!\n");
    }
    else if (STATE_BS == BIG && STATE_DI == FOUR) {
        printf("猜的數字比答案大....不錯喔!很接近了\n");
    }
    else if (STATE_BS == SMALL && STATE_DI == FIVE) {
        printf("猜的數字比答案小....還很遠,再加把勁!\n");
    }
    else if (STATE_BS == SMALL && STATE_DI == FOUR) {
        printf("猜的數字比答案小....不錯喔!很接近了\n");
    }
    else {
        printf("猜錯囉!\n");
    }
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:gn6.c
    功能:簡單的猜數字遊戲
    作者:張凱慶
    時間:西元2010年7月 */ 


因此,第 28 行到第 47 行為三個單一的 if-else 陳述,依據條件判斷設定狀態。第 52 行、第 55 行、第 58 行、第 61 行的狀態判斷,我們都用邏輯運算子 && 將兩種狀態做且運算,這是猜錯的時候,所以如果兩種狀態都相符,程式才會顯示該訊息。


請自行編譯執行,結果會是相同的。


問題與討論
  1. 為什麼太多層的巢狀 if-else 陳述會讓程式變得不好理解?
  2. 把狀態拆成用三個變數來儲存,有什麼優點跟缺點?
  3. 邏輯運算子有哪些?
  4. if 陳述中利用邏輯運算子有什麼方便的地方?




沒有留言: